Reading the Java 8 docs it seems that it's intended java.util.stream.Stream could ultimately be backed by an I/O java.io.InputStream.
So, I wanted to read in a character stream and feed it into a map-reduce pipeline using the new features. I couldn't find any utility methods to do this, so I had to roll my own:
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);
}
Are there utility methods which could accomplish the same or similar?
I find that in cases like these, it's easier to implement Spliterator
rather than 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);
}
It's better to implement an IntStream
to avoid boxing. You can always turn the IntStream
into a Stream<Character>
with .mapToObj(i->(char) i)
You can create an IntStream
representing the characters using
new BufferedReader(r).lines().flatMapToInt(CharSequence::chars)
If it really has to be a (boxing) Stream<Character>
you can use mapToObj(c -> (char)c)
on the IntStream
:
public static Stream<Character> chars(Reader r) {
return new BufferedReader(r).lines().flatMapToInt(CharSequence::chars)
.mapToObj(c -> (char)c);
}
but for most cases
public static IntStream chars(Reader r) {
return new BufferedReader(r).lines().flatMapToInt(CharSequence::chars);
}
should be sufficient.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.