JavaRush /Java Blog /Random-IT /Le 10 domande principali sulle raccolte in Java
FedoraLinux
Livello 21
Москва

Le 10 domande principali sulle raccolte in Java

Pubblicato nel gruppo Random-IT
L'articolo è una traduzione dell'articolo " Le 10 domande principali sulle raccolte Java " . Di seguito sono riportate le domande più popolari sulle raccolte in Java, poste e discusse su Stackowerflow. Prima di rispondere a queste domande, sarebbe bene osservare il diagramma della gerarchia delle classi. 1. Quando utilizzare LinkedList anziché ArrayList? Un ArrayList è infatti un array; ai suoi elementi è possibile accedere direttamente tramite indice. Se l'array trabocca, ne diventa necessario uno nuovo con più spazio. Posizionare e spostare tutti gli elementi richiederà un tempo O(n). Inoltre, è necessario aggiungere e rimuovere elementi per spostare gli elementi esistenti nell'array. Questo è forse il più grande inconveniente dell'utilizzo di ArrayList. LinkedList è un doppio elenco di collegamenti di elementi. Pertanto, per accedere all'elemento al centro, devi cercare dall'inizio alla fine del foglio. D'altra parte, aggiungere e rimuovere un elemento in una LinkedList è più veloce perché queste operazioni modificano solo la lista stessa. I tempi peggiori vengono confrontati di seguito:
Metodo Lista di array Lista collegata
ottenere(indice) O(1) SU)
aggiungi(E) SU) O(1)
aggiungi(E, indice) SU) SU)
rimuovi (indice) SU) SU)
Iterator.remove() SU) O(1)
Iterator.add(E) SU) O(1)
Nonostante il tempo di esecuzione, l'utilizzo della memoria deve essere considerato individualmente per elenchi di grandi dimensioni. In una LinkedList, ogni nodo deve avere almeno due puntatori aggiuntivi per collegare il nodo precedente e successivo, mentre in un ArrayList è necessario solo un array di elementi. Ulteriori confronti tra elenchi ArrayList, LinkedList e Vector . 2. Equivalente efficiente per rimuovere elementi durante l'iterazione della raccolta L'unico modo corretto per modificare (rimuovere elementi) una raccolta durante l'iterazione è utilizzare Iterator.remove() . Ad esempio: L'errore più comune è: riceverai una ConcurrentModificationException durante l'esecuzione del codice precedente. Ciò accade perché l'iteratore è stato generato per spostarsi attraverso l'intero elenco, ma allo stesso tempo il foglio viene modificato chiamando Iterator.remove(). Come scritto nella documentazione per questa eccezione, Iterator itr = list.iterator(); while(itr.hasNext()) { // do something itr.remove(); } for(Integer i: list) { list.remove(i); }
"non è generalmente consentito che un thread modifichi una raccolta mentre un altro thread la sta eseguendo."
In generale, non è accettabile che un thread modifichi una raccolta mentre un altro thread la sta attraversando. 3. Come convertire List nell'array int[]? Il modo più semplice per farlo è utilizzare ArrayUtils , che si trova nella libreria Apache Commons Lang . int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0])); Non esiste una scorciatoia per questa espressione nel JDK. Ricorda che non puoi utilizzare List.toArray() perché questa espressione converte List in Integer[] (che non è un tipo primitivo). Il modo corretto sarebbe la seguente opzione: int[] array = new int[list.size()]; for(int i=0; i < list.size(); i++) { array[i] = list.get(i); } 4. Come convertire un array int[] in un elenco? Il modo più semplice è anche utilizzare ArrayUtils nella libreria Apache Commons Lang , come sopra. List list = Arrays.asList(ArrayUtils.toObject(array)); Inoltre, non esiste alcuna scorciatoia per questa espressione nel JDK. 5. Qual è il modo migliore per filtrare la raccolta? Puoi utilizzare pacchetti di terze parti come Guava o Apache Commons Lang per aumentare la funzionalità. Entrambi questi pacchetti hanno un metodo filter() (nella classe Collections2 di Guava e CollectionUtils di Apache). Il metodo filter() restituirà gli elementi che corrispondono al predicato specificato. In JDK tutto è più complicato. La buona notizia è che i predicati verranno aggiunti in Java 8 , ma per ora è necessario utilizzare Iterator per scorrere l'intera raccolta. Naturalmente puoi imitare il percorso seguito da Guava e Apache prendendo familiarità con la nuova interfaccia di Predicate. Ora possiamo utilizzare il seguente codice per filtrare la raccolta: 6. Come convertire facilmente List in Set? Esistono due modi per farlo, a seconda di come si desidera definire l'uguaglianza. La prima parte di codice inserisce l'elenco in un HashSet. Il duplicato in questo caso è determinato principalmente da hashCode(). In genere questo funzionerà. Ma se devi tenere conto del percorso di confronto, allora sarebbe meglio utilizzare la seconda parte del codice, dove puoi definire il tuo comparatore. 7. Come posso rimuovere elementi duplicati da un ArrayList? Questa domanda è in qualche modo correlata alla domanda precedente. Se l'ordine degli elementi nell'ArrayList non è importante per te, una mossa intelligente sarebbe posizionare il foglio in un Set per rimuovere i duplicati e quindi restituirlo all'Elenco. Di seguito è riportato un esempio. Se l'ordine degli elementi è importante per te, l'ordine può essere garantito inserendo l'elenco in un LinkedHashSet , che si trova nel JDK standard. 8. Raccolta ordinata int[] array = {1,2,3,4,5}; List list = new ArrayList (); for(int i: array) { list.add(i); } Iterator itr = list.iterator(); while(itr.hasNext()) { int i = itr.next(); if (i > 5) { // filter all ints bigger than 5 itr.remove(); } } public interface Predicate { boolean test(T o); } public static void filter(Collection collection, Predicate predicate) { if ((collection != null) && (predicate != null)) { Iterator itr = collection.iterator(); while(itr.hasNext()) { T obj = itr.next(); if (!predicate.test(obj)) { itr.remove(); } } } } filter(list, new Predicate () { public boolean test(Integer i) { return i <= 5; } }); Set set = new HashSet (list); Set set = new TreeSet (aComparator); set.addAll(list); ArrayList** list = ... // initial a list with duplicate elements Set set = new HashSet (list); list.clear(); list.addAll(set); Esistono diversi modi per supportare una raccolta ordinata in Java. Tutti forniscono una raccolta in ordine naturale o tramite un comparatore specificato. Nel caso dell'ordine naturale, è necessario implementare anche l' interfaccia Comparable sull'elemento.
  1. Collections.sort() può ordinare un elenco. Come indicato nella documentazione Java, questo ordinamento è stabile e garantisce prestazioni n log(n).
  2. PriorityQueue fornisce una coda ordinata. La differenza tra PriorityQueue e Collections.sort() è che PriorityQueue mantiene sempre l'ordine della coda, ma puoi ottenere solo il primo elemento della coda. Non puoi accedere in modo casuale a un elemento come PriorityQueue.get(4).
  3. Se non sono presenti duplicati nella raccolta, puoi selezionare TreeSet . Inoltre, come PriorityQueue, TreeSet mantiene sempre un set ordinato. Puoi ottenere l'elemento più piccolo o più grande da un TreeSet, ma non puoi comunque avere accesso casuale agli elementi.
In poche parole, Collections.sort() fornisce un elenco ordinato una tantum. PriorityQueue e TreeSet mantengono sempre una raccolta ordinata, al costo della mancanza di accesso indicizzato agli elementi. 9. Collections.emptyList() o nuova istanza La stessa domanda si applica a emptyMap() e emptySet(). Entrambi i metodi restituiscono un elenco vuoto, ma Collections.emptyList() è un elenco immutabile. Ciò significa che non è possibile aggiungere nuovi elementi ad una lista "vuota". In background, ogni chiamata al metodo Collections.emptyList() in realtà non crea una nuova istanza dell'elenco vuoto. Invece, riutilizzerà l'istanza vuota già esistente. Se hai familiarità con Singleton come modello di progettazione , dovresti capire cosa si intende. Questo dovrebbe darti prestazioni migliori se chiamato frequentemente. 10 Copia di una raccolta, Collections.copy() Esistono due modi per copiare un elenco di origine in un elenco di destinazione. Un modo è utilizzare il costruttore ArrayList. Un altro modo è utilizzare il metodo Collections.copy() . Avviso sulla prima riga: stiamo allocando un elenco che abbia almeno la stessa lunghezza dell'elenco originale, perché la documentazione Java sulle raccolte dice: ArrayList dstList = new ArrayList (srcList);
L'elenco di destinazione deve essere lungo almeno quanto l'elenco di origine.
Ciò significa che l'elenco finale non deve essere più breve di quello originale. Entrambi i metodi sono copie superficiali. Allora qual è la differenza tra questi due metodi? Innanzitutto, Collections.copy() non riallocherà la capacità della raccolta dstList, anche se dstList non ha spazio sufficiente per contenere tutti gli elementi di srcList. Invece, genererà IndexOutOfBoundsException . Ci si potrebbe chiedere se ci sia qualche vantaggio in questo. Il motivo è che ciò garantisce che il metodo venga eseguito in modo lineare nel tempo. Ciò è adatto anche quando si desidera riutilizzare gli array anziché riallocare la memoria nel costruttore ArrayList. Invece di una conclusione Se dopo aver letto l'articolo hai ancora domande, sentiti libero di farle nei commenti. Inoltre, se trovi qualche inesattezza nella traduzione o qualsiasi altro errore, scrivi al PM, verrà corretto e sarai ringraziato. Originale. ArrayList dstList = new ArrayList (srcList.size()); Collections.copy(dstList, srcList);
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION