Efficient intersection of two List <String> in Java?
The question is simple:
I have two lists
List<String> columnsOld = DBUtils.GetColumns(db, TableName); List<String> columnsNew = DBUtils.GetColumns(db, TableName); And I need to get their intersection. Is there a quick way to achieve this?
You can use retainAll method:
columnsOld.retainAll (columnsNew); Since keepAll will not touch the collection of arguments, it will be faster:
List<String> columnsOld = DBUtils.GetColumns(db, TableName); List<String> columnsNew = DBUtils.GetColumns(db, TableName); for(int i = columnsNew.size() - 1; i > -1; --i){ String str = columnsNew.get(i); if(!columnsOld.remove(str)) columnsNew.remove(str); } The intersection will be the value remaining in the New columns. Removing fom columnsOld values ββalready compared will reduce the number of comparisons needed.
What about
private List<String> intersect(List<String> A, List<String> B) { List<String> rtnList = new LinkedList<>(); for(String dto : A) { if(B.contains(dto)) { rtnList.add(dto); } } return rtnList; } There is a good way with threads that can do this in one line of code, and you can use two lists that are not of the same type, which is impossible with the containsAll afaik method:
columnsOld.stream().filter(c -> columnsNew.contains(c)).collect(Collectors.toList()); An example for lists with different types. If you have a reality between foo and bar, and you can get a bar object from foo, than you can change your stream:
List<foo> fooList = new ArrayList<>(Arrays.asList(new foo(), new foo())); List<bar> barList = new ArrayList<>(Arrays.asList(new bar(), new bar())); fooList.stream().filter(f -> barList.contains(f.getBar()).collect(Collectors.toList()); If you put the second list in a set, tell HashSet. And just iterate over the first list, checking for the presence on the set and deleting if it is not there, your first list will ultimately have the intersection that you need. It will be faster than keepAll or listed. The emphasis here is on using a set instead of a list. Search is O (1). firstList.retainAll (new HashSet (second list)) will also work.
using retainAll if anyway, otherwise use N.intersection
a = N.asList(12, 16, 16, 17, 19); b = N.asList(16, 19, 107); a.retainAll(b); // [16, 16, 19] N.println(a); a = N.asList(12, 16, 16, 17, 19); b = N.asList(16, 19, 107); a = N.intersect(a, b); N.println(a); // [16, 19] N is a utility class in AbacusUtil
use org.apache.commons.collections4.ListUtils # intersection