在Java 8中,是否有ByteStream类?

sdg*_*sdh 37 java byte boxing java-8 java-stream

Java的8提供Stream<T>专业化的double,intlong:DoubleStream,IntStreamLongStream分别.但是,我byte文档中找不到相应的内容.

Java 8是否提供了一个ByteStream类?

Tag*_*eev 39

大多数与字节相关的操作会自动提升为int.例如,让我们考虑一个简单的方法,它bytebyte[]返回新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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,即使我们执行了两个byte变量的添加,它们也会扩展为int,您需要将结果强制转换为byte.在Java字节码最的byte-相关操作(除了阵列加载/存储和转换为字节)与32位整数指示(表示iadd,ixor,if_icmple等等).因此实际上可以将字节作为整数处理IntStream.我们只需要两个额外的操作:

  • 创建一个IntStreamfrom byte[]数组(扩大字节到整数)
  • 收集一个IntStreambyte[]阵列(使用(byte)流延)

第一个非常简单,可以像这样实现:

public static IntStream intStream(byte[] array) {
    return IntStream.range(0, array.length).map(idx -> array[idx]);
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以将这种静态方法添加到项目中并感到高兴.

将流收集到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();
}
Run Code Online (Sandbox Code Playgroud)

但是,由于同步,它有不必要的开销.特别是处理已知长度的流以减少分配和复制也是很好的.不过现在您可以将Stream API用于byte[]数组:

public static byte[] addStream(byte[] arr, byte addend) {
    return toByteArray(intStream(arr).map(b -> b+addend));
}
Run Code Online (Sandbox Code Playgroud)

我的StreamEx库在IntStreamEx类中具有这两个增强标准的操作IntStream,因此您可以像这样使用它:

public static byte[] addStreamEx(byte[] arr, byte addend) {
    return IntStreamEx.of(arr).map(b -> b+addend).toByteArray();
}
Run Code Online (Sandbox Code Playgroud)

内部toByteArray()方法使用简单的可调整大小的字节缓冲区,专门处理流是顺序的并且预先知道目标大小的情况.

  • `baos1.write(baos2.toByteArray(), 0, baos2.size())` 是一个不必要的复杂合并。首先,“toByteArray()”总是返回一个适当大小的数组,因此不需要“, 0, baos2.size()”。数组总是具有适当大小的原因是它总是返回新分配的数组。如果您想避免这种开销,请考虑使用“baos2.writeTo(baos1)”,它更短*而且*更高效。 (3认同)
  • 当然,`writoTo` 需要一个 `try...catch` 围绕它,所以 `{try{baos2.writeTo(baos1);}catch(IOException x){} }` 不短于 `baos1.write(baos2.toByteArray( ), 0, baos2.size())`,但它并没有明显变大(但效率更高)。“writeTo”必须声明“IOException”,因为您可以传递任意“OutputStream”作为参数。`write(byte[])` 方法尚未被覆盖,因此不幸的是,它具有通用的 `OutputStream.write(byte[])` 签名。提醒我[这个问题](http://stackoverflow.com/q/39648062/2711488)… (2认同)
  • @Kaplan 流不是存储结构。它是一个用于*处理*数据的工具,正如这个答案已经说过的那样,无论如何,在 Java 中“大多数与字节相关的操作都会自动提升为 int”。无论如何,考虑到当今的 CPU 具有 64 位宽的数据寄存器,这并没有什么坏处。这里的存储仍然是“byte[]”。 (2认同)

Tun*_*aki 33

不,它不存在.实际上,它没有明确地实现,以免混乱使用每个基本类型的大量类的Stream API.

引用一个邮件从布赖恩戈茨在OpenJDK的邮件列表:  

简答:不.

对于这些几乎从不使用的表格,每个JDK足迹的价值不再是另外的.如果我们添加了那些,有人会要求short,float或boolean.

换句话说,如果人们坚持认为我们拥有所有原始专业,那么我们就没有原始的专业化.哪个会比现状更糟糕.

  • 真的吗?字节流"几乎从不"使用?我想知道那个人生活在哪个星球上,因为在现实世界中,字节流无处不在. (53认同)
  • 我和@augurar在一起。有 `Arrays.stream(int[] array)`、`Arrays.stream(long[] array)` 和 `Arrays.stream(double[] array)` 但没有 `Arrays.stream(byte[] array)`或其他原始类型。其实我觉得挺可笑的。 (12认同)
  • @augurar你必须要问[那家伙](/sf/users/248716121/)肯定知道:-)我的印象是大多数开发人员都熟悉的那种字节流更多的是`ByteArrayInputStream` /`ByteArrayOutputStream`(用于I/O操作,批量数据处理等).这些对象在概念上与Java 8 Stream API的Stream`s完全不同,后者用于函数式编程. (5认同)
  • 啊,是的,很高兴看到我想要的东西没有实现,因为他们只是不喜欢它。 (4认同)
  • 每个人 - 1)你可以自己实现。2)您可以找到第三方实现。2a) 如果您找不到第 3 方实现,则意味着实际需要“ByteStream”的程度。 (2认同)