Java 8分别为Stream<T>
,double
和int
:long
,DoubleStream
和IntStream
提供了LongStream
个专精。但是,我在the documentation中找不到byte
的等效词。
Java 8是否提供ByteStream
类?
答案 0 :(得分:34)
大多数与字节相关的操作会自动提升为int。例如,让我们考虑一个简单的方法,它为byte
数组的每个元素添加byte[]
常量,返回新的byte[]
数组(ByteStream
的潜在候选者):
public static byte[] add(byte[] arr, byte addend) {
byte[] result = new byte[arr.length];
int i=0;
for(byte b : arr) {
result[i++] = (byte) (b+addend);
}
return result;
}
请参阅,即使我们添加了两个byte
变量,它们也会扩展为int
,您需要将结果转换回byte
。在Java字节码中,大多数与byte
相关的操作(除了数组加载/存储和转换为字节)都用32位整数指令表示(iadd
,ixor
,if_icmple
等等)。因此,实际上可以将字节作为IntStream
的整数处理。我们只需要两个额外的操作:
IntStream
数组创建byte[]
(扩大字节到整数)IntStream
至byte[]
阵列(使用(byte)
演员)第一个非常简单,可以这样实现:
public static IntStream intStream(byte[] array) {
return IntStream.range(0, array.length).map(idx -> array[idx]);
}
因此,您可以将这种静态方法添加到项目中并感到高兴。
将流收集到byte[]
数组中更加棘手。使用标准JDK类,最简单的解决方案是ByteArrayOutputStream
:
public static byte[] toByteArray(IntStream stream) {
return stream.collect(ByteArrayOutputStream::new, (baos, i) -> baos.write((byte) i),
(baos1, baos2) -> baos1.write(baos2.toByteArray(), 0, baos2.size()))
.toByteArray();
}
然而,由于同步,它有不必要的开销。特别是处理已知长度的流以减少分配和复制也是很好的。不过现在您可以将Stream API用于byte[]
数组:
public static byte[] addStream(byte[] arr, byte addend) {
return toByteArray(intStream(arr).map(b -> b+addend));
}
我的StreamEx库在IntStreamEx
类中具有这两项操作,这些操作增强了标准IntStream
,因此您可以像这样使用它:
public static byte[] addStreamEx(byte[] arr, byte addend) {
return IntStreamEx.of(arr).map(b -> b+addend).toByteArray();
}
内部toByteArray()
方法使用简单的可调整大小byte buffer和specially handles,当流是顺序的并且目标大小事先已知时。
答案 1 :(得分:31)
不,它不存在。实际上,它实际上没有被实现,以免混乱使用大量类的Stream API来为每种基本类型。
在OpenJDK邮件列表中引用Brian Goetz的a mail:
简答:不。
对于这些表单,不值得另外100K +的JDK足迹 几乎从不使用。如果我们添加了那些,有人会 需求short,float或boolean。
换句话说,如果人们坚持我们拥有所有原始的东西 专业化,我们没有原始的专业化。哪一个 会比现状更糟糕。
答案 2 :(得分:1)
改用 com.google.common.primitives.Bytes.asList(byte[]).stream()。
答案 3 :(得分:0)
如果没有 ByteStream,请构建一个
Stream.Builder<Byte> builder = Stream.builder();
for( int i = 0; i < array.length; i++ )
builder.add( array[i] );
Stream<Byte> stream = builder.build();
...其中数组可以是byte[]
或Byte[]
类型的
答案 4 :(得分:0)
我喜欢这个解决方案,因为它是在运行时从byte []
开始的,
而不是构建一个集合,然后从一个集合中流式传输。
我相信每次只会对流产生一个字节。
byte [] bytes =_io.readAllBytes(file);
AtomicInteger ai = new AtomicInteger(0);
Stream.generate(() -> bytes[ai.getAndIncrement()]).limit(bytes.length);
但是由于AtomicInteger的同步瓶颈,这非常慢,所以回到命令式循环!