En Java 8, ¿hay una clase ByteStream?

Java 8 proporciona especializaciones Stream para double , int y long : DoubleStream , IntStream y LongStream respectivamente. Sin embargo, no pude encontrar un equivalente para byte en la documentación .

¿Java 8 proporciona una clase ByteStream ?

No, no existe. En realidad, no se implementó explícitamente para no saturar la API de Stream con toneladas de clases para cada tipo primitivo.

Citando un correo de Brian Goetz en la lista de correo de OpenJDK:

Respuesta corta: no.

No vale más de 100K + de huella JDK para cada uno de estos formularios que casi nunca se usan. Y si agregamos esos, alguien demandaría short, float o boolean.

Dicho de otra manera, si la gente insistiera en que teníamos todas las especializaciones primitivas, no tendríamos especializaciones primitivas. Que sería peor que el status quo.

La mayoría de las operaciones relacionadas con bytes se promocionan automáticamente a int. Por ejemplo, consideremos el método simple que agrega una constante de byte a cada elemento de la matriz byte[] devuelve una nueva matriz de byte[] (candidato potencial para 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; } 

Mira, aunque realizamos una adición de dos variables de byte , se amplían a int y necesitas convertir el resultado a byte . En bytecode Java, la mayoría de las operaciones relacionadas con byte (excepto array carga / almacenamiento y conversión a byte) se expresan con instrucciones enteras de 32 bits ( iadd , ixor , if_icmple , etc.). Por lo tanto, prácticamente está bien procesar bytes como IntStream con IntStream . Solo necesitamos dos operaciones adicionales:

  • Crear un IntStream desde el byte[] array (ampliación de bytes a ints)
  • Reúna una IntStream de IntStream a byte[] (usando el molde (byte) )

El primero es realmente fácil y se puede implementar así:

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

Entonces puede agregar dicho método estático a su proyecto y ser feliz.

La recostackción de la secuencia en la matriz byte[] es más complicada. Usando clases estándar de JDK, la solución más simple es 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(); } 

Sin embargo, tiene una sobrecarga innecesaria debido a la sincronización. También sería bueno procesar especialmente las secuencias de longitud conocida para reducir las asignaciones y la copia. Sin embargo, ahora puedes usar Stream API para matrices de byte[] :

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

Mi biblioteca StreamEx tiene ambas operaciones en la clase IntStreamEx que mejora IntStream estándar, por lo que puede usarlo así:

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

Internamente, el método toByteArray() utiliza un búfer de bytes redimensionable simple y maneja especialmente el caso cuando la secuencia es secuencial y el tamaño de destino se conoce de antemano.

    Intereting Posts