使用 Java 8 流根据元素之间的差异将有序数字列表拆分为多个列表

A. *_*own 4 java list java-8

第一次在这里提问,所以请放轻松。:) 无论如何,我不确定使用 Java 8 流是否可以实现这一点,但我对学习非常感兴趣。

假设我有以下有序数字列表:

List<Integer> myList = Arrays.asList(1, 2, 3, 7, 9, 12, 13, 15);
Run Code Online (Sandbox Code Playgroud)

现在,我想当元素之间的差异大于 2 时,将此列表拆分为多个列表。因此,最终结果将是三个不同的列表:

{1, 2, 3}
{7, 9}
{12, 13, 15}
Run Code Online (Sandbox Code Playgroud)

我可以使用 for 循环轻松完成此练习,并将当前元素与前一个 while 循环进行比较。但是,我想知道是否有一种简洁的方法可以使用 Java 8 流来完成此任务?就像我之前说过的,这只是为了我自己对 Java 8 的学习和理解,所以如果不可能,那也没关系。

预先感谢您的任何评论或答复。

Eug*_*ene 5

好吧,我只能想到一个自定义收集器,因为您需要一些先前的状态,但这到目前为止并不简洁(除非您将其隐藏在方法后面):

 private static <T> Collector<Integer, ?, List<List<Integer>>> diffCollector() {

    class Acc {

        private Integer previous;

        private List<List<Integer>> result = new ArrayList<>();

        void accumulate(Integer elem) {
            if (previous == null) {
                previous = elem;
                List<Integer> list = new ArrayList<>();
                list.add(previous);
                result.add(list);
                return;
            }

            if (elem - previous > 2) {
                List<Integer> oneMore = new ArrayList<>();
                oneMore.add(elem);
                result.add(oneMore);
                previous = elem;
            } else {
                result.get(result.size() - 1).add(elem);
                previous = elem;
            }
        }

        Acc combine(Acc other) {

            throw new UnsupportedOperationException("Not for parallel");
        }

        List<List<Integer>> finisher() {
            return result;
        }

    }
    return Collector.of(Acc::new, Acc::accumulate, Acc::combine, Acc::finisher);
}
Run Code Online (Sandbox Code Playgroud)

用法是:

 List<Integer> myList = Arrays.asList(1, 2, 3, 7, 9, 12, 13, 15);
 System.out.println(myList.stream().collect(diffCollector()));
Run Code Online (Sandbox Code Playgroud)