Tho*_*orn 17 java io java-8 java-stream
我想换一个java.util.streams.Stream围绕InputStream处理一个字节或一次一个字符.我没有找到任何简单的方法来做到这一点.
请考虑以下练习:我们希望计算每个字母在文本文件中出现的次数.我们可以将它存储在一个数组中,以便tally[0]存储在文件中出现的次数,tally[1]存储出现的时间b等等.由于我找不到直接传输文件的方法,我这样做了:
int[] tally = new int[26];
Stream<String> lines = Files.lines(Path.get(aFile)).map(s -> s.toLowerCase());
Consumer<String> charCount = new Consumer<String>() {
public void accept(String t) {
for(int i=0; i<t.length(); i++)
if(Character.isLetter(t.charAt(i) )
tall[t.charAt(i) - 'a' ]++;
}
};
lines.forEach(charCount);
Run Code Online (Sandbox Code Playgroud)
有没有办法在不使用该lines方法的情况下完成此操作?我可以直接将每个字符作为Stream或Stream处理,而不是为文本文件中的每一行创建字符串.
我可以更直接地转换java.io.InputStream成java.util.Stream.stream?
Hol*_*ger 20
首先,您必须重新定义您的任务.您正在阅读字符,因此您不希望将InputStreama Reader转换为a Stream.
您不能重新实现发生的字符集转换,例如在a中InputStreamReader,通过Stream操作,因为在bytes InputStream和s 之间可以存在n:m映射char.
从a创建流Reader有点棘手.您将需要一个迭代器来指定获取项目和结束条件的方法:
PrimitiveIterator.OfInt it=new PrimitiveIterator.OfInt() {
int last=-2;
public int nextInt() {
if(last==-2 && !hasNext())
throw new NoSuchElementException();
try { return last; } finally { last=-2; }
}
public boolean hasNext() {
if(last==-2)
try { last=reader.read(); }
catch(IOException ex) { throw new UncheckedIOException(ex); }
return last>=0;
}
};
Run Code Online (Sandbox Code Playgroud)
获得迭代器后,您可以使用spliterator的绕行创建流并执行所需的操作:
int[] tally = new int[26];
StreamSupport.intStream(Spliterators.spliteratorUnknownSize(
it, Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false)
// now you have your stream and you can operate on it:
.map(Character::toLowerCase)
.filter(c -> c>='a'&&c<='z')
.map(c -> c-'a')
.forEach(i -> tally[i]++);
Run Code Online (Sandbox Code Playgroud)
请注意,虽然迭代器更为常见,但实现新Spliterator接口可以直接简化操作,因为它不需要在两个可以按任意顺序调用的方法之间维护状态.相反,我们只有一个tryAdvance方法可以直接映射到一个read()调用:
Spliterator.OfInt sp = new Spliterators.AbstractIntSpliterator(1000L,
Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) {
public boolean tryAdvance(IntConsumer action) {
int ch;
try { ch=reader.read(); }
catch(IOException ex) { throw new UncheckedIOException(ex); }
if(ch<0) return false;
action.accept(ch);
return true;
}
};
StreamSupport.intStream(sp, false)
// now you have your stream and you can operate on it:
…
Run Code Online (Sandbox Code Playgroud)
但请注意,如果你改变主意并愿意使用,Files.lines你可以拥有更轻松的生活:
int[] tally = new int[26];
Files.lines(Paths.get(file))
.flatMapToInt(CharSequence::chars)
.map(Character::toLowerCase)
.filter(c -> c>='a'&&c<='z')
.map(c -> c-'a')
.forEach(i -> tally[i]++);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
23090 次 |
| 最近记录: |