Java 在集合中查找具有给定属性的所有对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/587404/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Finding all objects that have a given property inside a collection
提问by Jake
I have some complicated object, such as a Cat, which has many properties, such as age, favorite cat food, and so forth.
我有一些复杂的对象,例如 Cat,它具有许多属性,例如年龄、最喜欢的猫食等。
A bunch of Cats are stored in a Java Collection, and I need to find all the Cats that are aged 3, or those whose favorite cat food is Whiskas. Surely, I can write a custom method that finds those Cats with a specific property, but this gets cumbersome with many properties; is there some generic way of doing this?
一堆猫存储在 Java 集合中,我需要找到所有 3 岁的猫,或者最喜欢猫食是 Whiskas 的猫。当然,我可以编写一个自定义方法来查找具有特定属性的 Cats,但是这对于许多属性来说变得很麻烦;有没有一些通用的方法来做到这一点?
采纳答案by David Z
You could write a method that takes an instance of an interface which defines a check(Cat)
method, where that method can be implemented with whatever property-checking you want.
您可以编写一个方法,该方法采用定义check(Cat)
方法的接口实例,该方法可以通过您想要的任何属性检查来实现。
Better yet, make it generic:
更好的是,让它通用:
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;
}
Of course, like other people are saying, this is what relational databases were made for...
当然,就像其他人所说的,这就是关系数据库的用途……
回答by Cesar
You could store those objects on a database. If you don't want the overhead of a full blown database server you can use an embedded one like HSQLDB. Then you can use Hibernate or BeanKeeper (simpler to use) or other ORM to map objects to tables. You keep using the OO model and get the advanced storage and querying benefits from a database.
您可以将这些对象存储在数据库中。如果你不想要一个完整的数据库服务器的开销,你可以使用像 HSQLDB 这样的嵌入式服务器。然后你可以使用 Hibernate 或 BeanKeeper(使用更简单)或其他 ORM 将对象映射到表。您继续使用 OO 模型并从数据库中获得高级存储和查询优势。
回答by Eric Petroelje
回答by duwanis
You can use something like JoSQL, and write 'SQL' against your collections: http://josql.sourceforge.net/
您可以使用 JoSQL 之类的东西,并针对您的集合编写“SQL”:http://josql.sourceforge.net/
Which sounds like what you want, with the added benefit of being able to do more complicated queries.
这听起来像您想要的,还有能够进行更复杂查询的额外好处。
回答by Rich Dougherty
You could try some of the generic code in the Apache Commons project. The Collectionssubproject provides code for finding objects that match a particular Predicate, as well as a large number of predicates (equals, null, instanceof, etc). The BeanUtilssubproject allows you to make predicates that test properties of beans.
您可以尝试 Apache Commons 项目中的一些通用代码。的类别子项目提供代码查找匹配特定谓词,以及大量的谓词(等号,NULL,的instanceof等)的对象。该BeanUtils的子项目使您可以断言豆类的试验性质。
Use the CollectionUtilsclass to search within a collection. There are a few methods for this, but check out the select() method, in particular. Use the following classes to construct predicates, or write your own: Predicate, PredicateUtils, BeanPredicate.
使用CollectionUtils类在集合中搜索。有几种方法可以做到这一点,但请特别查看 select() 方法。使用以下类来构造谓词,或编写您自己的类:Predicate、PredicateUtils、BeanPredicate。
This is all sometimes a bit cumbersome, but at least it's generic! :-)
这有时有点麻烦,但至少它是通用的!:-)
回答by Dave Costa
Here's an idea for a searcher class you could parameterize with the specific values you want to look for.
这是一个搜索器类的想法,您可以使用要查找的特定值进行参数化。
You could go further and store the names of the properties as well, probably in a Map with the desired values. In this case you would use reflection on the Cat class to call the appropriate methods given the property names.
您还可以进一步存储属性的名称,可能存储在具有所需值的 Map 中。在这种情况下,您将使用 Cat 类上的反射来调用给定属性名称的适当方法。
public 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.
}
}
回答by flybywire
回答by rcouto
I have been using Google Collections (now called Guava) for this kind of problem. There is a class called Iterables that can take an interface called Predicate as a parameter of a method that is really helpful.
我一直在使用 Google Collections(现在称为Guava)来解决这类问题。有一个叫做 Iterables 的类,它可以将一个叫做 Predicate 的接口作为一个非常有用的方法的参数。
Cat theOne = Iterables.find(cats, new Predicate<Cat>() {
public boolean apply(Cat arg) { return arg.age() == 3; }
});
Check it here!
在这里检查!
回答by Brian Dilley
Try the commons collections API:
尝试公共集合 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);
}
});
Of course you don't have to use an anonymous class everytime, you could create implementations of the Predicate
interface for commonly used searchs.
当然,您不必每次都使用匿名类,您可以Predicate
为常用搜索创建接口的实现。
回答by Brian Dilley
Again with the commons collections API: You get the "checker" type code when you Implement the Predicate Separately:-
再次使用公共集合 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;
}
}
which gets used as :-
它被用作:-
CollectionUtils.filter(catCollectionToFilter, new CatPredicate(3))