Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'filter()' and 'map()' can be swapped

I have a simple stream like following:

List<Long> r = l.stream()
                .filter(a->a.getB() % 2 == 0)
                .map(A::getB)
                .collect(Collectors.toList());

But Intellij suggests me:

'filter()' and 'map()' can be swapped Inspection info: Reports stream API call chains which can be simplified. It allows to avoid creating redundant temporary objects when traversing a collection. e.g.

  • collection.stream().forEach() → collection.forEach()
  • collection.stream().collect(toList/toSet/toCollection()) → new CollectionType<>(collection)

The example given by Intellij is easy to understand, but I don't understand why it suggests me to map().filter().

I view the source of ReferencePipeline but find no clue: map().filter() or filter().map() makes no difference when comes to the temporary object related to stream implementation (filter().map() will have less auto-boxing if A.b is a primitive which makes me more confused).

So, am I missing some point of stream implementation or this is a false alarm of Intellij?

like image 444
Tony Avatar asked Apr 07 '21 04:04

Tony


1 Answers

a.getB() is invoked twice - once inside the filter and it is also the mapping function, so instead of doing this twice, it would be better to first map it using getB and then filter it out

List<Long> r = l.stream().map(A::getB).filter(b->b % 2 == 0).collect(Collectors.toList());

EDIT

If getB returns a long then mapToLong could be used to avoid intermediate boxing operations.

List<Long> r = l.stream()
                .mapToLong(A::getB)
                .filter(b->b % 2 == 0)
                .boxed()
                .collect(Collectors.toList());

SAMPLE OUTPUT

Using a static counter to count the invocation of get method:

class A {
    public static int count = 0;
    private long b;

    public long getB() {
        count++;
        return b;
    }
}
List<A> list= List.of(new A(1L), new A(3L), new A(4L));
list.stream() 
    .filter(a -> a.getB()%2 == 0)
    .map(A::getB)
    .collect(Collectors.toList());
System.out.println(A.count); // returns 4

whereas

list.stream()
    .mapToLong(A::getB)
    .filter(b->b % 2 == 0)
    .boxed()
    .collect(Collectors.toList());
System.out.println(A.count); // returns 3
like image 108
Gautham M Avatar answered Oct 08 '22 03:10

Gautham M