关于java:一次从流中选择2个元素

 2021-02-24 

pick 2 elements from stream at a time

本问题已经有最佳答案,请猛点这里访问。

假设我们有一个集合(或流?)

1
{"1","2","3","4"...}

现在我们要采用两个元素并像这样组成一个对

1
{{"1","2"}, {"2","3"},{"3","4"}..}

我们知道如何做到这一点(for循环)。

我想知道如何使用Java 8流吗?

因为Java流和响应式扩展中的方法几乎相同(都是monad),所以我认为可能会有类似RX .pick(2)的东西,当2个元素到达时会触发事件...


这也不是很漂亮,但是您可以用收藏家来做。我使用了一个内部包含Arrays的ArrayList,但是如果需要,可以使用不同的中间集合类型。

我在这里所做的是一个收集器,该收集器将每个项目添加为添加到累加器的最后一个数组中的第二个项目,并作为要添加到累加器的新数组中的第一个项目。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

ArrayList<Integer[]> pairs =
    stream.collect(
        () -> new ArrayList<>(),
        (acc, next) -> {
            if(acc.isEmpty()) {
                acc.add(new Integer[] {next, null});
            } else {
                acc.get(acc.size() - 1)[1] = next;
                acc.add(new Integer[] {next, null});
            }
        },
        ArrayList::addAll
    );

pairs.forEach(a -> System.out.println(a[0] +"," + a[1]));

//-> 1, 2
//-> 2, 3
//-> 3, 4
//-> 4, 5
//-> 5, 6
//-> 6, null


可以使用IntStream.range以某种流形式循环。

1
2
3
4
String[] str = {"1","2","3","4"};
final String[][] result = IntStream.range(0, str.length - 1)
        .mapToObj(i -> new String[]{str[i], str[i + 1]})
        .toArray(String[][]::new);

结果包含{{"1","2"}, {"2","3"}, {"3","4"}}