Если вы не следуете правилам чистого функционального программирования, при преобразовании лямбды в ссылку на метод может произойти изменение семантики.
Разница в том, что ссылка на метод будет разрешена при построении потока. Но в лямбда-выражении код для получения метода может оцениваться при каждом выполнении лямбда-выражения.
Вот краткий автономный пример для демонстрации:
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();
}
}
Hwo, чтобы избежать этой проблемы: не используйте побочные эффекты при работе с потоками. Не используйте peek
для обработки! Этот метод существует главным образом для поддержки отладки (посмотрите на javado c).