2010-11-18 12 views
5

Mi piacerebbe avere un oggetto che implementa le interfacce Map e List in Java. L'idea è simile al problema in questa domanda: Java Ordered MapImplementare entrambe le interfacce Mappa ed Elenco in Java?

voglio aggiungere coppie nome/valore a un elenco e avere la lista preservare la sequenza, ma anche essere in grado di fare ricerche per nome:

foo.put("name0", "value0"); 
foo.put("name1", "value1"); 
foo.get(1); --> Map.Entry("name1", "value1") 
foo.get("name0"); --> "value0" 

Ecco il problema: quando creo questa classe:

class Foo implements Map, List { 
    // add all methods here 
} 

ottengo un errore di compilazione:

"The return type is incompatible with Map.remove(Object)" 
public boolean remove(Object o) { 
    return false; 
} 

Se non si implementano le interfacce Mappa ed Elenco, esistono molti metodi di raccolta Java che non sono disponibili per l'utilizzo in questa struttura di dati.

(Inoltre, la ragione per cui la soluzione proposta in Java ordinato mappa qui sopra non funziona è che LinkedHashMap non dispone di un metodo get (int). Non è possibile selezionare le voci in base all'indice.)

+2

Sei contrario all'estensione di 'LinkedHashMap', in caso contrario, perché non provare ad aggiungere il metodo' get (int) 'ad esso? –

+0

http://www.java.net/forum/topic/jdk/java-se/implementing-both-map-and-list-impossible-0 – Adam

+1

@Adam quel collegamento è rotto, ma suppongo che sappiamo un po 'cosa Dice, solo dall'URL;) – MatrixFrog

risposta

5

Come notato, non è possibile implementare sia List e Map sulla stessa classe. Ma per quello che ti serve, anche questo non dovrebbe essere necessario. Quello di cui hai bisogno è che sia possibile accedere allo data sia tramite l'interfaccia Map sia tramite l'interfaccia List. Un po 'come l'accesso ai dati Map come un insieme in entrySet() o come una raccolta utilizzando Map.values().

In breve, ciò che è necessario è 2 viste sui dati, una vista che implementa un List e un'altra vista che implementa Map.

Se esiste una vista dominante (ad esempio Mappa), è possibile fornire all'implementazione della mappa un metodo List getAsList() che presenta i dati come Elenco, supportati dai dati della Mappa.

EDIT

La risposta data da Paulo Guedes dovrebbe servire. Esiste già un'implementazione della mappa con i tuoi requisiti. La mia risposta è un po 'più generale, di presentare gli stessi dati utilizzando più interfacce incompatibili, dove un semplice adattatore non è sufficiente.

5

LinkedHashMap fa quello che ti serve.

tabella hash e attuazione lista collegata dell'interfaccia Map, con ordine di iterazione prevedibile. Questa implementazione differisce da HashMap in quanto mantiene una lista doppiamente collegata che attraversa tutte le sue voci.

+0

Non esiste un metodo 'get' per ottenere elementi per indice – Adam

+2

@Adam: quindi estendere LinkedHashMap e implementare get (int index) utilizzando l'iteratore. Si potrebbe anche usare l'array Entry [] di supporto chiamato 'table' (sebbene io userei l'iteratore per la robustezza). – extraneon

1

Le interfacce Map e List contengono definizioni in conflitto di un metodo remove. Non è possibile implementare entrambi in una singola classe perché non è possibile eseguire l'override della stessa firma del metodo con una differenza solo nel tipo restituito.

mi chiedo se si utilizza List<Map.Entry<K,V>> avrebbe soddisfare il vostro bisogno.

5

Va sottolineato che la causa dell'errore è che Map contiene la definizione per il remove seguente metodo:

V remove(Object key) 

Mentre List definisce:

boolean remove(Object o) 

E, in Java, i metodi non possono essere sovraccaricati in base al tipo di reso, quindi sono firme in conflitto e non possono essere implementati nella stessa classe.

2

Perché non implementa la tua interfaccia?

public interface HashListMap { 

public boolean add(Object arg0); 
public void add(int arg0, Object arg1); 
public boolean addAll(Collection arg0); 
public boolean addAll(int arg0, Collection arg1); 
public void clear(); 
public boolean contains(Object arg0); 
public boolean containsAll(Collection arg0); 
public Object get(int arg0); 
public int indexOf(Object arg0); 
public boolean isEmpty(); 
public Iterator iterator(); 
public int lastIndexOf(Object arg0); 
public ListIterator listIterator(); 
public ListIterator listIterator(int arg0); 
public boolean remove(Object arg0); 
public Object remove(int arg0); 
public boolean removeAll(Collection arg0); 
public boolean retainAll(Collection arg0); 
public Object set(int arg0, Object arg1); 
public int size(); 
public List subList(int arg0, int arg1); 
public Object[] toArray(); 
public Object[] toArray(Object[] arg0); 
public boolean containsKey(Object arg0); 
public boolean containsValue(Object arg0); 
public Set entrySet(); 
public Object get(Object arg0); 
public Set keySet(); 
public Object put(Object arg0, Object arg1); 
public void putAll(Map arg0); 
public Collection values(); 

}

+2

+1 per il senso dell'umorismo –

+0

molto divertente :) che senso ha usare un'interfaccia "mai supportata"? – Donatello

1

In aggiunta a quanto detto Dave Costa si dovrebbe usare LinkedHashMap. Questa è la Mappa ma conserva l'ordine di inserimento degli elementi.

Come mappa implementa il metodo values ​​(), quindi è possibile pronunciare nuovo ArrayList (map.values ​​()). Get (0) per simulare la funzionalità dell'elenco.

, ma si può anche dire map.get ("uno") perché è solo un'implementazione mappa.

Problemi correlati