Riepilogo Big-O per le implementazioni di Java Collections Framework? [chiuso]


164

Potrei insegnare presto un "corso crash Java". Anche se è probabilmente lecito ritenere che i membri del pubblico conosceranno la notazione Big-O, probabilmente non è lecito ritenere che conosceranno l'ordine delle varie operazioni sulle varie implementazioni della raccolta.

Potrei impiegare del tempo per generare una matrice di riepilogo, ma se è già di dominio pubblico da qualche parte, mi piacerebbe sicuramente riutilizzarla (con il giusto credito, ovviamente.)

Qualcuno ha qualche puntatore?


Ecco un link che ho trovato utile durante la discussione di alcuni oggetti Java molto comuni e quanto costano le loro operazioni usando la notazione Big-O. objectissues.blogspot.com/2006/11/…
Nick,

Sebbene non siano di dominio pubblico, l'eccellente Java Generics and Collections di Maurice Naftalin e Philip Wadler elenca panoramiche sulle informazioni di runtime nei suoi capitoli sulle diverse classi di raccolta.
Fabian Steeg,

1
Questo benchmark delle prestazioni sarebbe di qualche utilità?
ThreaT

Risposte:


149

Questo sito Web è abbastanza buono ma non specifico per Java: http://bigocheatsheet.com/ Ecco un'immagine nel caso in cui questo link non funzionasse


27
Ed è per questo che non utilizziamo gli URL come risposte. Quel documento / server, per quanto posso dire, non è più disponibile!
Jason Mock

1
@Ben J I collegamenti non funzionano più
Vikas V,

Anche i collegamenti all'archivio Web sono stati interrotti.
MikeFHay,

Sembra che siano stati aggiunti nuovi URL funzionanti. Grazie per lo sforzo, è molto utile.
Tejas C

1
@AndreaZilio LinkedList.remove (Object) è un tempo costante, supponendo che tu conosca già il vicino. Se non conosci il vicino, è tempo lineare di trovarlo per primo.
Paul Evans,

217

Il libro Java Generics and Collections contiene queste informazioni (pagine: 188, 211, 222, 240).

Elenca le implementazioni:

                      get  add  contains next remove(0) iterator.remove
ArrayList             O(1) O(1) O(n)     O(1) O(n)      O(n)
LinkedList            O(n) O(1) O(n)     O(1) O(1)      O(1)
CopyOnWrite-ArrayList O(1) O(n) O(n)     O(1) O(n)      O(n)

Imposta le implementazioni:

                      add      contains next     notes
HashSet               O(1)     O(1)     O(h/n)   h is the table capacity
LinkedHashSet         O(1)     O(1)     O(1) 
CopyOnWriteArraySet   O(n)     O(n)     O(1) 
EnumSet               O(1)     O(1)     O(1) 
TreeSet               O(log n) O(log n) O(log n)
ConcurrentSkipListSet O(log n) O(log n) O(1)

Implementazioni cartografiche:

                      get      containsKey next     Notes
HashMap               O(1)     O(1)        O(h/n)   h is the table capacity
LinkedHashMap         O(1)     O(1)        O(1) 
IdentityHashMap       O(1)     O(1)        O(h/n)   h is the table capacity 
EnumMap               O(1)     O(1)        O(1) 
TreeMap               O(log n) O(log n)    O(log n) 
ConcurrentHashMap     O(1)     O(1)        O(h/n)   h is the table capacity 
ConcurrentSkipListMap O(log n) O(log n)    O(1)

Implementazione della coda:

                      offer    peek poll     size
PriorityQueue         O(log n) O(1) O(log n) O(1)
ConcurrentLinkedQueue O(1)     O(1) O(1)     O(n)
ArrayBlockingQueue    O(1)     O(1) O(1)     O(1)
LinkedBlockingQueue   O(1)     O(1) O(1)     O(1)
PriorityBlockingQueue O(log n) O(1) O(log n) O(1)
DelayQueue            O(log n) O(1) O(log n) O(1)
LinkedList            O(1)     O(1) O(1)     O(1)
ArrayDeque            O(1)     O(1) O(1)     O(1)
LinkedBlockingDeque   O(1)     O(1) O(1)     O(1)

La parte inferiore di javadoc per il pacchetto java.util contiene alcuni buoni collegamenti:


3
Devi specificare per quale scenario sono quelle figure, ad esempio, l'eliminazione da Arraylist potrebbe richiedere O (n), se elimini l'elemento al centro o alla fine dell'array.
Popeye,

@popeye non è O di solito il caso peggiore?
Yassin Hajaj,

Come menzionato da @Popeye, dovrebbe esserci una descrizione chiara del caso in cui la risposta riguarda. Il caso può essere medio / peggiore per complessità temporale. Sembra che la risposta si riferisca a un caso "medio" per tutti i DS.
Yashwin Munsadwala,

12

I Javadocs di Sun per ogni classe di raccolta generalmente ti diranno esattamente quello che vuoi. HashMap , ad esempio:

Questa implementazione fornisce prestazioni a tempo costante per le operazioni di base (get e put), supponendo che la funzione hash disponga correttamente gli elementi tra i bucket. L'iterazione nelle viste di raccolta richiede un tempo proporzionale alla "capacità" dell'istanza di HashMap (il numero di bucket) più la sua dimensione (il numero di mapping di valori-chiave).

TreeMap :

Questa implementazione fornisce costi di log (n) di tempo garantiti per le operazioni IncludesKey, get, put e remove.

TreeSet :

Questa implementazione fornisce log (n) tempi di costo garantiti per le operazioni di base (aggiungi, rimuovi e contiene).

(enfatizzare il mio)


Non sono d'accordo con la parte HashMap. Conosco la posizione di Sun, ma ... get ad esempio deve chiamare obj.equals (chiave), che potrebbe essere lineare nella dimensione degli oggetti contenuti. Considera che in genere devi leggere i campi per questo confronto. Le eccezioni sarebbero numeri interi o stringhe (internati) ???
Sorvolato il

Prima di tutto, se si sbagliassero, non dovrebbe essere troppo difficile per te creare un test case che smentisca le prestazioni a tempo costante? In secondo luogo, se guardi il codice sorgente di HashMap, non chiama uguale a () per ogni tasto della mappa - solo quando gli hashcode sono uguali.
matt b

5
Se leggi la citazione sopra, dice che è tempo costante "supponendo che la funzione hash disperda correttamente gli elementi tra i secchi". Dalla teoria CS, le tabelle hash hanno operazioni a tempo costante quando la funzione hash è "buona" (cosa che accade in media), ma potrebbe richiedere tempo lineare nel peggiore dei casi.
Newacct,

4
@Overflown - tecnicamente, non importa quanto tempo impiega obj.equals () dal punto di vista della complessità, in quanto fa parte della "costante" in relazione al numero di elementi nella raccolta.
Mikera,

6

Il ragazzo sopra ha dato un confronto per HashMap / HashSet vs TreeMap / TreeSet.

Parlerò di ArrayList vs. LinkedList:

Lista di array:

  • O (1) get()
  • ammortizzato O (1) add()
  • se si inserisce o si elimina un elemento nel mezzo usando ListIterator.add()o Iterator.remove(), sarà O (n) per spostare tutti i seguenti elementi

Lista collegata:

  • Sopra) get()
  • O (1) add()
  • se si inserisce o si elimina un elemento nel mezzo usando ListIterator.add()o Iterator.remove(), sarà O (1)

1
if you insert or delete an element in the middle using ListIterator.add() or Iterator.remove(), it will be O(1) perché? prima dobbiamo trovare l'elemento nel mezzo, quindi perché non O (n)?
MyTitle,

@MyTitle: leggilo di nuovo. "utilizzo ListIterator.add()o Iterator.remove()" Abbiamo un iteratore.
nuovo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.