【问题标题】:Remove max (or min) from collection using Java8 streaming API使用 Java8 流 API 从集合中删除最大值(或最小值)
【发布时间】:2014-05-19 14:44:21
【问题描述】:

我对使用来自 Java 8 的新流式 API 的代码设计没有什么问题。我想学习新事物,其中一项任务是:

拒绝列表中的最大值和最小值。列表不包含重复项。

看起来很简单?不...我的代码:

  List<Integer> ranges = Lists.newArrayList(new Range(1, 15));
        List<Integer> collect = ranges.stream()
                .filter(x -> x != ranges.stream()
                        .mapToInt(Integer::intValue)
                        .max()
                        .getAsInt())
                .filter(x -> x != ranges.stream()
                        .mapToInt(Integer::intValue)
                        .min()
                        .getAsInt())

                .collect(Collectors.toList());
        assertThat(collect).hasSize(13);   // OK
        assertThat(collect).isEqualTo(Lists.newArrayList(new Range(2,14)));   // OK

这段代码很好(如果我们没有重复的最小值/最大值,但这不是这里的核心问题)但问题是我在这里使用了三个流。第一个是主流,第二个是删除最大值,第三个是删除最小值。 是否有可能在一个流中完成此任务?

//编辑: 非常原始的 Scala 版本:

val list = List.range(1, 15).sortWith(_>_).tail.reverse.tail

加上额外的排序,因为我们可以有 shuiffed 列表。

【问题讨论】:

  • 嗯,没有流的情况下做这个更简单......但是好吧,这是一个练习,所以......
  • 你不能用一个流来做,只要它是未排序的。您需要事先解决最小值和最大值。如果您的流已排序,您可以使用 .filter(x -&gt; x != ranges.get(0)).filter(x -&gt; x != ranges.get(ranges.size()-1))
  • 我认为Scala版本无法与Java版本相提并论。 Scala 方法(排序和删除第一个和最后一个元素)与 Java 方法(计算最小值和最大值,以及过滤流)完全不同
  • @Marco13 我知道,但这是我想要得到的一个很好的例子。
  • 不应该像List&lt;Integer&gt; collect = ranges.stream().sorted().collect(Collectors.toList()).subList(1, ranges.size()-1); 这样的选择吗?它至少更接近 Scala 方法...

标签: java collections java-8 java-stream


【解决方案1】:

别忘了Collection.removeIf。您可以计算最小值和最大值,然后执行:

list.removeIf(x -> x == min || x == max);

(这也可以很好地处理重复。)

【讨论】:

  • 太棒了。我不知道这存在!
【解决方案2】:

该解决方案效率不高,但我认为它符合您的要求 - 它可以满足您的要求,并且在一个 管道 中 - 一个单一的批量数据操作序列,Java 8 如何调用它。

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

Stream<Integer> ranges = Stream.iterate(1, i -> i + 1).limit(15);
List<Integer> collect = ranges
    .sorted(Comparator.reverseOrder()) // sort the stream from the highest to the smallest
    .skip(1)                           // discards 1 element from the beginning
    .sorted()                          // sort the stream from the smallest to the highest
    .skip(1)                           // discards 1 element from the beginning
    .collect(Collectors.toList())     
    ;

但是,正如 fge 建议和 Marco13 在您的问题下方的评论中所写的那样,对流进行排序、将管道终止到列表然后删除第一个和最后一个成员会更好、更有效:P 或没有排序甚至更快 - 遍历所有元素,找到最小值和最大值,记住它们的位置,然后删除它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-23
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 2020-11-19
    • 2018-06-25
    • 1970-01-01
    相关资源
    最近更新 更多