简体   繁体   English

如何在Java对象列表中进行搜索

[英]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中 ,使用LambdasStreamAPI应该是:

List<Sample> result = list.stream()
     .filter(item -> item.value3.equals("three"))
     .collect(Collectors.toList());

much nicer! 好多了!

Using Java 8 使用Java 8

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
  • It's very fast, no cast at every iteration 速度非常快,每次迭代都无需投放
  • If your filter logic gets heavier, you can do list.parallelStream() instead of list.stream() ( read this ) 如果您的过滤器逻辑变得更重,则可以执行list.parallelStream()而不是list.stream()阅读此内容


Apache Commons Apache Commons

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: 注意:

  • There is a cast from Object to Sample at each iteration 每次迭代都有一个从ObjectSample
  • If you need your results to be typed as 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. 如果可以的话,您应该考虑将列表更改为带有示例类的特定ComparatorSet (以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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM