web-dev-qa-db-fra.com

Obtenir des objets spécifiques de ArrayList lorsque des objets ont été ajoutés de manière anonyme?

J'ai créé un court exemple de mon problème. Je crée une liste d'objets de manière anonyme et les ajoute à une variable ArrayList. Une fois que les éléments sont dans la variable ArrayList, je reviens plus tard et ajoute plus d'informations à chaque objet de la liste. Existe-t-il un moyen d'extraire un objet spécifique de la liste si vous ne connaissez pas son index?

Je ne connais que le 'nom' de l'objet, mais vous ne pouvez pas faire de list.get(ObjectName) ou quoi que ce soit. Quelle est la façon recommandée de gérer cela? Je préférerais ne pas avoir à parcourir la liste complète à chaque fois que je veux récupérer un objet spécifique.

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;
    }
}
8
leigero

Avec l'utilisation de List, il n'y a aucun moyen de "rechercher" une valeur sans l'itérer ...

Par exemple...

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;
    }
}

Maintenant, cela prendra du temps. Si l'élément que vous recherchez se trouve à la fin de la liste, vous devrez itérer jusqu'à la fin de la liste avant de trouver une correspondance.

Il serait peut-être préférable d’utiliser une variable Map de quelque sorte que ce soit ...

Donc, si nous mettons à jour Cave pour qu'il ressemble à ...

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

Nous pourrions faire quelque chose comme ...

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 = ...
}

Au lieu...

En fin de compte, tout dépendra de ce que vous voulez réaliser ...

13
MadProgrammer

List.indexOf() vous donnera ce que vous voulez, à condition que vous sachiez précisément ce que vous cherchez, et que la méthode equals() pour Party soit bien définie.

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

C'est là que ça devient intéressant - les sous-classes ne devraient pas examiner les propriétés privées de leurs parents. Nous allons donc définir equals() dans la 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;
}

Il est également sage de remplacer hashCode si vous remplacez equals - le contrat général pour hashCode impose que, si x.equals(y), alors x.hashCode () == y.hashCode () .

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

Si vous souhaitez rechercher des objets en fonction de leur nom String, il s'agit d'un cas d'école pour un Map, disons un HashMap. Vous pouvez utiliser un LinkedHashMap et le convertir en List ou Array plus tard (Chris a très bien expliqué cela dans les commentaires ci-dessous).

LinkedHashMap car il vous permet d'accéder aux éléments dans l'ordre dans lequel vous les insérez si vous le souhaitez. Sinon, HashMap ou TreeMap fera l'affaire.

Vous pouvez obtenir que cela fonctionne avec List comme le suggèrent les autres, mais cela me semble hacher ... et cela sera plus propre à court et à long terme.

Si vous DEVEZ utiliser une liste pour l'objet, vous pouvez toujours stocker une Map du nom de l'objet dans l'index du tableau. C'est un peu plus moche, mais vous obtenez presque les mêmes performances qu'un simple Map.

5
Karthik T

Vous pouvez utiliser le bogue list.indexOf(Object) en toute honnêteté. Ce que vous décrivez semble mieux vaut utiliser un Map.

Essaye ça:

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

Ensuite, lorsque vous souhaitez récupérer l'objet, utilisez 

mapOfObjects.get("objectName");

En supposant que vous connaissiez le nom de l'objet comme vous l'avez indiqué, il sera à la fois plus propre et plus rapide, en particulier si la carte contient un grand nombre d'objets.

Si vous avez besoin que les objets de la Map restent en ordre, vous pouvez utiliser 

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

au lieu

2
StormeHawke

Selon vos exigences, je voudrais suggérer que Map résoudra votre problème de manière très efficace et sans tracas.

Dans Map, vous pouvez donner le nom en tant que clé et votre objet d'origine en tant que valeur.

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

Vous pouvez simplement créer une méthode pour obtenir l'objet par son nom.

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

Je suggérerais de remplacer la equals(Object) de votre classe Party. Cela pourrait ressembler à quelque chose comme ça:

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;
}

Ensuite, vous pouvez utiliser la méthode indexOf(Object) pour extraire l'index de la partie spécifiée par son nom, comme indiqué ci-dessous:

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

Renverrait l'index de la Party avec le nom SecondParty

Remarque: cela ne fonctionne que parce que vous substituez la méthode equals(Object).

0
Josh M