[英]How to search in a List of Java object
I have a List of object and the list is very big. 我有一个对象列表,列表很大。 The object is 对象是
class Sample {
String value1;
String value2;
String value3;
String value4;
String value5;
}
Now I have to search for a specific value of an object in the list. 现在,我必须在列表中搜索对象的特定值。 Say if value3=='three'
I have to return those objects (My search is not always based on value3) 说如果value3=='three'
我必须返回那些对象(我的搜索并不总是基于value3)
The list is 清单是
List<Sample> list = new ArrayList<Sample>();
What is the efficient way of doing it? 有效的方法是什么?
Thanks. 谢谢。
You can give a try to Apache Commons Collections . 您可以尝试使用Apache Commons Collections 。
There is a class CollectionUtils that allows you to select or filter items by custom Predicate . 有一个CollectionUtils类,允许您通过自定义谓词选择或过滤项目。
Your code would be like this: 您的代码将如下所示:
Predicate condition = new Predicate() {
boolean evaluate(Object sample) {
return ((Sample)sample).value3.equals("three");
}
};
List result = CollectionUtils.select( list, condition );
Update: 更新:
In java8 , using Lambdas and StreamAPI this should be: 在java8中 ,使用Lambdas和StreamAPI应该是:
List<Sample> result = list.stream()
.filter(item -> item.value3.equals("three"))
.collect(Collectors.toList());
much nicer! 好多了!
With Java 8 you can simply convert your list to a stream allowing you to write: 使用Java 8,您可以简单地将列表转换为流,从而可以编写:
import java.util.List;
import java.util.stream.Collectors;
List<Sample> list = new ArrayList<Sample>();
List<Sample> result = list.stream()
.filter(a -> Objects.equals(a.value3, "three"))
.collect(Collectors.toList());
Note that 注意
a -> Objects.equals(a.value3, "three")
is a lambda expression a -> Objects.equals(a.value3, "three")
是一个lambda表达式 result
is a List
with a Sample
type result
是带有Sample
类型的List
list.parallelStream()
instead of list.stream()
( read this ) 如果您的过滤器逻辑变得更重,则可以执行list.parallelStream()
而不是list.stream()
( 阅读此内容 ) If you can't use Java 8, you can use Apache Commons library and write: 如果您不能使用Java 8,则可以使用Apache Commons库并编写:
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
Collection result = CollectionUtils.select(list, new Predicate() {
public boolean evaluate(Object a) {
return Objects.equals(((Sample) a).value3, "three");
}
});
// If you need the results as a typed array:
Sample[] resultTyped = (Sample[]) result.toArray(new Sample[result.size()]);
Note that: 注意:
Object
to Sample
at each iteration 每次迭代都有一个从Object
到Sample
Sample[]
, you need extra code (as shown in my sample) 如果需要将结果键入为Sample[]
,则需要额外的代码(如我的示例所示) Bonus: A nice blog article talking about how to find element in list. 奖励:一篇不错的博客文章,讨论如何在列表中查找元素。
If you always search based on value3
, you could store the objects in a Map: 如果您始终基于value3
搜索,则可以将对象存储在Map中:
Map<String, List<Sample>> map = new HashMap <>();
You can then populate the map with key = value3
and value = list of Sample objects with that same value3
property. 然后,您可以使用key = value3
和value =具有相同value3
属性的Sample对象列表填充地图。
You can then query the map: 然后,您可以查询地图:
List<Sample> allSamplesWhereValue3IsDog = map.get("Dog");
Note: if no 2 Sample
instances can have the same value3
, you can simply use a Map<String, Sample>
. 注意:如果没有两个Sample
实例可以具有相同的value3
,则可以简单地使用Map<String, Sample>
。
I modifie this list and add a List to the samples try this 我修改了此列表,并向示例添加了一个列表,请尝试此操作
Pseudocode 伪码
Sample {
List<String> values;
List<String> getList() {
return values}
}
for(Sample s : list) {
if(s.getString.getList.contains("three") {
return s;
}
}
As your list is an ArrayList
, it can be assumed that it is unsorted. 由于您的列表是ArrayList
,因此可以假定它是未排序的。 Therefore, there is no way to search for your element that is faster than O(n) . 因此,无法搜索比O(n)更快的元素。
If you can, you should think about changing your list into a Set
(with HashSet
as implementation) with a specific Comparator
for your sample class. 如果可以的话,您应该考虑将列表更改为带有示例类的特定Comparator
的Set
(以HashSet
作为实现)。
Another possibility would be to use a HashMap
. 另一种可能性是使用HashMap
。 You can add your data as Sample
(please start class names with an uppercase letter) and use the string you want to search for as key. 您可以将数据添加为Sample
(请以小写字母开头的类名称),然后将要搜索的字符串用作键。 Then you could simply use 然后,您可以简单地使用
Sample samp = myMap.get(myKey);
If there can be multiple samples per key, use Map<String, List<Sample>>
, otherwise use Map<String, Sample>
. 如果每个键可以有多个样本,请使用Map<String, List<Sample>>
,否则请使用Map<String, Sample>
。 If you use multiple keys, you will have to create multiple maps that hold the same dataset. 如果使用多个键,则必须创建多个保存相同数据集的地图。 As they all point to the same objects, space shouldn't be that much of a problem. 因为它们都指向相同的对象,所以空间不应该成为问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.