我有以下代码:
return userService.getAll()
.stream()
.map(User::getRoleName)
.map(roleName -> roleService.findRoleByName(roleName))
.collect(Collectors.toSet());
看来
roleName -> roleService.findRoleByName(roleName)
可以替换为方法引用(即对特定对象的实例方法的引用),但是 IntelliJ IDEA 警告说这可能会改变语义:它如何改变语义?它会改变语义吗?
最佳答案
如果您不遵循干净函数式编程的规则,则在将 lambda 转换为方法引用时,语义可能会发生变化。
不同之处在于方法引用将在构建流时解析。但是在 lambda 表达式中,可以在每次执行 lambda 时评估获取方法的代码。
这是一个简短的自包含示例用于演示:
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();
}
}
如何避免这个问题:在处理流时不要使用副作用。请勿使用 peek
用于加工!这个方法的存在主要是为了支持调试(看看javadoc)。
关于java - IntelliJ - 方法引用可能会改变语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61283367/