2010-04-15 49 views
5

Ho un java.util.ArrayList<Item> e un oggetto Item.Contare le occorrenze di elementi in ArrayList

Ora, voglio ottenere il numero di volte che lo Item è memorizzato nell'arrayist.

So che posso eseguire il controllo arrayList.contains() ma restituisce true, indipendentemente dal fatto che contenga uno o più Item s.

Q1. Come posso trovare il numero di volte in cui l'elemento è memorizzato nell'elenco?

Q2. Inoltre, se l'elenco contiene più di un articolo, come è possibile determinare l'indice di altri articoli perché arrayList.indexOf(item) restituisce l'indice del solo primo elemento ogni volta?

+0

non di esclusione dell'oggetto è uguale e codice hash? Hanno bisogno di –

+0

Perché non estendere la classe ArrayList per aggiungere la funzionalità aggiuntiva richiesta? Questo è il motivo per cui OOP esiste;) Q1 può essere fatto facilmente implementando un contatore per ciascun elemento univoco nell'elenco e incrementandolo ogni volta che viene aggiunto un elemento già esistente. –

risposta

5

Questo è facile da fare a mano.

public int countNumberEqual(ArrayList<Item> itemList, Item itemToCheck) { 
    int count = 0; 
    for (Item i : itemList) { 
     if (i.equals(itemToCheck)) { 
      count++; 
     } 
    } 
    return count; 
} 

Tenete presente che se non si esegue l'override equals nella classe Item, questo metodo usa identità di un oggetto (in quanto questo è l'implementazione di Object.equals()).

Modifica: Per quanto riguarda la tua seconda domanda (prova a limitare i post a una domanda a testa), puoi farlo anche a mano.

public List<Integer> indices(ArrayList<Item> items, Item itemToCheck) { 
    ArrayList<Integer> ret = new ArrayList<Integer>(); 
    for (int i = 0; i < items.size(); i++) { 
     if (items.get(i).equals(itemToCheck)) { 
      ret.add(i); 
     } 
    } 
    return ret; 
} 
+0

Esiste un altro metodo più efficiente perché il mio elenco contiene migliaia di elementi e un particolare elemento può essere duplicato al massimo 4 o 5 volte. Quindi penso che non valga la pena confrontare quelle migliaia di elementi per trovare quei 4 o 5 duplicati. Per favore non suggerirmi di usare 'Set' perché c'è una solida ragione per non usare Set nel mio caso. –

+1

Pensa al fatto che per contare gli oggetti avrai bisogno di ANDARE TUTTA la lista, dal momento che dovrai controllarli tutti per sapere il conteggio esatto. – Jack

+1

Se vuoi qualcosa che abbia una complessità temporale inferiore, sei sfortunato - non sapere nulla sul contenuto del tuo Elenco, devi controllare ogni posizione. Un'ottimizzazione consiste nel confrontare il 'hashCode' del tuo oggetto con il' hashCode' di ciascun elemento nell'Elenco, ma se sono uguali, devi comunque controllare l'uguaglianza usando 'equals()' poiché la tua funzione hash potrebbe avere collisioni. Se stai controllando solo l'identità dell'oggetto, non c'è bisogno di farlo poiché 'equals' confronterà gli indirizzi di memoria o qualcosa del genere. – danben

22

È possibile utilizzare Collections classe:

public static int frequency(Collection<?> c, Object o) 

Restituisce il numero di elementi della collezione specificato uguale all'oggetto specificato. Più formalmente, restituisce il numero di elementi e nella raccolta in modo tale che (o == null? E == null: o.equals (e)).

Se è necessario contare occurencies di una lunga lista molte volte vi consiglio di utilizzare un HashMap per memorizzare i contatori e aggiornarli mentre si inserisce nuovi elementi alla lista. Questo eviterebbe di calcolare qualsiasi tipo di contatore ... ma ovviamente non avrai indici.

HashMap<Item, Integer> counters = new HashMap<Item, Integer>(5000); 
ArrayList<Item> items = new ArrayList<Item>(5000); 

void insert(Item newEl) 
{ 
    if (counters.contains(newEl)) 
    counters.put(newEl, counters.get(newEl)+1); 
    else 
    counters.put(newEl, 1); 

    items.add(newEl); 
} 

Un suggerimento finale: è possibile utilizzare altri framework collezioni (come Apache Collections) e utilizzare un datastructure Bag che è descritto come

Definisce una collezione che conta il numero di volte in cui un oggetto viene visualizzato nella collezione.

Quindi esattamente ciò che serve ..

+2

wow non ha mai saputo di questo metodo. Javadoc trovato qui: http://java.sun.com/javase/6/docs/api/java/util/Collections.html#frequency%28java.util.Collection,%20java.lang.Object% 29 –

+0

Il tuo primo metodo è più adatto alle mie esigenze. Ma c'è un problema. Se ho trovato più di una voce nell'elenco, come recuperare gli altri elementi dall'elenco? –

+2

Se sono uguali, perché preoccuparsi di recuperarli? Sai già cosa c'è dentro! O ci sono campi che non entrano nel confronto 'equals'? O stai cercando di fare qualcosa in più del semplice recupero, come forse l'eliminazione? –

0

Come gli altri intervistati hanno già detto, se si sta fermamente impegnati a memorizzare i tuoi oggetti in un ArrayList non ordinata, quindi contando articoli prenderà O (n) , dove n è il numero di elementi nell'elenco. Qui in SO, diamo consigli ma non facciamo magie!

Come ho appena accennato, se la lista viene cercata molto più di quanto non sia stata modificata, potrebbe aver senso tenerla ordinata.Se il tuo elenco è ordinato, puoi trovare il tuo oggetto in O (log n) ora, che è molto più veloce; e se hai un'implementazione hashcode che si adatta perfettamente al tuo equals, tutti gli elementi identici si troveranno uno accanto all'altro.

Un'altra possibilità sarebbe quella di creare e mantenere due strutture di dati in parallelo. È possibile utilizzare uno HashMap contenente gli elementi come chiavi e il loro conteggio come valori. Sarai obbligato ad aggiornare questa seconda struttura ogni volta che la tua lista cambierà, ma le ricerche di conteggio degli articoli sarebbero o (1).

0

potrei sbagliarmi, ma mi sembra come la struttura dei dati si vuole realmente potrebbe essere un Multiset (da google-collections/guava) piuttosto che un List. Permette multipli, a differenza di Set, ma in realtà non interessa l'ordine. Detto questo, ha un metodo int count(Object element) che fa esattamente quello che vuoi. E poiché non è un elenco e ha implementazioni supportate da un HashMap, ottenere il conteggio è notevolmente più efficiente.

0

Grazie per il tuo suggerimento. Ma questo sotto codice è davvero molto utile in quanto non abbiamo alcun metodo di ricerca con List che possa dare il numero di occurance.

void insert(Item newEl) 
{ 
    if (counters.contains(newEl)) 
    counters.put(newEl, counters.get(newEl)+1); 
    else 
    counters.put(newEl, 1); 

    items.add(newEl); 
} 

Grazie a Jack. Buona pubblicazione.

Grazie,

Binod Suman

http://binodsuman.blogspot.com

Problemi correlati