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;
}
}
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 ...
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;
}
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
.
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
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>();
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;
}
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)
.