在Java 8中,是否有ByteStream类?

时间:2015-09-08 13:54:18

标签: java java-8 byte java-stream boxing

Java 8分别为Stream<T>doubleintlongDoubleStreamIntStream提供了LongStream个专精。但是,我在the documentation中找不到byte的等效词。

Java 8是否提供ByteStream类?

5 个答案:

答案 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位整数指令表示(iaddixorif_icmple等等)。因此,实际上可以将字节作为IntStream的整数处理。我们只需要两个额外的操作:

  • IntStream数组创建byte[](扩大字节到整数)
  • 收集IntStreambyte[]阵列(使用(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 bufferspecially 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的同步瓶颈,这非常慢,所以回到命令式循环!