J'ai une liste d'objets et la liste est très grande. L'objet est
class Sample {
String value1;
String value2;
String value3;
String value4;
String value5;
}
Maintenant, je dois rechercher une valeur spécifique d'un objet dans la liste. Dites si value3=='three'
je dois retourner ces objets (ma recherche n'est pas toujours basée sur valeur3)
La liste est
List<Sample> list = new ArrayList<Sample>();
Quel est le moyen efficace de le faire?
Merci.
Vous pouvez essayer/ Apache Commons Collections .
Il existe une classe CollectionUtils qui vous permet de sélectionner ou de filtrer des éléments par Custom Predicate .
Votre code serait comme ça:
Predicate condition = new Predicate() {
boolean evaluate(Object sample) {
return ((Sample)sample).value3.equals("three");
}
};
List result = CollectionUtils.select( list, condition );
Mettre à jour:
Dans Java8, en utilisant Lambdas et StreamAPI ceci devrait être:
List<Sample> result = list.stream()
.filter(item -> item.value3.equals("three"))
.collect(Collectors.toList());
beaucoup plus gentil!
Avec Java 8 vous pouvez simplement convertir votre liste en un stream vous permettant d’écrire:
import Java.util.List;
import Java.util.stream.Collectors;
List<Sample> list = new ArrayList<Sample>();
List<Sample> result = list.stream()
.filter(a -> Objects.equals(a.value3, "three"))
.collect(Collectors.toList());
Notez que
a -> Objects.equals(a.value3, "three")
est une expression - lambdaresult
est une List
avec un type Sample
list.parallelStream()
au lieu de list.stream()
( lisez ceci )Si vous ne pouvez pas utiliser Java 8, vous pouvez utiliser Apache Commons library et écrire:
import org.Apache.commons.collections.CollectionUtils;
import org.Apache.commons.collections.Predicate;
Collection result = CollectionUtils.select(list, new Predicate() {
public boolean evaluate(Object a) {
return Objects.equals(((Sample) a).value3, "three");
}
});
// If you need the results as a typed array:
Sample[] resultTyped = (Sample[]) result.toArray(new Sample[result.size()]);
Notez que:
Object
à Sample
à chaque itérationSample[]
, vous avez besoin d'un code supplémentaire (comme indiqué dans mon exemple).Bonus: A Article de blog sympa qui explique comment trouver un élément dans la liste.
Si vous recherchez toujours en fonction de value3
, vous pouvez stocker les objets dans une carte:
Map<String, List<Sample>> map = new HashMap <>();
Vous pouvez ensuite renseigner la carte avec key = value3
et value = liste d'objets Sample avec la même propriété value3
.
Vous pouvez ensuite interroger la carte:
List<Sample> allSamplesWhereValue3IsDog = map.get("Dog");
Remarque: si 2 instances Sample
ne peuvent pas avoir le même value3
, vous pouvez simplement utiliser un Map<String, Sample>
.
Je modifie cette liste et ajoute une liste aux exemples, essayez ceci
Pseudocode
Sample {
List<String> values;
List<String> getList() {
return values}
}
for(Sample s : list) {
if(s.getString.getList.contains("three") {
return s;
}
}
Comme votre liste est une ArrayList
, on peut supposer qu'elle n'est pas triée. Par conséquent, il n'existe aucun moyen de rechercher votre élément plus rapide que O(n).
Si vous le pouvez, envisagez de modifier votre liste en une variable Set
(avec HashSet
comme implémentation) avec une variable Comparator
pour votre classe exemple.
Une autre possibilité serait d'utiliser un HashMap
. Vous pouvez ajouter vos données sous la forme Sample
(commencez les noms de classe par une lettre majuscule) et utilisez la chaîne que vous souhaitez rechercher en tant que clé. Ensuite, vous pouvez simplement utiliser
Sample samp = myMap.get(myKey);
S'il peut y avoir plusieurs échantillons par clé, utilisez Map<String, List<Sample>>
, sinon utilisez Map<String, Sample>
. Si vous utilisez plusieurs clés, vous devrez créer plusieurs cartes contenant le même jeu de données. Comme ils désignent tous les mêmes objets, l'espace ne devrait pas poser trop de problèmes.