2010-08-03 21 views
41

Tengo una biblioteca de clases, trabajando con mis datos, que se están leyendo en el búfer. ¿Es posible de alguna manera evitar copiar matrices una y otra vez, pasando partes de datos cada vez más profundamente en los métodos de procesamiento? Bueno, suena extraño, pero en mi caso particular, hay un escritor especial, que divide los datos en bloques y los escribe individualmente en diferentes ubicaciones, por lo que solo realiza System.arraycopy, obtiene lo que necesita y llama al escritor subyacente, con ese nuevo subarreglo. Y esto sucede muchas veces. ¿Cuál es el mejor enfoque para refactorizar dicho código?¿Cómo obtener una matriz secundaria de matriz en Java, sin copiar datos?

+0

¿Qué tal hacer magia JNI en C++? Podría ser un desastre del GC POV. –

+0

posible duplicado de [Toma un segmento de una matriz en Java sin crear una nueva matriz en el montón] (http://stackoverflow.com/questions/1100371/grab-a-segment-of-an-array-in-java- without-creating-a-new-array-on-heap) –

Respuesta

20

Muchas clases en Java aceptan un subconjunto de matrices como parámetro. P.ej. Writer.write (char cbuf [], int off, int len). Tal vez esto ya sea suficiente para su uso.

+0

Este es el enfoque más simple, así que lo intentaré. –

-1

Eche un vistazo a los métodos Arrays.copyOfRange(***).

+12

De javadoc: "Copia el rango especificado de la matriz especificada en una nueva matriz", que no es lo que quiere el OP. – f1sh

2

Puede tomar el mismo enfoque que toma la clase String; crea una clase para objetos inmutables que se construyen a partir de una matriz, un desplazamiento inicial y una compensación final que ofrece acceso a la sub-matriz. El usuario de tal objeto no tiene que saber la distinción entre la matriz completa o una sub-matriz. El constructor no tiene que copiar la matriz, solo almacena la referencia de la matriz y sus límites.

54
Arrays.asList(array).subList(x, y). 

Este método no le da una matriz, sino una List, que es mucho más flexible.

+2

El objetivo de la pregunta es evitar copiar. ¿Qué crees que hace lo de arriba? – Theo

+59

Devuelve una lista de tamaño fijo respaldada por la matriz especificada. Acepto tu disculpa. –

+10

¡Oh! Gracias :) – Theo

1

Puede usar (ArrayList) .subList (value1, value2) Creo, ¿podría ayudarlo en su caso? Eso es, por supuesto, si quiere usar un ArrayList.

+0

¿esta respuesta aún no se ha dado? – dldnh

7

No hay manera real de ajustar los datos sin copiar y recibir arra real y en Java. Simplemente no puede crear una nueva matriz sobre la memoria existente. Tiene básicamente 2 opciones:

  • Utilice métodos que puedan aceptar el rango de la matriz. Esto ya fue recomendado.
  • Utilice un contenedor que ofrezca algún tipo de abstracción que esté cerca de la matriz y que sea adecuado para muchas aplicaciones. Se describirá a continuación.

Usted puede utilizar java.nio.Buffer clases jerarquía, especialmente java.nio.ByteBuffer que ofrece la abstracción búfer en la matriz de todo o sub-intervalos. A menudo es lo que las personas necesitan. Esto también ofrece muchas habilidades interesantes como flip 'cero copia' y representación de área de bytes flexible.

Aquí hay un ejemplo de envoltura usando java.nio.ByteBuffer. Esto debería estar muy cerca de lo que necesita. Al menos para algunas operaciones.

byte [] a1 = {0, 0, 1, 0}; 
ByteBuffer buf = ByteBuffer.wrap(a1,1,2); 

Entonces usted puede hacer en cualquier operación bufByteBuffer.

Solo una advertencia, buf.array() devuelve el original a1 array (backend) con todos los elementos.

+0

Ah, incluso si lo hago buf = ByteBuffer.wrap (a1, 1, 2) ... buf.array() todavía devolverá {0, 0, 1, 0}. ¿Entonces esta idea realmente no se puede usar para obtener un subcampo? – Benitok

+0

No se puede obtener una sub-matriz real sin copiar en Java. Entonces se usan envoltorios. La lista uno fue ilustrada antes y la abstracción del buffer es otra. Yo diría que es mucho más útil sobre el rango de bytes de memoria, pero para los conjuntos de objetos complejos La lista es más común. –

3

No hay manera de declarar un subcampo en Java si usa matrices integradas como byte []. La razón es: la longitud de la matriz se almacena con los datos, no con la declaración de la referencia a la misma. ¡Por lo tanto, un subcampo que no copia los datos no tiene lugar donde pueda almacenar la longitud! Por lo tanto, para tipos básicos puede usar las copias de matriz de bytes eficientes mencionadas y para los tipos superiores (Lista) hay métodos disponibles.

Cuestiones relacionadas