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)));
HashSetwill probably be faster in general, whereasTreeSetwill behave more predictably and may be faster at small sizes