反向排序流

Sun*_*esh 10 java sorting java-8 java-stream

我想反向排序下面的流,但得到编译时错误"The method sorted() in the type IntStream is not applicable for the arguments ((<no type> o1, <no type> o2) -> {})".谁能纠正这个

IntStream.range(1, 100)
         .filter(x -> x%2 != 0)
         .sorted((o1,o2) -> -o1.compareTo(o2))
         .forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

Ous*_* D. 13

说明

因为你正在使用IntStream它只有一个已排序方法的重载,它是自然顺序(这是有道理的).

相反,将流从中包装IntStreamStream<Integer>那么它应该足够了:

 IntStream.range(1, 100)
          .filter(x -> x % 2 != 0)
          .boxed()  // <--- boxed to Stream<Integer>
          .sorted((o1,o2) -> -o1.compareTo(o2)) // now we can call compareTo on Integer
          .forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

但是,正如@Holger在评论中提到的那样:

从不使用比较器功能(o1,o2) -> -o1.compareTo(o2).compareTo返回实现 是完全合法的Integer.MIN_VALUE,在这种情况下,否定将失败并产生不一致的结果.有效的反向比较器将是(o1,o2) - > o2.compareTo(o1)

建议改进您的代码.JDK8

更好的方法是:

IntStream.range(1, 100)
         .filter(x -> x % 2 != 0)
         .boxed()
         .sorted(Comparator.reverseOrder())
         .forEachOrdered(System.out::println);
Run Code Online (Sandbox Code Playgroud)

为什么?

  • 已经有一个内置的比较器执行如上所示的逆序.
  • 如果你想保证在打印时按照排序顺序看到这些元素然后利用forEachOrdered(大声喊叫@Holger总是提醒我)

或者根据@Holger的建议,它可以简化为:

 IntStream.range(0, 50)
          .map(i -> 99-i*2)
          .forEachOrdered(System.out::println);
Run Code Online (Sandbox Code Playgroud)

JDK9变种

顺便说一句,在JDK9中,从帖子中的代码开始,您可以先将其简化iterate为:

IntStream.iterate(1, i  -> i <= 99, i -> i + 2)
         .boxed()
         .sorted(Comparator.reverseOrder())
         .forEachOrdered(System.out::println);
Run Code Online (Sandbox Code Playgroud)

通过这种方法,我们可以避免过滤器中间操作和2的增量.

最后你可以进一步简化它:

IntStream.iterate(99, i  -> i > 0 , i -> i - 2)
         .forEachOrdered(System.out::println);
Run Code Online (Sandbox Code Playgroud)

通过这种方法,我们能够避免filter,boxed,sorted等人.

  • 当我们处于通常的提醒状态时,永远不要使用比较器函数,如`(o1,o2) - > -o1.compareTo(o2)`.`compareTo`实现返回`Integer.MIN_VALUE`是完全合法的,在这种情况下,否定将失败并产生不一致的结果.一个有效的反向比较器将是`(o1,o2) - > o2.compareTo(o1)`,或者只是你所显示的`Comparator.reverseOrder()`,它已经完成了工作.顺便说一句,我不会使用`iterate`而是`IntStream.range(0,50).map(i - > 99-i*2)`这在很多情况下更有效. (4认同)
  • @Holger非常感激,一如既往地学习.编辑以适应您的建议. (2认同)