查找集合中具有给定属性的所有对象

Jak*_*ake 85 java collections

我有一些复杂的物体,比如猫,它有许多属性,如年龄,最喜欢的猫粮等.

一堆Cats存储在Java Collection中,我需要找到所有3岁的猫,或者那些喜欢的猫粮是Whiskas的猫.当然,我可以编写一个自定义方法来查找具有特定属性的Cats,但这对于许多属性来说很麻烦; 这有什么通用的方法吗?

Bri*_*ley 62

尝试commons集合API:

List<Cat> bigList = ....; // master list

Collection<Cat> smallList = CollectionUtils.select(bigList, new Predicate() {
    public boolean evaluate(Object o) {
        Cat c = (Cat)o;
        return c.getFavoriteFood().equals("Wiskas") 
            && c.getWhateverElse().equals(Something);
    }
});
Run Code Online (Sandbox Code Playgroud)

当然,您不必每次都使用匿名类,您可以Predicate为常用搜索创建接口的实现.

  • 请注意,在比较字符串时,必须使用.equals方法,否则您要比较内存引用位置,请参阅:http://stackoverflow.com/questions/767372/java-string-equals-versus (3认同)

小智 55

我一直在使用Google Collections(现在称为Guava)来解决这类问题.有一个名为Iterables的类可以将名为Predicate的接口作为一个非常有用的方法的参数.

Cat theOne = Iterables.find(cats, new Predicate<Cat>() {
    public boolean apply(Cat arg) { return arg.age() == 3; }
});
Run Code Online (Sandbox Code Playgroud)

检查它在这里!


Adr*_*hum 53

使用Java 8 lambda表达式,您可以执行类似的操作

cats.stream()
    .filter( c -> c.getAge() == 3 && c.getFavoriteFood() == WHISKAS )
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

在概念上与Guava Predicate方法相同,但使用lambda看起来更清晰

可能不是OP的有效答案,但值得注意的是有相似需求的人.:)


Dav*_*d Z 45

您可以编写一个方法,该方法接受定义check(Cat)方法的接口实例,其中该方法可以使用您想要的任何属性检查来实现.

更好的是,让它通用:

public interface Checker<T> {
    public boolean check(T obj);
}

public class CatChecker implements Checker<Cat> {
    public boolean check(Cat cat) {
        return (cat.age == 3); // or whatever, implement your comparison here
    }
}

// put this in some class
public static <T> Collection<T> findAll(Collection<T> coll, Checker<T> chk) {
    LinkedList<T> l = new LinkedList<T>();
    for (T obj : coll) {
         if (chk.check(obj))
             l.add(obj);
    }
    return l;
}
Run Code Online (Sandbox Code Playgroud)

当然,就像其他人说的那样,这就是关系数据库的用途......

  • (1)很高兴知道它是如何实现的(2)通常不值得为这样一个简单的方法引入一个额外的库. (15认同)
  • 怎么了?没有人听说过Commons Collections,Google Collections或Hamcrest系列吗?我无法相信这有很多赞成或者被接受. (14认同)
  • 我没有使用Comparator的原因是Comparator应该对集合强加一个总排序,而我们需要的只是对某些条件的布尔测试.正在检查的财产可能没有任何有意义的订单. (6认同)
  • 我会说同样的,但建议使用Comparator而不是自定义界面. (4认同)
  • @David:参数+1(+1).看了这一千次:导入额外的lib,额外的jar,一个20行的单个类的额外回购.保持比例感! (3认同)

fly*_*ire 11

我建议使用Jxpath,它允许你对对象图进行查询,就好像它在xpath那样

JXPathContext.newContext(cats).
     getValue("//*[@drinks='milk']")
Run Code Online (Sandbox Code Playgroud)

  • +1有趣(即使XPath不是学习有效使用的最简单方法) (2认同)

小智 5

再次使用commons集合API:当您单独实现谓词时,您将获得"检查器"类型代码: -

public class CatPredicate implements Predicate {

    private int age; 


    public CatPredicate(int age) {
        super();
        this.age = age;
    }


    @Override
    public boolean evaluate(Object o) {
        Cat c (Cat)o;
        return c.getAge()==this.age;
    }

}
Run Code Online (Sandbox Code Playgroud)

被用作: -

CollectionUtils.filter(catCollectionToFilter, new CatPredicate(3))
Run Code Online (Sandbox Code Playgroud)