Java – how to convert a character stream to a string stream pair?
I want to take a string and convert it into a word stream For example:
I have: {"a", "apple", "B", "banana", "C", "carrot"}
I want: {("a", "apple"), ("apple", "B"), ("B", "banana"), ("banana", "C")}
This is almost the same as zipping, as described in zipping streams using jdk8 with lambda (Java. Util. Stream. Streams. Zip)
However, this will produce: {(a, Apple), (B, banana), (C, carrot)}
The following code is valid, but obviously the wrong method (not thread safe, etc.):
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);});
Solution
If you:
>Don't like the idea of creating a list of all strings in the stream > don't want to use external libraries > like to dirty your hands
You can then use the Java 8 low-level flow builder streamsupport and splitter to create a way to group elements from the flow:
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()); } }
Methods and parameter naming are inspired by their Scala counterparts
Let's test:
Stream<String> testing = Stream.of("A","Carrot"); System.out.println(StreamUtils.sliding(2,testing).collect(Collectors.toList()));
How about not repeating elements:
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]