Is there a performance gain by using lambda expressions?

ycr :

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?

hovanessyan :

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 of anyMatch() because both expressions return boolean

  • filter() will always traverse the whole list

  • anyMatch() 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 case anyMatch() 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.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=435746&siteId=1