Java stream reduce

后端 未结 4 2485
南旧
南旧 2021-02-20 11:53

I have the following example data set that I want to transform / reduce using Java stream api based on direction\'s value

Direction    int[]
IN           1, 2
O         


        
4条回答
  •  爱一瞬间的悲伤
    2021-02-20 12:30

    How about this. First define a small helper method:

    private static Tuple mergeTwo(Tuple left, Tuple right) {
        int[] leftArray = left.getData();
        int[] rightArray = right.getData();
        int[] result = new int[leftArray.length + rightArray.length];
        System.arraycopy(leftArray, 0, result, 0, leftArray.length);
        System.arraycopy(rightArray, 0, result, leftArray.length, rightArray.length);
        return new Tuple(left.getDirection(), result);
    }
    

    This is close to your concat/merge I guess, but a single one. Basically a way to merge two Tuple(s) together.

    And a helper method to produce the needed Collector, you can put this into a utility so that it can be re-used:

    private static Collector> mergedTuplesCollector() {
        class Acc {
    
            ArrayDeque deque = new ArrayDeque<>();
    
            void add(Tuple elem) {
                Tuple head = deque.peek();
                if (head == null || head.getDirection() != elem.getDirection()) {
                    deque.offerFirst(elem);
                } else {
                    deque.offerFirst(mergeTwo(deque.poll(), elem));
                }
            }
    
            Acc merge(Acc right) {
    
                Tuple lastLeft = deque.peekLast();
                Tuple firstRight = right.deque.peekFirst();
    
                if (lastLeft.getDirection() == firstRight.getDirection()) {
                    deque.offerLast(mergeTwo(deque.pollLast(), right.deque.pollFirst()));
                } else {
                    deque.addAll(right.deque);
                }
    
                return this;
            }
    
            public List finisher() {
                return new ArrayList<>(deque);
            }
    
        }
        return Collector.of(Acc::new, Acc::add, Acc::merge, Acc::finisher);
    }
    

    And usage would be, for example:

    List merged = tuples.stream()
                .parallel()
                .collect(mergedTuplesCollector());
    

提交回复
热议问题