我想取一串字符串并将其转换为单词对流.例如:
我有:{“A”,“Apple”,“B”,“Banana”,“C”,“Carrot”}
我想要:{(“A”,“Apple”),(“Apple”,“B”),(“B”,“Banana”),(“Banana”,“C”)}.
这与Zipping几乎相同,如Zipping streams using JDK8 with lambda (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);});
解决方法
如果你:
>不喜欢创建包含流中所有字符串的列表的想法
>不想使用外部库
>喜欢弄脏你的手
然后,您可以使用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()); } }
方法和参数命名的灵感来自他们的Scala对应物.
我们来测试一下:
Stream<String> testing = Stream.of("A","Carrot"); System.out.println(StreamUtils.sliding(2,testing).collect(Collectors.toList()));
[[A,Apple],[Apple,B],[B,Banana],[Banana,C],[C,Carrot]]
不重复元素怎么样:
Stream<String> testing = Stream.of("A",2,Carrot]]现在有一个无限的流:
StreamUtils.sliding(5,Stream.iterate(0,n -> n + 1)) .limit(5) .forEach(System.out::println);[0,3,4] [1,4,5] [2,5,6] [3,6,7] [4,7,8]