我想检查一个列表是否包含一个对象,该对象具有具有特定值的字段。现在,我可以使用循环来遍历和检查,但我很好奇是否有更高效的代码。

类似的;

if(list.contains(new Object().setName("John"))){
    //Do some stuff
}

我知道上面的代码没有做任何事情,它只是粗略地演示了我想要实现的目标。

另外,澄清一下,我不想使用简单循环的原因是,这段代码将进入一个循环,这个循环在一个循环中,而这个循环又在一个循环中。为了可读性,我不想一直在这些循环中添加循环。所以我想知道是否有什么简单的替代方案。


当前回答

如果您需要执行此List。重复包含(字段值等于x的对象),一个简单而有效的解决方案是:

List<field obj type> fieldOfInterestValues = new ArrayList<field obj type>;
for(Object obj : List) {
    fieldOfInterestValues.add(obj.getFieldOfInterest());
}

然后是列表。contains(字段值等于x的对象)将与fieldOfInterestValues.contains(x)具有相同的结果;

其他回答

包含在内部使用等号的方法。因此,您需要根据需要重写类的equals方法。

顺便说一句,这看起来语法不正确:

new Object().setName("John")

Eclipse集合

如果您正在使用Eclipse Collections,则可以使用anyssatisfy()方法。如果可能的话,在ListAdapter中调整列表或将列表更改为ListIterable。

ListIterable<MyObject> list = ...;

boolean result =
    list.anySatisfy(myObject -> myObject.getName().equals("John"));

如果要经常执行这样的操作,最好提取一个方法来回答该类型是否具有该属性。

public class MyObject
{
    private final String name;

    public MyObject(String name)
    {
        this.name = name;
    }

    public boolean named(String name)
    {
        return Objects.equals(this.name, name);
    }
}

您可以使用替代形式anySatisfyWith()和方法引用。

boolean result = list.anySatisfyWith(MyObject::named, "John");

如果不能将List更改为ListIterable,下面是如何使用ListAdapter。

boolean result = 
    ListAdapter.adapt(list).anySatisfyWith(MyObject::named, "John");

注意:我是Eclipse集合的提交者。

谷歌番石榴

如果您正在使用Guava,您可以采用功能方法并执行以下操作

FluentIterable.from(list).find(new Predicate<MyObject>() {
   public boolean apply(MyObject input) {
      return "John".equals(input.getName());
   }
}).Any();

看起来有点啰嗦。但是谓词是一个对象,您可以为不同的搜索提供不同的变体。注意库本身是如何分离集合的迭代和希望应用的函数的。您不必为特定的行为重写equals()。

如下面所述,Java 8及以后版本中内置的Java .util. stream框架提供了类似的功能。

Map

你可以创建一个Hashmap<String, Object>,使用其中一个值作为键,然后查看yourHashMap.keySet().contains(yourValue)是否返回true。

谓词

如果你不使用Java 8,或者不使用为处理集合提供更多功能的库,你可以实现一些比你的解决方案更可重用的东西。

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

    static class CollectionUtil{

        public static <T> T find(final Collection<T> collection,final  Predicate<T> predicate){
            for (T item : collection){
                if (predicate.contains(item)){
                    return item;
                }
            }
            return null;
        }
    // and many more methods to deal with collection    
    }

我使用类似的东西,我有谓词接口,我把它的实现传递给我的util类。

用我的方式做这件事有什么好处?有一个方法可以处理任何类型集合中的搜索。如果你想通过不同的字段进行搜索,你不必创建单独的方法。你所需要做的就是提供不同的谓词,一旦它不再有用/就可以销毁

如果你想使用它,你所需要做的就是调用方法并定义你的谓词

CollectionUtil.find(list, new Predicate<MyObject>{
    public boolean contains(T item){
        return "John".equals(item.getName());
     }
});