我有一些复杂的物体,比如猫,它有许多属性,如年龄,最喜欢的猫粮等.
一堆Cats存储在Java Collection中,我需要找到所有3岁的猫,或者那些喜欢的猫粮是Whiskas的猫.当然,我可以编写一个自定义方法来查找具有特定属性的Cats,但这对于许多属性来说很麻烦; 这有什么通用的方法吗?
尝试commons集合API:
ListbigList = ....; // master list Collection smallList = CollectionUtils.select(bigList, new Predicate() { public boolean evaluate(Object o) { Cat c = (Cat)o; return c.getFavoriteFood().equals("Wiskas") && c.getWhateverElse().equals(Something); } });
当然,您不必每次都使用匿名类,您可以Predicate
为常用搜索创建接口的实现.
我一直在使用Google Collections(现在称为Guava)来解决这类问题.有一个名为Iterables的类可以将名为Predicate的接口作为一个非常有用的方法的参数.
Cat theOne = Iterables.find(cats, new Predicate() { public boolean apply(Cat arg) { return arg.age() == 3; } });
检查它在这里!
使用Java 8 lambda表达式,您可以执行类似的操作
cats.stream() .filter( c -> c.getAge() == 3 && c.getFavoriteFood() == WHISKAS ) .collect(Collectors.toList());
在概念上与Guava Predicate方法相同,但使用lambda看起来更清晰
可能不是OP的有效答案,但值得注意的是有相似需求的人.:)
您可以编写一个方法,该方法接受定义check(Cat)
方法的接口实例,其中该方法可以使用您想要的任何属性检查来实现.
更好的是,让它通用:
public interface Checker{ public boolean check(T obj); } public class CatChecker implements Checker { public boolean check(Cat cat) { return (cat.age == 3); // or whatever, implement your comparison here } } // put this in some class public static Collection findAll(Collection coll, Checker chk) { LinkedList l = new LinkedList (); for (T obj : coll) { if (chk.check(obj)) l.add(obj); } return l; }
当然,就像其他人说的那样,这就是关系数据库的用途......
我建议使用Jxpath,它允许你对对象图进行查询,就好像它在xpath那样
JXPathContext.newContext(cats). getValue("//*[@drinks='milk']")
再次使用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; } }
被用作: -
CollectionUtils.filter(catCollectionToFilter, new CatPredicate(3))