I have a requirement to check whether there is a common element in two lists. I came up with two ways to do this:
Method 01 : Loops
private boolean func01 (List<String> list1, List<String> list2) {
for (String group : list1) {
for (String funcGroup : list2) {
if (group.equals(funcGroup)) {
return true;
}
}
}
return false;
}
Method 02 : Lambda
private boolean func02 (List<String> list1, List<String> list2) {
return list1.stream().filter(list2::contains).findAny().isPresent();
}
In my view, I find the first method more readable. What I need to understand is, whether there are any differences or advantages when comparing these two methods?
method 1 optimization:
you don't need 2 loops and you can return immediately when you have a match, so you stop the traversing of the list at that point - (e.g. sunshine case you get a match on first element - you have 1 iteration, worst case your match is the last element - you have to traverse the whole list to hit that match)
private boolean func01 (List<String> list1, List<String> list2) {
for (String group : list1) {
if (list2.contains(group)) return true;
}
return false;
}
lambda equivalent optimization:
findAny().isPresent()
- get an optional of an element matching the predicate and check if the Optional is present - this is equivalent ofanyMatch()
because both expressions returnboolean
filter()
will always traverse the whole listanyMatch()
has a short-circuit behavior - means it will stop on the first match
so you can re-write it as:
private boolean func02 (List<String> list1, List<String> list2) {
return list1.stream().anyMatch(list2::contains);
}
To answer your question - there's no significant performance difference in the two approaches, but take into consideration:
creating stream for a collection has a slight overhead
stream operations can be run in parallel (
list1.stream().parallel().anyMatch(list2::contains)
). For example in this caseanyMatch()
running in parallel threads over the same stream will periodically check if the previous threads found a match and will stop traversing the collection and not continue traversing the whole collection. So in theory for significantly large input lists, you should get better results with parallel streams.