2013-01-11 13 views
7

In questo esempio di codice da pagina 114 del The Well-Grounded Java Developer, l'ultima riga:passare la matrice di dimensioni pari a zero, salvare l'assegnazione?

Update[] updates = lu.toArray(new Update[0]); 

contiene la nota: Passo gamma di dimensioni pari a zero, salvo allocazione

List<Update> lu = new ArrayList<Update>(); 
String text = ""; 
final Update.Builder ub = new Update.Builder(); 
final Author a = new Author("Tallulah"); 

for (int i=0; i<256; i++) { 
    text = text + "X"; 
    long now = System.currentTimeMillis(); 
    lu.add(ub.author(a).updateText(text).createTime(now).build()); 
    try { 
    Thread.sleep(1); 
    } catch (InterruptedException e) { 
    } 
} 

Collections.shuffle(lu); 
Update[] updates = lu.toArray(new Update[0]); 

Cosa allocazione è questo risparmio, Esattamente?

Javadoc per List#toArray(T[] a) cita:

Se l'elenco si inserisce nella matrice specificata, viene ivi restituito. Altrimenti, un nuovo array è allocato con il tipo di runtime dell'array specificato e la dimensione di questa lista.

Quale è quello che ho ricordato: se la matrice passata a toArray(T[] a) non può corrispondere a tutto nella lista, viene assegnato un nuovo array. Chiaramente, vi sono 256 elementi nella lista, che non può inserirsi in un array di dimensione 0, quindi una nuova matrice deve essere allocato all'interno del metodo, giusto?

Quindi è quella nota non è corretto? O c'è qualcos'altro?

+6

In realtà, è meglio, imho, fare 'lu.toArray (nuovo aggiornamento [lu.size()])', ma ... – fge

+1

Probabilmente un errore di battitura e dovrebbe significare "allocazione sicura"? Nel senso che è lasciato a 'toArray()' per "tranquillamente" creare l'array di dimensioni appropriate e tipizzate correttamente ... –

+0

BTW Ho cenato con uno degli autori, ieri sera. ;) –

risposta

2

Uscendo da @Andreas commento sulla domanda, penso che sia un errore di battitura, e dovrebbe fare:

passare la matrice di dimensione zero, sicuro assegnazione.

Perché se non si passa nulla al metodo, si finirà per chiamare il sovraccarico di no-argomento List#toArray()!

Ciò restituire un Object[] (anche se sarebbe contenere altro che Update casi) e richiederebbe la modifica del tipo di variabile updates, quindi l'ultima riga diventerebbe:

Object[] updates = lu.toArray(); 

E poi ogni volta che si voleva per eseguire un'iterazione e utilizzare gli elementi di quell'array, devi eseguirne il cast su Update.

Fornitura dell'array chiama il metodo List#toArray(T[] a), che restituisce un <T> T[]. Questo array viene reificato per sapere che si tratta di un array di istanze Update.

Così fornendo una matrice vuota di risultati Aggiornamenti in un aggiornamento [] di ritorno dalla chiamata toArray, non un oggetto []. Questa è un'assegnazione molto più sicura - ! La parola "salva" nella nota deve essere un refuso!

... questo consumato modo troppo sforzo mentale. Pubblicheremo link a questo nei forum del libro in modo che possano correggerlo.

+0

Link per postare sul sito di manning: http://www.manning-sandbox.com/thread.jspa?threadID=54973&stqc=true –

+1

Ciao! Sono il coautore - grazie per aver raccolto questo tipo - anzi dovrebbe dire che è sicuro - spero che ti piaccia il resto del libro! –

+0

Wow, non me l'aspettavo! Mi sto decisamente godendo il libro! –

3

Chiaramente, ci sono 256 elementi nell'elenco, che non possono essere inseriti in una matrice di dimensione 0, quindi un nuovo array deve essere allocato all'interno del metodo, giusto?

sì.


È possibile utilizzare

private static final Update NO_UPDATES = { } 

lu.toArray(NO_UPDATES); 

tuttavia ciò dovrebbe aiutare solo se si prevede che l'elenco di essere tipicamente 0 lunghezza.

In generale, vorrei lo stesso approccio fge

lu.toArray(new Update[lu.size()]); 

Nel vostro caso specifico si conosce la dimensione in anticipo in modo che si può fare

Update[] updates = new Update[256]; 
String text = ""; 
final Update.Builder ub = new Update.Builder(); 
final Author a = new Author("Tallulah"); 

long now = System.currentTimeMillis(); 
for (int i=0; i<updates.length; i++) 
    updates[i] = ub.author(a).updateText(text += 'X').createTime(now++).build(); 

Collections.shuffle(Arrays.asList(updates)); 
+0

Il codice potrebbe (e dovrebbe) usa un array di dimensioni adeguate, sì. Ma la domanda era di spiegare la nota. –

+0

Aggiornato la mia risposta;) –

+1

Ora avrò malincuore Peter ora ;-) - le onde a Peter - il grande convo l'altra sera BTW, sto ancora cercando un SSD più lento per quei test! –

0

Si risparmia l'allocazione, confrontandole con toArray(new Update[255]) o toArray(new Update[1000])

+0

Puoi spiegare ulteriormente ?. Non penso che salvi nulla. Un array di dimensioni 255 è troppo piccolo e quindi dovrebbe essere riallocato all'interno della chiamata al metodo. Un array di 1000 non dovrebbe essere allocato, ma spreca 744 slot di riferimento in memoria. Una matrice di 256 è la dimensione corretta da allocare, per risposta di @Peter Lawrey, tuttavia questo non spiega la nota. –

Problemi correlati