web-dev-qa-db-fra.com

Comment effectuer une recherche dans une liste d'objets Java

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.

24
Jeevi

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!

39
Esteve

Utiliser Java 8

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 - lambda
  • result est une List avec un type Sample
  • C'est très rapide, pas de casting à chaque itération
  • Si votre logique de filtrage devient plus lourde, vous pouvez utiliser list.parallelStream() au lieu de list.stream() ( lisez ceci )


Apache Commons

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:

  • Il y a un casting de Object à Sample à chaque itération
  • Si vous souhaitez que vos résultats soient saisis sous la forme Sample[], 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.

38
Yves M.

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

3
assylias

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

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.

0
brimborium