【问题标题】:Sonar : Replace this lambda with a method reference声纳:用方法引用替换这个 lambda
【发布时间】:2014-10-25 17:53:48
【问题描述】:
此代码示例
Collection<Number> values = transform(
getValuatedObjects(),
input -> getValueProvider().apply(input).getValue());
违反sonarqube rule:
尽可能用方法引用替换 lambdas
这是声纳错误吗?
或者我真的可以使用方法参考吗?
【问题讨论】:
标签:
java
lambda
java-8
sonarqube
【解决方案1】:
您不能在不改变语义的情况下将 lambda input -> getValueProvider().apply(input).getValue() 替换为方法引用。
方法引用替换单个方法调用,因此它不能简单地替换由多个方法调用组成的 lambda 表达式。
input -> getValueProvider().apply(input) 形式的 lambda 表达式可以替换为 getValueProvider()::apply 当且仅当 getValueProvider() 的评估时间无关紧要,因为在 lambda 形式中,该方法在每个 lambda 主体评估时调用,而对于方法引用,它只被调用一次并捕获结果。
这类似于x -> System.out.println(x) 和System.out::println 之间的区别,其中读取字段System.out 的内容发生在不同的时间,但通常没关系。但你应该知道其中的区别。
在您的示例中,调用了第三种方法getValue()。用方法引用表达这一点的唯一方法需要一个像Function 这样的函数接口,它具有像andThen 和/或compose 这样的方法。但是,Java 8 的工作方式需要将第一个方法引用转换为目标接口以调用组合方法,这绝不比您现在拥有的 lambda 表达式更容易阅读:((Function<X,Y>)getValueProvider()::apply).andThen(Y::getValue) 其中Y 是类型,apply(input) 返回。
请注意,规则说“用方法引用替换 lambdas如果可能”这让你有空间说,“好吧,这是不可能的”,但是,我不确定你有多少那么可以称之为“规则”……
【解决方案2】:
list.stream().sorted().collect(Collectors.toList()).forEach(element ->
操作(元素));
用方法引用替换上面的 lambda。
list.stream().sorted().collect(Collectors.toList()).forEach(this::operate);
【解决方案3】:
如果您使用 java 8 进行编码,则可以使用方法引用代替 lambda 表达式以使代码可读
List<Integer> list = Arrays.asList(1,2,3,4,5);
用方法引用替换这个 lambda
strList.stream().sorted().collect(Collectors.toList()).forEach(s -> System.out.println(s));
替换
strList.stream().sorted().collect(Collectors.toList()).forEach(System.out::println);
【解决方案4】:
List<String> inputStringList = List.of("A", "B", "C", "D");
List<String> outputStringList = List.of("C", "D", "E", "F");
assertTrue(outputStringList.stream().anyMatch(inputStringList::contains));
assertTrue(outputStringList.stream().allMatch(inputStringList::contains));
这是一个示例代码,用于使用方法参考检查 List 的内容是否与另一个 List 匹配。