The 30 second answer
I put the second list into a HashSet, then filter the first list with contains and distinct. That is linear expected time instead of nested scans. I mention equals and hashCode again if the element type is a custom class.
Set<T> setB = new HashSet<>(b);
List<T> common = a.stream()
.filter(setB::contains)
.distinct()
.toList();O(n + m) expected time instead of O(n · m) from calling contains on a list. [Opinion — standard complexity reasoning]
Sources:
Sources (0)
See inline citations in the answer above.