How can I convert a Stream of Strings to Stream of String pairs?

前端 未结 4 1798
说谎
说谎 2021-01-12 20:43

I want to take a stream of strings and turn it into a stream of word pairs. eg:

I have: { \"A\", \"Apple\", \"B\", \"Banana\", \"C\", \"Carrot\" }

4条回答
  •  借酒劲吻你
    2021-01-12 21:09

    If you:

    1. Don't like the idea of creating a list with all strings from your stream
    2. Don't want to use external libraries
    3. Like to get your hands dirty

    Then you can create a method to group elements from a stream using Java 8 low-level stream builders StreamSupport and Spliterator:

    class StreamUtils {
        public static Stream> sliding(int size, Stream stream) {
            return sliding(size, 1, stream);
        }
    
        public static Stream> sliding(int size, int step, Stream stream) {
            Spliterator spliterator = stream.spliterator();
            long estimateSize;
    
            if (!spliterator.hasCharacteristics(Spliterator.SIZED)) {
                estimateSize = Long.MAX_VALUE;
            } else if (size > spliterator.estimateSize()) {
                estimateSize = 0;
            } else {
                estimateSize = (spliterator.estimateSize() - size) / step + 1;
            }
    
            return StreamSupport.stream(
                    new Spliterators.AbstractSpliterator>(estimateSize, spliterator.characteristics()) {
                        List buffer = new ArrayList<>(size);
    
                        @Override
                        public boolean tryAdvance(Consumer> consumer) {
                            while (buffer.size() < size && spliterator.tryAdvance(buffer::add)) {
                                // Nothing to do
                            }
    
                            if (buffer.size() == size) {
                                List keep = new ArrayList<>(buffer.subList(step, size));
                                consumer.accept(buffer);
                                buffer = keep;
                                return true;
                            }
                            return false;
                        }
                    }, stream.isParallel());
        }
    }
    

    Methods and parameters naming was inspired in their Scala counterparts.

    Let's test it:

    Stream testing = Stream.of("A", "Apple", "B", "Banana", "C", "Carrot");
    System.out.println(StreamUtils.sliding(2, testing).collect(Collectors.toList()));
    

    [[A, Apple], [Apple, B], [B, Banana], [Banana, C], [C, Carrot]]

    What about not repeating elements:

    Stream testing = Stream.of("A", "Apple", "B", "Banana", "C", "Carrot");
    System.out.println(StreamUtils.sliding(2, 2, testing).collect(Collectors.toList()));
    

    [[A, Apple], [B, Banana], [C, Carrot]]

    And now with an infinite Stream:

    StreamUtils.sliding(5, Stream.iterate(0, n -> n + 1))
            .limit(5)
            .forEach(System.out::println);
    

    [0, 1, 2, 3, 4]
    [1, 2, 3, 4, 5]
    [2, 3, 4, 5, 6]
    [3, 4, 5, 6, 7]
    [4, 5, 6, 7, 8]

提交回复
热议问题