-2

If I had, say separate 3 nested ArrayLists of Strings, i.e., ArrayList<ArrayList<String>>:

  1. What is the most efficient way of finding their intersection (common elements)?
  2. Are there other data structures to replace the nested ArrayLists structure that could improve the efficiency of finding their intersection? (e.g. The first structure I can think of is using a Set, but I would like to see if there are other suggestions for this.)

Thanks in advance!

1
  • 2
    Yep, you want a set. Any kind of set will do. HashSet will probably be faster in general, whereas TreeSet will behave more predictably and may be faster at small sizes Commented May 15, 2021 at 23:41

2 Answers 2

1

The intersection of two lists is done using the retainAll() method.

It update the list, so if you don't want that, you should copy the list first.

If you have more than 2 lists, you copy the first and then call retainAll() for each of the remaining lists.

ArrayList<ArrayList<String>> lists = ...

List<String> intersection = new ArrayList<>(lists.get(0));
for (List<String> list : lists.subList(1, lists.size()))
    intersection.retainAll(list);

However performance will be a bad O(n*m), where n and m are the sizes of the two largest lists.

That is because retainAll() does a contains() against the list given in the parameter, which is a sequential search, for each element in the intersection list.

Performance can be improved to O(n), where n is the largest list, by converting the lists to sets.

List<String> intersection = new ArrayList<>(lists.get(0));
for (List<String> list : lists.subList(1, lists.size()))
    intersection.retainAll(new HashSet<>(list));

In Java 8+, the for loop can be simplified to one of these:

lists.subList(1, lists.size()).stream().map(HashSet::new).forEach(intersection::retainAll);

lists.subList(1, lists.size()).forEach(list -> intersection.retainAll(new HashSet<>(list)));
Sign up to request clarification or add additional context in comments.

Comments

1

i would use the list.retainAll method as in

private ArrayList<String> getIntersection(ArrayList<ArrayList<String>> lists) {
    if(null == lists || lists.isEmpty()) {
        return null;
    }
    ArrayList<String> intersection = lists.get(0);
    lists.forEach(intersection::retainAll);
    return intersection;
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.