将java中的两个自定义对象与可空字段进行比较

时间:2017-03-16 12:03:54

标签: java performance if-statement collections null

我有Collection<A>

class A {
    String name;
    Long id;
}

现在我有UI屏幕,我可以提供姓名&amp; id值以匹配此集合并显示结果。

现在我有3个标准:

  1. 仅提供ID:显示所有与Id匹配的记录,尽管名称为空
  2. 仅限姓名
  3. 姓名和身份证。
  4. 我可以通过三次if检查来检查基于UI字段的空检查,但我不想让if-else阻止,因为如果我有多个UI文件,那么就会很忙嵌套if-else检查。

    请在java 7中建议更好的方法。

3 个答案:

答案 0 :(得分:0)

您可以提供一些用于过滤集合的谓词。由于java.util.function.Predicate仅添加了Java 8,因此您需要自行推送或使用Google Guava等库。

使用它可以传递要在过滤器中使用的谓词:

Collection<Predicate<A>> predicates = ...;//you get them from your UI
Collection<A> filtered = Collections2.filter( originalCollection, Preciates.and( predicates ) );

谓词可能如下所示:

class ANamePredicate implements Predicate<A> {
  private String name; 

  public ANamePredicate( String n) { 
    name = n;
  }     

  boolean apply(@Nullable A input) { 
    //if one or both could be null, add handling for that
    return input.name.equals(n);
  }

  //implement equals(...) as well
}

当然你也可以使用匿名类,但是你可能想要提供一个抽象基类来消除总是实现equals()的要求:

abstract class AbstractPredicate<T> implements Predicate<T> {
  public boolean equals( Object o) { 
    //simplified, you might have to provide a better implementation, e.g. you want to provide a set of predicates
    return false;
  }
}

然后在需要时创建谓词集合:

Collection<Predicate<A>> predicates = new LinkedList<>();
predicates.add( new AbstractPredicate<A>() {
   boolean apply(A input) { 
    return "Skabdus".equals(input.name);
   }
} );
predicates.add( new AbstractPredicate<A>() {
   boolean apply(A input) { 
    return input.id == 1;
   }
} );

答案 1 :(得分:0)

您可以将装饰器模式与表达式一起使用。原则是要有一个接口,每个“标准”将实现(使用一种方法:eval),并区分终端运营商终端运营商

你有一个 NameIsSet 类,一个 IdIsSet 类作为终端操作符(或者如果你将来有其他实现,则为其他类),并且逻辑表达式为非终端运营商:,......

然后,您应该以这种方式使用模式:

tableView

如果要为每种情况设置特定行为,可以创建这些谓词的List,并设置一个方法,如果谓词为true,则调用该方法:

Predicate predicate = new And(new IdIsSet("id"), new Not(new NameIsSet("name")));
if(predicate.eval()){
// Do something
}

以下是And class和NameIsSet类的示例:

for(Predicate predicate: predicateList){
    if(predicate.eval()) {
       predicate.execute();
       //break if only one case is accepted
    }
}

在此实现中,您必须事先创建所有谓词,将它们添加到列表中并为每个谓词设置execute()方法。

希望这对你有用。

答案 2 :(得分:0)

您的if声明不需要嵌套。例如,您可以这样做:

static boolean matches(A candidate, A pattern) {
    if (pattern.name != null && !candidate.name.equals(pattern.name))
        return false;
    if (pattern.id != null && !candidate.id.equals(pattern.id))
        return false;
    return true;
}

这可以按任意数量的字段以1:1的比例缩放。 (您可以在那里使用candidate.id != pattern.id,但我使用equals来保持一致性。)

如果您有数十个字段,并且不想单独命名,则可以使用反射并使用单个for循环处理所有字段:

static boolean matches(A candidate, A pattern) throws IllegalAccessException {
    for (Field fld : A.class.getDeclaredFields()) {
        Object c = fld.get(candidate);
        Object p = fld.get(pattern);
        if (p != null && !c.equals(p))
            return false;
    }
    return true;
}