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:
How could it change semantics? Would it change semantics?
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With