ata*_*lor 12 java inputstream java-stream
我正在减少InputStreams像这样的流:
InputStream total = input.collect(
Collectors.reducing(
empty,
Item::getInputStream,
(is1, is2) -> new SequenceInputStream(is1, is2)));
Run Code Online (Sandbox Code Playgroud)
为了身份InputStream,我正在使用:
InputStream empty = new ByteArrayInputStream(new byte[0]);
Run Code Online (Sandbox Code Playgroud)
这有效,但有没有更好的方法来表示空InputStream?
Tho*_*sch 16
由于InputStream只有一种抽象方法read(),
public abstract int read() throws IOException返回:
数据的下一个字节,或者-1如果到达流的末尾.
通过匿名子类很容易创建一个空流.像这样:
InputStream empty = new InputStream() {
@Override
public int read() {
return -1; // end of stream
}
};
Run Code Online (Sandbox Code Playgroud)
但诚然,它比你的空代码更多ByteArrayInputStream.
从Java 11开始,您可以使用静态方法InputStream.nullInputStream():
返回不读取任何字节的新InputStream。返回的流最初是打开的。通过调用close()方法关闭流。随后对close()的调用无效。
我会走不同的路线。
通过减少大量InputStream实例(is1, is2) -> new SequenceInputStream(is1, is2)可能会创建一个深度不平衡的SequenceInputStream实例树,这会变得非常低效。
线性数据结构更合适:
InputStream total = new SequenceInputStream(
Collections.enumeration(input.map(Item::getInputStream).collect(Collectors.toList())));
Run Code Online (Sandbox Code Playgroud)
这将创建一个SequenceInputStream处理所有收集的输入流。由于这也本质上处理空列表情况,因此不再需要特殊的空InputStream实现。
但是当你查看的源代码时SequenceInputStream,你会发现这个类并不神奇,事实上,我们甚至可以通过不使用像Vectorand这样的古老类来做得更好Enumeration:
public class StreamInputStream extends InputStream {
final Spliterator<? extends InputStream> source;
final Consumer<InputStream> c = is -> in = Objects.requireNonNull(is);
InputStream in;
public StreamInputStream(Stream<? extends InputStream> sourceStream) {
(source = sourceStream.spliterator()).tryAdvance(c);
}
public StreamInputStream(InputStream first, InputStream second) {
this(Stream.of(first, second));
}
public int available() throws IOException {
return in == null? 0: in.available();
}
public int read() throws IOException {
if(in == null) return -1;
int b; do b = in.read(); while(b<0 && next());
return b;
}
public int read(byte b[], int off, int len) throws IOException {
if((off|len) < 0 || len > b.length - off) throw new IndexOutOfBoundsException();
if(in == null) return -1; else if(len == 0) return 0;
int n; do n = in.read(b, off, len); while(n<0 && next());
return n;
}
public void close() throws IOException {
closeCurrent();
}
private boolean next() throws IOException {
closeCurrent();
return source.tryAdvance(c);
}
private void closeCurrent() throws IOException {
if(in != null) try { in.close(); } finally { in = null; }
}
}
Run Code Online (Sandbox Code Playgroud)
除了更简单和更干净(它不需要像 那样的语句catch (IOException ex) { throw new Error("panic"); }),它还考虑了流的惰性:在遍历所有元素之前关闭时,它不会遍历剩余的流来关闭InputStream元素,因为它们通常不是即使在此时创建,因此不需要关闭。
现在流的创建很简单
InputStream total = new StreamInputStream(input.map(Item::getInputStream));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7246 次 |
| 最近记录: |