Comment rechercher 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. Disons si value3=='three' je dois retourner ces objets (Ma recherche n'est pas toujours basée sur value3)

, La liste est

List<Sample> list = new ArrayList<Sample>();

Quelle est la manière efficace de le faire?

Merci.

Author: Yves M., 2012-10-30

5 answers

Vous pouvez essayer de Apache Commons Collections.

Il existe une classe CollectionUtilsqui vous permet de sélectionner ou de filtrer des éléments par un prédicat personnalisé .

Votre code serait comme ceci:

Predicate condition = new Predicate() {
   boolean evaluate(Object sample) {
        return ((Sample)sample).value3.equals("three");
   }
};
List result = CollectionUtils.select( list, condition );

Mise à Jour:

Dans java8, en utilisant Lambdas et StreamAPI cela devrait être:

List<Sample> result = list.stream()
     .filter(item -> item.value3.equals("three"))
     .collect(Collectors.toList());

Beaucoup plus agréable!

 34
Author: Esteve, 2016-03-22 09:47:35

Utilisation de Java 8

Avec Java 8, vous pouvez simplement convertir votre liste à 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 un List avec Sample de type
  • C'est très rapide, pas de cast à chaque itération
  • Si votre logique de filtre devient plus lourde, vous pouvez faire list.parallelStream() au lieu de list.stream() (lire ceci)


Apache Communes

Si vous ne pouvez pas utiliser Java 8, vous pouvez utiliser la bibliothèqueApache Commons 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 est une fonte à partir de Object à Sample à chaque itération
  • Si vous avez besoin que vos résultats soient tapés comme Sample[] , vous avez besoin de code supplémentaire (comme indiqué dans mon exemple)



Bonus: Unbel article de blog parlant de la façon de trouver un élément dans la liste.

 35
Author: Yves M., 2017-05-23 12:34:14

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 remplir la carte avec key = value3 et value = liste d'exemples d'objets avec cette même propriété value3.

Vous pouvez ensuite interroger la carte:

List<Sample> allSamplesWhereValue3IsDog = map.get("Dog");

Remarque: si n 2 Sample instances peuvent avoir le même value3, vous pouvez simplement utiliser un Map<String, Sample>.

 3
Author: assylias, 2012-10-30 12:31:34

Je modifie cette liste et ajoute une liste aux exemples essayez ceci

Pseudo -

Sample {
   List<String> values;
   List<String> getList() {
   return values}
}



for(Sample s : list) {
   if(s.getString.getList.contains("three") {
      return s;
   }
}
 3
Author: MemLeak, 2015-04-28 11:53:13

Comme votre liste est un ArrayList, on peut supposer qu'elle n'est pas triée. Par conséquent, il n'y a aucun moyen de rechercher votre élément qui est plus rapide que O(n).

Si vous le pouvez, vous devriez penser à changer votre liste en Set (avec HashSet comme implémentation) avec un Comparator spécifique pour votre classe d'exemple.

Une Autre possibilité serait d'utiliser un HashMap. Vous pouvez ajouter vos données en tant que {[6] }( veuillez commencer les noms de classe avec une lettre majuscule) et utiliser la chaîne que vous souhaitez rechercher pour les clés. Ensuite, vous pouvez simplement utiliser

Sample samp = myMap.get(myKey);

Si 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 ensemble de données. Comme ils pointent tous vers les mêmes objets, l'espace ne devrait pas être un problème.

 0
Author: brimborium, 2012-10-30 12:42:22