给定起始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有办法解决这个问题吗?
答案 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());
}
});