Estoy buscando un método en Java que devolverá un segmento de una matriz. Un ejemplo sería obtener la matriz de bytes que contiene los bytes 4 y 5 de una matriz de bytes. No quiero tener que crear una nueva matriz de bytes en la memoria de almacenamiento dinámico solo para hacerlo. En este momento tengo el siguiente código:
doSomethingWithTwoBytes(byte[] twoByteArray);
void someMethod(byte[] bigArray)
{
byte[] x = {bigArray[4], bigArray[5]};
doSomethingWithTwoBytes(x);
}
Me gustaría saber si había una manera de hacer simplemente doSomething(bigArray.getSubArray(4, 2))
donde 4 es el desplazamiento y 2 es la longitud, por ejemplo.
Respuestas:
Descargo de responsabilidad: esta respuesta no se ajusta a las restricciones de la pregunta:
( Honestamente, siento que mi respuesta es digna de borrarse. La respuesta de @ unique72 es correcta. Imma deja que esta edición se asiente por un momento y luego borraré esta respuesta ) .
No conozco una manera de hacer esto directamente con matrices sin asignación de montón adicional, pero las otras respuestas que usan un contenedor de sublista tienen asignación adicional solo para el contenedor, pero no la matriz, lo que sería útil en el caso de Una gran variedad.
Dicho esto, si uno busca la brevedad, el método de utilidad
Arrays.copyOfRange()
se introdujo en Java 6 (¿a finales de 2006?):fuente
copyOfRange
. Si fuera de código cerrado, tal vez podría haber pasado. :)Arrays.asList(myArray)
delega a newArrayList(myArray)
, que no copia la matriz sino que solo almacena la referencia. UsarList.subList(start, end)
después de eso haceSubList
que solo haga referencia a la lista original (que todavía solo hace referencia a la matriz). No se copia la matriz ni su contenido, solo se crea el contenedor, y todas las listas involucradas están respaldadas por la matriz original. (Pensé que sería más pesado).fuente
Arrays
una llamada confusaArrayList
, pero que realmente es unaList
matriz, a diferencia de lajava.util.ArrayList
que haría una copia. No hay nuevas asignaciones (del contenido de la lista) ni dependencias de terceros. Esta es, creo, la respuesta más correcta.byte[]
en su caso). Todo lo que obtendrás seríaList<byte[]>
. Y cambiarbyte[] bigArray
aByte[] bigArray
podría imponer una sobrecarga de memoria significativa.sun.misc.Unsafe
clase.Si está buscando un enfoque de alias de estilo de puntero, de modo que ni siquiera necesite asignar espacio y copiar los datos, entonces creo que no tiene suerte.
System.arraycopy()
copiará desde su origen hasta su destino, y se reclama la eficiencia de esta utilidad. Es necesario asignar la matriz de destino.fuente
array*copy*()
reutilizar la misma memoria? ¿No es exactamente lo contrario de lo que esperaría una persona que llama?Una forma es envolver la matriz
java.nio.ByteBuffer
, usar las funciones absolutas put / get y cortar el búfer para trabajar en una submatriz.Por ejemplo:
Tenga en cuenta que debe llamar a ambos
wrap()
yslice()
, dado quewrap()
solo afecta a las funciones put / get relativas, no a las absolutas.ByteBuffer
puede ser un poco difícil de entender, pero lo más probable es que se implemente de manera eficiente y valga la pena aprenderlo.fuente
StandardCharsets.UTF_8.decode(ByteBuffer.wrap(buffer, 0, readBytes))
Arrays.copyOfRange
?Arrays.copyOfRange
es probablemente más eficiente. En general, tendría que medir para su caso de uso específico.Utilice java.nio.Buffer's. Es un envoltorio liviano para buffers de varios tipos primitivos y ayuda a administrar el corte, la posición, la conversión, el pedido de bytes, etc.
Si sus bytes se originan en un Stream, los NIO Buffers pueden usar el "modo directo" que crea un buffer respaldado por recursos nativos. Esto puede mejorar el rendimiento en muchos casos.
fuente
Puede usar ArrayUtils.subarray en apache commons. No es perfecto, pero es un poco más intuitivo que
System.arraycopy.
El inconveniente es que introduce otra dependencia en su código.fuente
Veo que la respuesta subList ya está aquí, pero aquí hay un código que demuestra que es una verdadera sublista, no una copia:
Sin embargo, no creo que haya una buena manera de hacer esto directamente con las matrices.
fuente
fuente
Los
List
s le permiten usar y trabajar consubList
algo de forma transparente. Las matrices primitivas requieren que realice un seguimiento de algún tipo de límite de desplazamiento.ByteBuffer
s tienen opciones similares a las que escuché.Editar: si está a cargo del método útil, simplemente puede definirlo con límites (como se hace en muchos métodos relacionados con la matriz en Java):
Sin embargo, no está claro si trabaja en los elementos de la matriz, por ejemplo, si calcula algo y escribe el resultado.
fuente
Una opción sería pasar toda la matriz y los índices de inicio y fin, e iterar entre ellos en lugar de iterar sobre toda la matriz pasada.
fuente
Las referencias de Java siempre apuntan a un objeto. El objeto tiene un encabezado que, entre otras cosas, identifica el tipo concreto (por lo que los lanzamientos pueden fallar
ClassCastException
). Para las matrices, el inicio del objeto también incluye la longitud, los datos siguen inmediatamente después en la memoria (técnicamente, una implementación es libre de hacer lo que le plazca, pero sería una tontería hacer cualquier otra cosa). Por lo tanto, no puede; t tener una referencia que apunte en algún lugar de una matriz.En C, los punteros apuntan a cualquier lugar y a cualquier cosa, y puede apuntar al centro de una matriz. Pero no puede emitir o averiguar con seguridad cuánto dura la matriz. En D, el puntero contiene un desplazamiento en el bloque de memoria y la longitud (o, de manera equivalente, un puntero al final, no recuerdo qué hace realmente la implementación). Esto permite que D corte las matrices. En C ++ tendrías dos iteradores apuntando al inicio y al final, pero C ++ es un poco extraño así.
Así que volviendo a Java, no, no puedes. Como se mencionó, NIO le
ByteBuffer
permite ajustar una matriz y luego dividirla, pero ofrece una interfaz incómoda. Por supuesto, puedes copiar, lo que probablemente sea mucho más rápido de lo que piensas. Puede introducir su propiaString
abstracción similar que le permite cortar una matriz (la implementación actual de SunString
tiene unachar[]
referencia más un desplazamiento inicial y una longitud, la implementación de mayor rendimiento solo tienechar[]
).byte[]
es de bajo nivel, pero cualquier abstracción basada en la clase que usted ponga hará un desastre horrible de la sintaxis, hasta JDK7 (tal vez).fuente
substring
en HotSpot (olvide qué compilación cambió esto). ¿Por qué dice que JDK7 permitiría una mejor sintaxis que ByteBuffer?[]
notación de matriz en tipos definidos por el usuario, comoList
yByteBuffer
. Todavía@ unique72 responda como una función o línea simple, es posible que deba reemplazar Object, con el tipo de clase respectivo que desea 'cortar'. Se ofrecen dos variantes para satisfacer diversas necesidades.
fuente
¿Qué tal un
List
envoltorio delgado ?(No probado)
fuente
Byte
objetos para todos losbyte
valores se almacenan en caché. Por lo tanto, la sobrecarga del boxeo debería ser bastante lenta.Necesitaba iterar hasta el final de una matriz y no quería copiar la matriz. Mi enfoque fue hacer un Iterable sobre la matriz.
fuente
Esto es un poco más liviano que Arrays.copyOfRange: sin rango o negativo
fuente