Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IntelliJ - method reference may change semantics

I have following code:

return userService.getAll()
    .stream()
    .map(User::getRoleName)
    .map(roleName -> roleService.findRoleByName(roleName))
    .collect(Collectors.toSet());

It seems that roleName -> roleService.findRoleByName(roleName) could be replaced by a method reference (namely a Reference to an instance method of a particular object) however IntelliJ IDEA warns that this may change semantics:

screenshot

How could it change semantics? Would it change semantics?

like image 645
streetturtle Avatar asked Oct 16 '22 04:10

streetturtle


1 Answers

If you do not follow the rules of clean functional programming, there may be a change of semantics when you convert a lambda to a method reference.

The difference is that the method reference will be resolved when the stream is being built. But in the lambda expression the code for getting the method can be evaluated in each execution of the lambda.

Here is a short self-contained example for demonstration:

public class Test40 {
  public static void main(String[] args) {
    Function<Integer, Integer> f2 = n -> 2 * n;
    Function<Integer, Integer> f3 = n -> 3 * n;
    Function<Integer, Integer>[] funcArray = new Function[1];

    funcArray[0] = f2;
    Stream.of(1, 2, 3)
          .peek(n -> { if (n > 1 ) funcArray[0] = f3; })
          .map(funcArray[0]::apply)            // Method reference, '::apply' could be omitted
          .forEach(System.out::print);         // prints 246
    System.out.println();

    funcArray[0] = f2;
    Stream.of(1, 2, 3)
          .peek(n -> { if (n > 1 ) funcArray[0] = f3; })
          .map(n -> funcArray[0].apply(n))     // Lambda
          .forEach(System.out::print);         // prints 269
    System.out.println();
  }
}

How to avoid this problem: Do not use side effects when working with streams. Do not use peek for processing! This method exists mainly to support debugging (have a look at the javadoc).

like image 137
Donat Avatar answered Oct 18 '22 23:10

Donat