whatwg - En Java 8, ¿hay una clase ByteStream?
w3c html standards (2)
La mayoría de las operaciones relacionadas con bytes se promueven 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
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;
}
Vea, a pesar de que realizamos una adición de dos variables de
byte
, se amplían a
int
y necesita convertir el resultado de nuevo a
byte
.
En Java bytecode, la mayoría de las operaciones relacionadas con
byte
(excepto la carga / almacenamiento de
if_icmple
y la
if_icmple
a byte) se expresan con instrucciones de enteros 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:
-
Cree un
IntStream
desde laIntStream
debyte[]
(ensanchando bytes a ints) -
Recopile un
IntStream
en laIntStream
debyte[]
(usando el reparto(byte)
)
El primero es realmente fácil y puede implementarse así:
public static IntStream intStream(byte[] array) {
return IntStream.range(0, array.length).map(idx -> array[idx]);
}
Entonces puede agregar un método estático a su proyecto y ser feliz.
Recopilar la secuencia en la matriz de
byte[]
es más complicado.
Usando clases JDK estándar, 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 puede usar la API Stream para conjuntos 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 objetivo se conoce de antemano.
Java 8 proporciona especializaciones
Stream<T>
para
double
,
int
y
long
:
DoubleStream
,
IntStream
y
LongStream
respectivamente.
Sin embargo, no pude encontrar un equivalente para el
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 exigirí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. Lo cual sería peor que el status quo.