如何将字符串流转换为字符串流对?

Nic*_*ian 6 java lambda java-8 java-stream

我想取一串字符串并将其转换为单词对流.例如:

我有: { "A", "Apple", "B", "Banana", "C", "Carrot" }

我想:{ ("A", "Apple"), ("Apple", "B"), ("B", "Banana"), ("Banana", "C") }.

这与使用带有lambda的JDK8的Zipping流中概述的Zipping几乎相同(java.util.stream.Streams.zip)

但是,这会产生: { (A, Apple), (B, Banana), (C, Carrot) }

以下代码有效,但显然是错误的方法(不是线程安全等):

static String buffered = null;

static void output(String s) {
    String result = null;
    if (buffered != null) {
        result = buffered + "," + s;
    } else {
        result = null;
    }

    buffered = s;
    System.out.println(result);
}

// ***** 

Stream<String> testing = Stream.of("A", "Apple", "B", "Banana", "C", "Carrot");
testing.forEach(s -> {output(s);});
Run Code Online (Sandbox Code Playgroud)

Hel*_*ira 4

如果你:

  1. 不喜欢使用流中的所有字符串创建列表的想法
  2. 不想使用外部库
  3. 喜欢把手弄脏

然后,您可以使用 Java 8 低级流构建器创建一个方法来对流中的元素进行分组,StreamSupport并且Spliterator

class StreamUtils {
    public static<T> Stream<List<T>> sliding(int size, Stream<T> stream) {
        return sliding(size, 1, stream);
    }

    public static<T> Stream<List<T>> sliding(int size, int step, Stream<T> stream) {
        Spliterator<T> 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<List<T>>(estimateSize, spliterator.characteristics()) {
                    List<T> buffer = new ArrayList<>(size);

                    @Override
                    public boolean tryAdvance(Consumer<? super List<T>> consumer) {
                        while (buffer.size() < size && spliterator.tryAdvance(buffer::add)) {
                            // Nothing to do
                        }

                        if (buffer.size() == size) {
                            List<T> keep = new ArrayList<>(buffer.subList(step, size));
                            consumer.accept(buffer);
                            buffer = keep;
                            return true;
                        }
                        return false;
                    }
                }, stream.isParallel());
    }
}
Run Code Online (Sandbox Code Playgroud)

方法和参数命名受到 Scala 对应项的启发。

我们来测试一下:

Stream<String> testing = Stream.of("A", "Apple", "B", "Banana", "C", "Carrot");
System.out.println(StreamUtils.sliding(2, testing).collect(Collectors.toList()));
Run Code Online (Sandbox Code Playgroud)

[[A,苹果],[苹果,B],[B,香蕉],[香蕉,C],[C,胡萝卜]]

不重复元素怎么样:

Stream<String> testing = Stream.of("A", "Apple", "B", "Banana", "C", "Carrot");
System.out.println(StreamUtils.sliding(2, 2, testing).collect(Collectors.toList()));
Run Code Online (Sandbox Code Playgroud)

[[A,苹果],[B,香蕉],[C,胡萝卜]]

现在有无限Stream

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

[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]