Java8:如何根据java.io.Reader创建java.util.stream.Stream<Character>
Java 8: How to create java.util.stream.Stream<Character> based on java.io.Reader
阅读 Java 8 篇文档,似乎 java.util.stream.Stream 最终可以得到 I/O java.io.InputStream.
的支持
所以,我想读入一个字符流,然后使用新功能将其送入 map-reduce 管道。我找不到任何实用方法来执行此操作,所以我不得不自己动手:
public static Stream<Character> charStream(Reader r) {
Iterator<Character> iter = new Iterator<Character>() {
Character nextChar = null;
@Override
public boolean hasNext() {
if (nextChar != null) {
return true;
} else {
try {
int readChar = r.read();
if(readChar == -1) {
return false;
}
nextChar = Character.valueOf((char) readChar);
return true;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
@Override
public Character next() {
if (nextChar != null || hasNext()) {
Character theChar = nextChar;
nextChar = null;
return theChar;
} else {
throw new NoSuchElementException();
}
}
};
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
iter, Spliterator.ORDERED | Spliterator.NONNULL), false);
}
是否有可以实现相同或相似的实用方法?
我发现在这种情况下,实施 Spliterator
比实施 Iterator
更容易:
public static IntStream charStream(Reader r) {
Spliterator.OfInt split = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE, Spliterator.ORDERED) {
@Override
public boolean tryAdvance(IntConsumer action) {
try {
int c = r.read();
if (c == -1) {
return false;
} else {
action.accept(c);
return true;
}
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
};
return StreamSupport.intStream(split, false);
}
最好实现一个 IntStream
以避免装箱。你总是可以把 IntStream
变成 Stream<Character>
和 .mapToObj(i->(char) i)
您可以创建一个 IntStream
来表示使用
的字符
new BufferedReader(r).lines().flatMapToInt(CharSequence::chars)
如果它真的必须是(拳击)Stream<Character>
你可以在 IntStream
上使用 mapToObj(c -> (char)c)
:
public static Stream<Character> chars(Reader r) {
return new BufferedReader(r).lines().flatMapToInt(CharSequence::chars)
.mapToObj(c -> (char)c);
}
但对于大多数情况
public static IntStream chars(Reader r) {
return new BufferedReader(r).lines().flatMapToInt(CharSequence::chars);
}
应该足够了。
阅读 Java 8 篇文档,似乎 java.util.stream.Stream 最终可以得到 I/O java.io.InputStream.
的支持所以,我想读入一个字符流,然后使用新功能将其送入 map-reduce 管道。我找不到任何实用方法来执行此操作,所以我不得不自己动手:
public static Stream<Character> charStream(Reader r) {
Iterator<Character> iter = new Iterator<Character>() {
Character nextChar = null;
@Override
public boolean hasNext() {
if (nextChar != null) {
return true;
} else {
try {
int readChar = r.read();
if(readChar == -1) {
return false;
}
nextChar = Character.valueOf((char) readChar);
return true;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
@Override
public Character next() {
if (nextChar != null || hasNext()) {
Character theChar = nextChar;
nextChar = null;
return theChar;
} else {
throw new NoSuchElementException();
}
}
};
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
iter, Spliterator.ORDERED | Spliterator.NONNULL), false);
}
是否有可以实现相同或相似的实用方法?
我发现在这种情况下,实施 Spliterator
比实施 Iterator
更容易:
public static IntStream charStream(Reader r) {
Spliterator.OfInt split = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE, Spliterator.ORDERED) {
@Override
public boolean tryAdvance(IntConsumer action) {
try {
int c = r.read();
if (c == -1) {
return false;
} else {
action.accept(c);
return true;
}
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
};
return StreamSupport.intStream(split, false);
}
最好实现一个 IntStream
以避免装箱。你总是可以把 IntStream
变成 Stream<Character>
和 .mapToObj(i->(char) i)
您可以创建一个 IntStream
来表示使用
new BufferedReader(r).lines().flatMapToInt(CharSequence::chars)
如果它真的必须是(拳击)Stream<Character>
你可以在 IntStream
上使用 mapToObj(c -> (char)c)
:
public static Stream<Character> chars(Reader r) {
return new BufferedReader(r).lines().flatMapToInt(CharSequence::chars)
.mapToObj(c -> (char)c);
}
但对于大多数情况
public static IntStream chars(Reader r) {
return new BufferedReader(r).lines().flatMapToInt(CharSequence::chars);
}
应该足够了。