Intersection and union of ArrayLists in Java

后端 未结 24 2111
离开以前
离开以前 2020-11-22 06:05

Are there any methods to do so? I was looking but couldn\'t find any.

Another question: I need these methods so I can filter files. Some are AND filter

相关标签:
24条回答
  • 2020-11-22 06:55

    Final solution:

    //all sorted items from both
    public <T> List<T> getListReunion(List<T> list1, List<T> list2) {
        Set<T> set = new HashSet<T>();
        set.addAll(list1);
        set.addAll(list2);
        return new ArrayList<T>(set);
    }
    
    //common items from both
    public <T> List<T> getListIntersection(List<T> list1, List<T> list2) {
        list1.retainAll(list2);
        return list1;
    }
    
    //common items from list1 not present in list2
    public <T> List<T> getListDifference(List<T> list1, List<T> list2) {
        list1.removeAll(list2);
        return list1;
    }
    
    0 讨论(0)
  • 2020-11-22 06:57

    I was also working on the similar situation and reached here searching for help. Ended up finding my own solution for Arrays. ArrayList AbsentDates = new ArrayList(); // Will Store Array1-Array2

    Note : Posting this if it can help someone reaching this page for help.

    ArrayList<String> AbsentDates = new ArrayList<String>();//This Array will store difference
          public void AbsentDays() {
                findDates("April", "2017");//Array one with dates in Month April 2017
                findPresentDays();//Array two carrying some dates which are subset of Dates in Month April 2017
    
                for (int i = 0; i < Dates.size(); i++) {
    
                    for (int j = 0; j < PresentDates.size(); j++) {
    
                        if (Dates.get(i).equals(PresentDates.get(j))) {
    
                            Dates.remove(i);
                        }               
    
                    }              
                    AbsentDates = Dates;   
                }
                System.out.println(AbsentDates );
            }
    
    0 讨论(0)
  • 2020-11-22 06:58
    public static <T> Set<T> intersectCollections(Collection<T> col1, Collection<T> col2) {
        Set<T> set1, set2;
        if (col1 instanceof Set) {
            set1 = (Set) col1;
        } else {
            set1 = new HashSet<>(col1);
        }
    
        if (col2 instanceof Set) {
            set2 = (Set) col2;
        } else {
            set2 = new HashSet<>(col2);
        }
    
        Set<T> intersection = new HashSet<>(Math.min(set1.size(), set2.size()));
    
        for (T t : set1) {
            if (set2.contains(t)) {
                intersection.add(t);
            }
        }
    
        return intersection;
    }
    

    JDK8+ (Probably Best Performance)

    public static <T> Set<T> intersectCollections(Collection<T> col1, Collection<T> col2) {
        boolean isCol1Larger = col1.size() > col2.size();
        Set<T> largerSet;
        Collection<T> smallerCol;
    
        if (isCol1Larger) {
            if (col1 instanceof Set) {
                largerSet = (Set<T>) col1;
            } else {
                largerSet = new HashSet<>(col1);
            }
            smallerCol = col2;
        } else {
            if (col2 instanceof Set) {
                largerSet = (Set<T>) col2;
            } else {
                largerSet = new HashSet<>(col2);
            }
            smallerCol = col1;
        }
    
        return smallerCol.stream()
                .filter(largerSet::contains)
                .collect(Collectors.toSet());
    }
    

    If you don't care about performance and prefer smaller code just use:

    col1.stream().filter(col2::contains).collect(Collectors.toList());
    
    0 讨论(0)
  • 2020-11-22 07:01

    If the objects in the list are hashable (i.e. have a decent hashCode and equals function), the fastest approach between tables approx. size > 20 is to construct a HashSet for the larger of the two lists.

    public static <T> ArrayList<T> intersection(Collection<T> a, Collection<T> b) {
        if (b.size() > a.size()) {
            return intersection(b, a);
        } else {
            if (b.size() > 20 && !(a instanceof HashSet)) {
                a = new HashSet(a);
            }
            ArrayList<T> result = new ArrayList();
            for (T objb : b) {
                if (a.contains(objb)) {
                    result.add(objb);
                }
            }
            return result;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 07:02

    You can use CollectionUtils from apache commons.

    0 讨论(0)
  • 2020-11-22 07:04

    One-liners since Java 8

    import static java.util.stream.Stream.concat;
    import static java.util.stream.Collectors.toList;
    import static java.util.stream.Collectors.toSet;

    Union if there are no duplicates:

      return concat(a.stream(), b.stream()).collect(toList());
    

    Union and distinct:

      return concat(a.stream(), b.stream()).distinct().collect(toList());
    

    Union and distinct if Collection/Set return type:

      return concat(a.stream(), b.stream()).collect(toSet());
    

    Intersect if no duplicates:

      return a.stream().filter(b::contains).collect(toList());
    

    If collection b is huge and not O(1), then pre-optimize filter performance by adding 1 line before return. Copy to HasSet (import java.util.Set;):

    ... b = Set.copyOf(b);

    Intersect and distinct:

      return a.stream().distinct().filter(b::contains).collect(toList());
    
    0 讨论(0)
提交回复
热议问题