How to search in a List of Java object

前端 未结 5 1307
耶瑟儿~
耶瑟儿~ 2020-11-27 16:21

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;
          


        
相关标签:
5条回答
  • 2020-11-27 16:51

    As your list is an ArrayList, it can be assumed that it is unsorted. Therefore, there is no way to search for your element that is faster than 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.

    Another possibility would be to use a 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. 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>. 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.

    0 讨论(0)
  • 2020-11-27 16:52

    Using Java 8

    With Java 8 you can simply convert your list to a stream allowing you to write:

    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
    • result is a List with a Sample type
    • 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)


    Apache Commons

    If you can't use Java 8, you can use Apache Commons library and write:

    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
    • If you need your results to be typed as Sample[], you need extra code (as shown in my sample)



    Bonus: A nice blog article talking about how to find element in list.

    0 讨论(0)
  • 2020-11-27 16:58

    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;
       }
    }
    
    0 讨论(0)
  • 2020-11-27 16:59

    You can give a try to Apache Commons Collections.

    There is a class CollectionUtils that allows you to select or filter items by custom Predicate.

    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:

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

    much nicer!

    0 讨论(0)
  • 2020-11-27 17:00

    If you always search based on value3, you could store the objects in a 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.

    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>.

    0 讨论(0)
提交回复
热议问题