如何将字符串流转换为字符串流对? [英] How can I convert a Stream of Strings to Stream of String pairs?
问题描述
我想获取一串字符串并将其转换为字对流。例如:
I want to take a stream of strings and turn it into a stream of word pairs. eg:
我有: {A,Apple,B,Banana,C,Carrot }
我想: {(A,Apple),(Apple,B ),(B,香蕉),(香蕉,C)}
。
这几乎是与Zipping相同,如使用Zipping流中所述JDK8 with lambda(java.util.stream.Streams.zip)
This is nearly the same as Zipping, as outlined at Zipping streams using JDK8 with lambda (java.util.stream.Streams.zip)
然而,这会产生:
{( A,Apple),(B,Banana),(C,Carrot)}
以下代码有效,但显然是错误的方式这样做(不是线程安全等等):
The following code works, but is clearly the wrong way to do it (not thread safe etc 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);});
推荐答案
如果您:
- 不喜欢用流中的所有字符串创建列表的想法
- 不想使用外部库
- 喜欢弄脏你的手
然后你可以创建一个方法来分组元素使用Java 8低级流构建器的流 StreamSupport
和 Spliterator
:
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<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对应物。
Methods and parameters naming was inspired in their Scala counterparts.
让我们测试一下:
Stream<String> testing = Stream.of("A", "Apple", "B", "Banana", "C", "Carrot");
System.out.println(StreamUtils.sliding(2, testing).collect(Collectors.toList()));
[[A,Apple],[Apple,B],[ B,香蕉],[香蕉,C],[C,胡萝卜]]
[[A, Apple], [Apple, B], [B, Banana], [Banana, C], [C, Carrot]]
如何不重复元素:
Stream<String> 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]]
[[A, Apple], [B, Banana], [C, Carrot]]
现在有了无限的 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]
[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]
这篇关于如何将字符串流转换为字符串流对?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!