pick 2 elements from stream at a time [duplicate]

ε祈祈猫儿з 提交于 2019-12-12 11:36:45

问题


Suppose we have a collection (or stream?)

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

now we want to take two elements and compose a pair like this

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

We know how to do that the ugly way (for loop).

I wonder how do we do this with java 8 streams?

Because approaches in java streams and reactive extensions are pretty much same (both are monads) I thought there might be something alike RX .pick(2) which would trigger event when 2 elements arrive...


回答1:


It's not pretty either but you can do it with a collector. I've used an ArrayList with Arrays inside, but you can use different intermediate collection types if you want.

What I've done here is a collector that adds every item as a second item on the last array added to the accumulator and as a first item on a new array that will be added to the accumulator.

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



回答2:


It is possible to use the IntStream.range to loop in a stream-kind-of-way.

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);

The result contains {{"1", "2"}, {"2", "3"}, {"3", "4"}}.



来源:https://stackoverflow.com/questions/28622119/pick-2-elements-from-stream-at-a-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!