2013-08-27 16 views
6

Ho creato un breve esempio del mio problema. Sto creando un elenco di oggetti in modo anonimo e aggiungendoli a un ArrayList. Una volta che gli articoli sono nello ArrayList, torno più tardi e aggiungo ulteriori informazioni a ciascun oggetto all'interno dell'elenco. C'è un modo per estrarre un oggetto specifico dalla lista se non si conosce il suo indice?Ottieni oggetti specifici da ArrayList quando gli oggetti sono stati aggiunti in modo anonimo?

Conosco solo il "nome" dell'oggetto ma non è possibile eseguire uno list.get(ObjectName) o altro. Qual è il modo consigliato per gestire questo? Preferirei non dover scorrere l'intero elenco ogni volta che voglio recuperare un oggetto specifico.

public class TestCode{ 

    public static void main (String args []) { 
     Cave cave = new Cave(); 

     // Loop adds several Parties to the cave's party list 
     cave.parties.add(new Party("FirstParty")); // all anonymously added 
     cave.parties.add(new Party("SecondParty")); 
     cave.parties.add(new Party("ThirdParty")); 

     // How do I go about setting the 'index' value of SecondParty for example? 
    } 
} 

class Cave { 
    ArrayList<Party> parties = new ArrayList<Party>(); 
} 

class Party extends CaveElement{ 
    int index; 

    public Party(String n){ 
     name = n; 
    } 

    // getter and setter methods 

    public String toString() { 
     return name; 
    } 
} 


class CaveElement { 
    String name = ""; 
    int index = 0; 

    public String toString() { 
     return name + "" + index; 
    } 
} 
+0

Devi utilizzare un elenco? – smk

risposta

11

Dato l'uso di List, non c'è modo di "ricerca" di un valore senza scorrendo si ...

Per esempio ...

Cave cave = new Cave(); 

// Loop adds several Parties to the cave's party list 
cave.parties.add(new Party("FirstParty")); // all anonymously added 
cave.parties.add(new Party("SecondParty")); 
cave.parties.add(new Party("ThirdParty")); 

for (Party p : cave.parties) { 
    if (p.name.equals("SecondParty") { 
     p.index = ...; 
     break; 
    } 
} 

Ora, ci vorrà del tempo. Se l'elemento che stai cercando è alla fine dell'elenco, dovrai eseguire un'iterazione fino alla fine dell'elenco prima di trovare una corrispondenza.

Potrebbe essere meglio utilizzare un Map di qualche tipo ...

Quindi, se aggiorniamo Cave a guardare come ...

class Cave { 
    Map<String, Party> parties = new HashMap<String, Party>(25); 
} 

Potremmo fare qualcosa di simile ...

Cave cave = new Cave(); 

// Loop adds several Parties to the cave's party list 
cave.parties.put("FirstParty", new Party("FirstParty")); // all anonymously added 
cave.parties.put("SecondParty", new Party("SecondParty")); 
cave.parties.put("ThirdParty", new Party("ThirdParty")); 

if (cave.parties.containsKey("SecondParty")) { 
    cave.parties.get("SecondParty").index = ... 
} 

Invece ...

In definitiva, tutto questo sarà dipende da cosa vuoi ottenere ...

+1

Credo che questa sia la risposta più utile. Non sarò in grado di usare una mappa, c'è un po 'più di questo puzzle che ho incluso per queste domande per Per favore di mettere un SSCCE. Grazie per la risposta – leigero

+1

@leigero se vuoi il meglio di entrambi i mondi, potresti usare un 'HashMap' per memorizzare il mapping di' name' -> index .. –

+0

Anche se hai bisogno la funzionalità di List per altri motivi, stai ANCORA meglio eseguendo questo come 'LinkedHashMap' dietro le quinte e convertendolo in List in base alle necessità.Le mappe sono molto più efficienti – StormeHawke

4

List.indexOf() vi darà ciò che si desidera, a condizione di sapere esattamente quello che stai dopo, ea condizione che il metodo equals() per Party è ben definito.

Party searchCandidate = new Party("FirstParty"); 
int index = cave.parties.indexOf(searchCandidate); 

Questo è dove si fa interessante - sottoclassi non dovrebbero essere esaminando le proprietà private dei loro genitori, quindi dovremo definire equals() nella superclasse.

@Override 
public boolean equals(Object o) { 
    if (this == o) { 
     return true; 
    } 
    if (!(o instanceof CaveElement)) { 
     return false; 
    } 

    CaveElement that = (CaveElement) o; 

    if (index != that.index) { 
     return false; 
    } 
    if (name != null ? !name.equals(that.name) : that.name != null) { 
     return false; 
    } 

    return true; 
} 

E 'anche saggio per sostituire hashCode se si ignora equals - il contratto generale per hashCode mandati che, se x.equals(y), quindi x.hashCode() == y.hashCode().

@Override 
public int hashCode() { 
    int result = name != null ? name.hashCode() : 0; 
    result = 31 * result + index; 
    return result; 
} 
+0

Sì, avevi ragione, mio ​​cattivo. È stata una lunga giornata: P –

5

Se si vuole occhiata gli oggetti in base al loro nome String, questo è un caso da manuale per una Map, diciamo un HashMap. È possibile utilizzare uno LinkedHashMap e convertirlo in un List o Array in un secondo momento (Chris lo ha descritto bene nei commenti di seguito).

LinkedHashMap perché consente di accedere agli elementi nell'ordine in cui vengono inseriti se si desidera farlo. Altrimenti lo farà HashMap o TreeMap.

Si potrebbe ottenere questo funziona con List come suggeriscono gli altri, ma questo si sente Hacky per me .. e questo sarà più pulito sia a breve che a lungo termine.

Se è necessario utilizzare un elenco per l'oggetto, è comunque possibile memorizzare un valore Map del nome dell'oggetto nell'indice dell'array. Questo è un po 'più brutto, ma si ottiene quasi la stessa prestazione di un semplice Map.

+2

In particolare, puoi sempre usare 'map.values ​​(). AArray (new Party [0])' per eseguire il dump in un array, e puoi usare 'new ArrayList (map.values ​​()) 'per scaricare in una lista. –

+1

Di tutte le 5 o 6 risposte finora, mi piace il tuo migliore. Ha la ricerca O (1) e mantiene ancora l'ordine di inserimento. –

+0

@ ChrisJester-Young yup grazie, ecco perché suggerisco 'LinkedHashMap', dovrei renderlo esplicito –

0

Suggerire di ignorare lo equals(Object) della classe Party. Potrebbe sembrare qualcosa di simile:

public boolean equals(Object o){ 
    if(o == null) 
     return false; 
    if(o instanceof String) 
     return name.equalsIgnoreCase((String)o); 
    else if(o instanceof Party) 
     return equals(((Party)o).name); 
    return false; 
} 

Dopo aver fatto questo, è possibile utilizzare il metodo indexOf(Object) per recuperare l'indice del partito specificato con il suo nome, come illustrato di seguito:

int index = cave.parties.indexOf("SecondParty"); 

Sarebbe tornato l'indice di Party con il nome SecondParty.

Nota: questo funziona solo perché si sta eseguendo l'override del metodo equals(Object).

+0

Vorrei anche suggerire che è una violazione del contratto 'equals', ma questo è solo MHO: P – MadProgrammer

+0

@MadProgrammer Eh, sembra essere piuttosto conveniente però: P –

+1

Comodo forse, ma cosa succede se si hanno due oggetti' Party' denominati lo stesso, ma gli indici sono diversi. Il contratto è ora rotto;) – MadProgrammer

2

È possibile utilizzare il bug list.indexOf(Object) in tutta onestà, ciò che si sta descrivendo suona come se fosse meglio usare uno Map.

Prova questo:

Map<String, Object> mapOfObjects = new HashMap<String, Object>(); 
mapOfObjects.put("objectName", object); 

Poi più tardi, quando si vuole recuperare l'oggetto, utilizzare

mapOfObjects.get("objectName"); 

Supponendo che si conosce il nome dell'oggetto, come lei ha affermato, questo sarà sia più pulito e volontà avere prestazioni più veloci, in particolare se la mappa contiene un numero elevato di oggetti.

Se avete bisogno di oggetti nel Map di rimanere in ordine, è possibile utilizzare

Map<String, Object> mapOfObjects = new LinkedHashMap<String, Object>(); 

invece

1

Come da tua domanda, vorrei suggerire che la Mappa risolverà il tuo problema in modo molto efficiente e senza problemi.

In Mappa è possibile assegnare il nome come chiave e l'oggetto originale come valore.

Map<String,Cave> myMap=new HashMap<String,Cave>(); 
0

Si potrebbe semplicemente creare un metodo per ottenere l'oggetto in base al nome.

public Party getPartyByName(String name) { 
    for(Party party : parties) { 
     if(name.equalsIgnoreCase(party.name)) { 
      return party; 
     } 
    } 
    return null; 
} 
Problemi correlati