Finding all objects that have a given property inside a collection
我有一些复杂的物体,比如一只猫,它有很多特性,比如年龄,最喜欢的猫食等等。
一组猫被储存在一个Java集合中,我需要找到所有3岁的猫,或者那些最喜欢猫咪食物的猫咪。当然,我可以编写一个自定义方法来查找具有特定属性的cats,但是对于许多属性,这会变得很麻烦;是否有一些通用的方法来执行此操作?
尝试Commons Collections API:
1 2 3 4 5 6 7 8 9 | 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); } }); |
当然,您不必每次都使用匿名类,您可以为常用的搜索创建
我一直在使用谷歌收藏(现在称为guava)来解决这类问题。有一个名为iterables的类,它可以将名为predicate的接口作为方法的参数,这真的很有用。
1 2 3 | Cat theOne = Iterables.find(cats, new Predicate<Cat>() { public boolean apply(Cat arg) { return arg.age() == 3; } }); |
在这里检查一下!
一个Java的东西你可以做8表达兰布达样
1 2 3 | cats.stream() .filter( c -> c.getAge() == 3 && c.getFavoriteFood() == WHISKAS ) .collect(Collectors.toList()); |
conceptually 51%为番石榴一样的方法,但它看起来很清洁,λ
答案可能是困难的,但一个有效的价值和手术需要注意与人相似。:)
您可以编写一个方法,该方法采用定义
更好的是,使其通用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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; } |
当然,正如其他人所说,这就是关系数据库的用途……
我建议使用jxpath,它允许您像使用xpath一样对对象图进行查询。
1 2 | JXPathContext.newContext(cats). getValue("//*[@drinks='milk']") |
同样,使用Commons Collections API:单独实现谓词时,将获得"checker"类型代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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; } } |
用作:
1 | CollectionUtils.filter(catCollectionToFilter, new CatPredicate(3)) |
你可以使用lambdaj。这些琐碎的东西一样,是非常光滑的语法:
1 2 3 4 5 6 | Person me = new Person("Mario","Fusco", 35); Person luca = new Person("Luca","Marrocco", 29); Person biagio = new Person("Biagio","Beatrice", 39); Person celestino = new Person("Celestino","Bellone", 29); List<Person> meAndMyFriends = asList(me, luca, biagio, celestino); List<Person> oldFriends = filter(having(on(Person.class).getAge(), greaterThan(30)), meAndMyFriends); |
你可以做更复杂的事情。它使用的hamcrest匹配器。我想认为这不是Java的风格,但它的乐趣,这让盖伊Java知识的双位的功能编程。有一个看的源代码,所以它不是科幻小说。
只是你有没有其他的答案3到这个问题,使用番石榴,但没有答案的问题。提问者希望安切洛蒂说"嘿猫找到一个匹配的所有物业,例如时代3。一只
1 2 3 4 5 6 | Iterable<Cat> matches = Iterables.filter(cats, new Predicate<Cat>() { @Override public boolean apply(Cat input) { return input.getAge() == 3; } }); |
使用共享的集合:
1 2 3 | EqualPredicate nameEqlPredicate = new EqualPredicate(3); BeanPredicate beanPredicate = new BeanPredicate("age", nameEqlPredicate); return CollectionUtils.filter(cats, beanPredicate); |
使用谷歌的番石榴。
1 2 3 4 5 6 7 | final int lastSeq = myCollections.size(); Clazz target = Iterables.find(myCollections, new Predicate<Clazz>() { @Override public boolean apply(@Nullable Clazz input) { return input.getSeq() == lastSeq; } }); |
我想使用这个方法。
您可以在ApacheCommons项目中尝试一些通用代码。collections子项目提供用于查找与特定谓词匹配的对象以及大量谓词(equals、null、instanceof等)的代码。beanutils子项目允许您创建用于测试bean属性的谓词。
使用CollectionUtils类在集合内搜索。有一些方法可以解决这个问题,但请特别检查select()方法。使用以下类来构造谓词,或编写自己的:谓词、谓词实用程序、beanpredicate。
这有时有点麻烦,但至少是通用的!-)
您可以使用josql之类的工具,并针对集合编写"sql":http://josql.sourceforge.net/
这听起来像是你想要的,还有一个好处就是能够进行更复杂的查询。
听起来很像在.NET中使用Linq
虽然Java还没有"真正的"LINQ实现,但您可能需要查看QuaEIR,它可以很容易地描述您所描述的内容。
基于谓词、过滤器和自定义迭代器/比较器的解决方案很好,但它们不提供类似于数据库索引的解决方案。例如:我想以不同的方式搜索猫的集合:按性别、年龄和年龄,所以它看起来像两个索引:1)[性别,年龄]2)[年龄]。该索引访问的值可以散列,以实现快速查找,而不必迭代整个集合。有没有这样的解决方案?
一个很普通的问题,我没有在这里是我的代码谷歌收藏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | public class FindByIdPredicate implements Predicate<IDObject> { private Long entityId; public FindByIdPredicate(final Long entityId) { this.entityId = entityId; } @Override public boolean apply(final IDObject input) { return input.getId().equals(this.entityId); } /** * Pass in the Collection * @param Collection * @return IdObject if present or null */ public IDObject getEntity(final Collection<? extends IDObject> collection) { for (IDObject idObject : collection) { if (this.apply(idObject)) { return idObject; } } return null; } /** * @param Set * @return IdObject if present or null */ @SuppressWarnings("unchecked") public <T> T getEntity(final Set<? extends IDObject> set) { for (IDObject idObject : set) { if (this.apply(idObject)) { return (T) idObject; } } return null; } |
}
希望这帮助
有一个非常强大的搜索能力,番石榴,当谈到搜索型问题。例如,如果你正在寻找一个对象区域的基于它的属性,你可以考虑:
1 2 3 4 5 6 | Iterables.tryFind(listOfCats, new Predicate<Cat>(){ @Override boolean apply(@Nullable Cat input) { return"tom".equalsIgnoreCase(input.name()); } }).or(new Cat("Tom")); |
在案件的是,它是不可能在listofcats汤姆猫,它会返回,从而允许你避免NPE。
jfilter http:/ / / / / P code.google.com jfilter套房您的需求。
jfilter是一个简单的和高性能的开源图书馆查询收集的Java豆。
关键特征
- 支持的集合(java.util.collection,java.util.map属性和数组)。
- 支持收集收集在任何深度。
- 内部支持的查询。
- parameterized支持查询。
- CAN过滤器1万个记录在100毫秒。
- 滤波器(查询)是没有简单的JSON格式,这样mangodb查询。以下是一些例子。
- { {"身份证":"为乐":"10"}
- 在对象ID是小于等于10个物业。
- {:{"ID"的"元":["0"、"1"] }
- 在对象标识物业是0或100。
- {"lineitems":"lineamount { }":"1"
- 在收集的财产型lineitems parameterized安切洛蒂lineamount equals to 1。
- {"美元"和"身份"::{"0 n
你可以从一个搜索列表项的功能如下。祝你好运!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19int _searchList(List<T> list,T item) {
int idx = -1;
idx = Collections.binarySearch(list,item,
new Comparator<T>() {
public int compare(Titm1,
Titm2) {
// key1
if (itm1.key1.compareTo(itm2.key1) != 0) {
return itm1.key2.compareTo(itm2.key2);
}
// key2
return itm1.key2
.compareTo(itm2.key2);
}
});
return idx;}
下面是搜索者类的一个想法,您可以用您想要查找的特定值参数化搜索者类。
您还可以进一步将属性的名称存储在一个具有所需值的映射中。在这种情况下,您将使用对cat类的反射来调用给定属性名的适当方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27public class CatSearcher {
private Integer ageToFind = null;
private String foodToFind = null;
public CatSearcher( Integer age, String food ) {
this.ageToFind = age;
this.foodToFind = food;
}
private boolean isMatch(Cat cat) {
if ( this.ageToFind != null && !cat.getAge().equals(this.ageToFind) ) {
return false;
}
if ( this.foodToFind != null && !cat.getFood().equals(this.foodToFind) {
return false;
}
return true;
}
public Collection<Cat> search( Collection<Cat> listToSearch ) {
// details left to the imagination, but basically iterate over
// the input list, call isMatch on each element, and if true
// add it to a local collection which is returned at the end.
}
}您可以将这些对象存储在数据库中。如果您不想让一个完整的数据库服务器产生开销,您可以使用一个嵌入的服务器,比如hsqldb。然后您可以使用Hibernate或Beankeeper(使用起来更简单)或其他ORM将对象映射到表。您一直在使用OO模型,并从数据库中获得高级存储和查询的好处。
- { {"身份证":"为乐":"10"}