2010-08-03 18 views
41

Ho una libreria di classi, che lavora con i miei dati, che vengono letti nel buffer. È possibile in qualche modo evitare di copiare gli array più e più volte, passando parti di dati sempre più in profondità nei metodi di elaborazione? Beh, suona strano, ma nel mio caso particolare, c'è uno scrittore speciale, che divide i dati in blocchi e li scrive individualmente in posizioni diverse, quindi esegue semplicemente System.arraycopy, ottiene ciò di cui ha bisogno e chiama lo scrittore sottostante, con quello nuovo sottoarray. E questo succede molte volte. Qual è l'approccio migliore per refactoring di tale codice?Come ottenere un sotto array di array in Java, senza copiare i dati?

+0

Che ne dici di fare qualche magia JNI in C++? Potrebbe essere un disastro dal GC POV. –

+0

possibile duplicato di [Afferra un segmento di un array in Java senza creare un nuovo array su heap] (http://stackoverflow.com/questions/1100371/grab-a-segment-of-an-array-in-java- senza-creare-un-nuovo-array-on-heap) –

risposta

20

Molte classi in Java accettano un sottoinsieme di un array come parametro. Per esempio. Writer.write (char cbuf [], int off, int len). Forse questo è già sufficiente per il tuo caso.

+0

Questo è l'approccio più semplice, quindi proverò. –

-1

avere uno sguardo su Arrays.copyOfRange(***) metodi.

+12

Da javadoc: "Copia l'intervallo specificato dell'array specificato in un nuovo array", che non è ciò che l'OP desidera. – f1sh

2

Si potrebbe prendere lo stesso approccio della classe String prende; creare una classe per oggetti immutabili che sono costruiti da una matrice, un offset iniziale e uno sfasamento finale che offre l'accesso alla matrice secondaria. L'utente di un tale oggetto non deve conoscere la distinzione tra l'intero array o un sotto-array. Il costruttore non deve copiare la matrice, ma solo il riferimento dell'array e i suoi limiti.

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

Questo metodo non ti dà un array, ma un List, che è molto più flessibile.

+2

L'intero punto della domanda è di evitare di copiare. Cosa ne pensi di quanto sopra? – Theo

+59

Restituisce un elenco di dimensioni fisse supportato dall'array specificato. Accetto le tue scuse. –

+10

Oh! Grazie :) – Theo

1

Si potrebbe utilizzare (ArrayList) .subList (valore1, valore2) i belive, forse, che potrebbe aiutare nel vostro caso? Ovviamente, se vuoi usare un ArrayList.

+0

questa risposta non è stata già fornita? – dldnh

7

Non esiste un modo reale per avvolgere qualsiasi dato senza copiare e ricevere arra reale in Java. Non puoi semplicemente creare un nuovo array sulla memoria esistente. Hai fondamentalmente 2 opzioni:

  • Utilizzare metodi che possono accettare gamma di matrice. Questo era già raccomandato.
  • Utilizzare il wrapper che offre una sorta di astrazione vicina all'array ed è adatta a molte applicazioni. Sarà descritto di seguito.

Puoi svolgere gerarchia java.nio.Buffer classi, specialmente java.nio.ByteBuffer che offre tampone astrazione su tutta la matrice o sottointervalli. Spesso è ciò di cui le persone hanno bisogno. Questo offre anche molte abilità interessanti come il capovolgimento "zero copy" e la rappresentazione dell'area di byte flessibile.

Ecco esempio di confezionamento utilizzando java.nio.ByteBuffer. Questo dovrebbe essere molto vicino a quello che ti serve. Almeno per alcune operazioni.

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

Poi si può fare su qualsiasi bufByteBuffer operazione.

Solo un avviso, buf.array() restituisce l'originale a1 array (backend) con tutti gli elementi.

+0

Ah quindi anche se faccio buf = ByteBuffer.wrap (a1, 1, 2) ... buf.array() restituirà ancora {0, 0, 1, 0}. Quindi questa idea non può essere davvero utilizzata per ottenere un sottoarray? – Benitok

+0

Non è possibile ottenere una vera sottoarray senza copiare in Java. Quindi vengono utilizzati wrapper. L'elenco uno è stato illustrato prima e l'astrazione Buffer è un altro. Direi che è molto più utile sulla gamma di byte della memoria, ma per gli array di oggetti complessi. L'elenco è più comune. –

3

Non esiste alcun modo per dichiarare un sottoarray in Java se si utilizzano gli array incorporati come byte []. Il motivo è: la lunghezza dell'array è memorizzata con i dati, non con la dichiarazione del riferimento ad esso. Quindi un sottoarray che non copia i dati non ha posto dove può memorizzare la lunghezza! Quindi per i tipi di base è possibile utilizzare le copie di array di byte efficienti menzionate e per i tipi superiori (List) ci sono metodi disponibili.

Problemi correlati