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
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;
}
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 );
}
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());
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;
}
}
You can use CollectionUtils
from apache commons.
import static java.util.stream.Stream.concat;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
return concat(a.stream(), b.stream()).collect(toList());
return concat(a.stream(), b.stream()).distinct().collect(toList());
return concat(a.stream(), b.stream()).collect(toSet());
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);
return a.stream().distinct().filter(b::contains).collect(toList());