代码之家  ›  专栏  ›  技术社区  ›  Koziołek

使用Java8流API从集合中删除max(或min)

  •  11
  • Koziołek  · 技术社区  · 12 年前

    我对使用Java8中新的流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
    

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

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

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

    有额外的排序,因为我们可能会有一个水飞的列表。

    2 回复  |  直到 11 年前
        1
  •  28
  •   Brian Goetz    11 年前

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

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

    (这也能很好地处理重复项。)

        2
  •  6
  •   Honza Zidek    12 年前

    该解决方案效率不高,但我认为它符合您的要求-它可以满足您的需求,而且是一个单一的解决方案 管道 -一个单一的批量数据操作序列,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或者更快,不进行排序-遍历所有元素,找到最小值和最大值,记住它们的位置,然后删除它们。

    推荐文章