最简洁的方法来确定列表<foo>包含元素,其中Foo.getBar()=“Baz”?</foo>

时间:2010-09-14 20:46:34

标签: java search collections

给定起始List<Foo>,确定具有属性Foo(由bar访问)的getBar()元素的值是否最简洁的方法是什么? Baz“?我能想出的最佳答案是线性搜索:

List<Foo> listFoo;
for(Foo f:listFoo) {
    if(f.getBar().equals("Baz")) {
        // contains value
    }
}

我查看了HashSet,但似乎没有办法使用contains()而没有先实例化Foo传入(在我的情况下,Foo创建起来很昂贵)。我还查看了HashMap,但似乎没有一种方法可以在没有循环遍历列表的情况下填充,并一次添加一个Foo元素。这个列表很小,所以我并不担心性能,因为我清晰的代码。

我的大多数开发经验都是使用C#和Python,因此我习惯于更简洁的语句,如:

// C#
List<Foo> listFoo;
bool contains = listFoo.Count(f => f.getBar=="Baz")>0;

# Python
# list_foo = [Foo(), ...]
contains = "Baz" in (f.bar for f in list_foo)

Java有办法解决这个问题吗?

4 个答案:

答案 0 :(得分:4)

Java本身并没有。 另外(就像fyi一样)f.getBar ==“Baz”不能用于字符串比较,因为字符串是对象。然后使用==运算符实际比较对象(它们不相等,因为它们不在同一个内存位置并且是单个对象)。 equals方法是进行对象比较的最佳方法。特别是最好使用“Baz”.equals(f.getBar()),因为这样可以避免令人讨厌的NullPointerExceptions。

现在来解决你的问题。我可以想办法,但它可能取决于父对象Foo与子对象Bar的关系。它会永远是一对一的吗?换句话说,“Baz”的Bar值是否可以与多个Foo对象相关联?

我要去的地方是你之前谈过的HashMap对象。这是因为有方法containsKey和containsValue。由于HashMap允许与不同键关联的重复值,因此可以将Bar作为值,将Foo作为键。然后只需使用myHashMap.containsValue(“Baz”)来确定它是否在“列表”中。既然如此,那么你总是可以检索与之相关的键(Foos)。

答案 1 :(得分:4)

Java不支持闭包(但是),因此您的解决方案是最短的解决方案之一。另一种方法是使用,例如google-collections Iterable的封闭式Predicate

boolean contains = Iterables.any(iterableCollection, new Predicate<Foo>() {
    @Override
    public boolean apply(Foo foo) {
       return foo != null && foo.getBar().equals("Baz");
    }
}

答案 2 :(得分:3)

您只能在Java中模拟它,例如使用“功能对象”。但是,由于这在Java中有点笨拙和冗长,如果你有几个不同的谓词来从列表中选择元素,那么这是值得的:

interface Predicate<T> {
  boolean isTrueFor(T item);
}

Foo getFirst(List<Foo> listFoo, Predicate<Foo> pred) {
  for(Foo f:listFoo) {
    if(pred.isTrueFor(f)) {
      return f;
    }
  }
}

class FooPredicateBar implements Predicate<Foo> {
  private final String expected;
  FooPredicateBar(String expected) {
    this.expected = expected;
  }
  public boolean isTrueFor(Foo item) {
    return item != null && expected.equals(item.getBar());
  }
}
...
List<Foo> listFoo;
Foo theItem = getFirst(listFoo, new FooPredicateBar("Baz"));

答案 3 :(得分:2)

您也可以使用Apache Commons CollectionUtils

 boolean contains = CollectionUtils.exists(listFoo, new Predicate() {
     public boolean evaluate(Object input) {
         return "Baz".equals(((Foo)input).getBar());
     }
 });