如何在 Sonarqube 上修复 "Intermediate Stream methods should not be left unused"

How to fix "Intermediate Stream methods should not be left unused" on Sonarqube

我在 Sonarqube 上发现了这个错误:

private String getMacAdressByPorts(Set<Integer> ports) {
    ports.stream().sorted(); // sonar list show "Refactor the code so this stream pipeline is used"
    return ports.toString();
} //getMacAdressByPorts

网上找了半天,没用。请帮助或尝试提供一些想法如何实现这一目标。

sorted()方法对你传入的Set没有影响;实际上,这是一个非终端操作,所以它甚至没有被执行。如果你想对你的端口进行排序,你需要像

这样的东西
return ports.stream().sorted().collect(Collectors.joining(","));

编辑: 正如@Slaw 正确指出的那样,要获得与之前相同的格式(即 [item1, item2, item3],您还需要将方括号添加到连接收集器中,即 Collectors.joining(", ", "[", "]")。为了简单起见,我将它们省略了。

来自 Sonar Source documentation 关于此警告(我的重点):

Stream operations are divided into intermediate and terminal operations, and are combined to form stream pipelines. After the terminal operation is performed, the stream pipeline is considered consumed, and cannot be used again. Such a reuse will yield unexpected results.

Official JavaDoc for stream() 提供了更多关于 sorted() 的细节(我的重点):

Returns a stream consisting of the elements of this stream, sorted according to natural order. If the elements of this stream are not Comparable, a java.lang.ClassCastException may be thrown when the terminal operation is executed. [...] This is a stateful intermediate operation.

这意味着仅使用 sorted() 不会产生任何结果。来自Oracle Stream package documentation(仍然是我的重点):

Stream operations are divided into intermediate and terminal operations, and are combined to form stream pipelines. A stream pipeline consists of a source (such as a Collection, an array, a generator function, or an I/O channel); followed by zero or more intermediate operations such as Stream.filter or Stream.map; and a terminal operation such as Stream.forEach or Stream.reduce.

Intermediate operations return a new stream. They are always lazy; executing an intermediate operation such as filter() does not actually perform any filtering, but instead creates a new stream that, when traversed, contains the elements of the initial stream that match the given predicate. Traversal of the pipeline source does not begin until the terminal operation of the pipeline is executed.

sorted() returns 另一个 stream(),而不是排序列表。要解决您的 Sonar 问题(可能还有您的代码问题,以这种方式),您必须调用终端操作才能 运行 所有中间操作。您可以找到一个终端操作列表(我认为并不详尽)on CodeJava for instance.


对于您的情况,解决方案可能如下所示:

private String getMacAdressByPorts(Set<Integer> ports) {
    /* Ports > Stream > Sort (intermediate operation) > 
    / Collector (final operation) > List > String
    / Note that you need to import the static method toList()
    / from the Collector API, otherwise it won't compile
    */

    return ports.stream().sorted().collect(toList()).toString();
}

我终于用下面的代码解决了这个问题。

private String getMacAdressByPorts(Set<Integer> ports) {
        return ports.stream().sorted().collect(Collectors.toList()).toString();