86 votes

Un bon moyen d'obtenir *n'importe quelle* valeur d'un ensemble Java ?

Étant donné un simple Set<T> Quel est le bon moyen (rapide, quelques lignes de code) pour obtenir cualquier de la valeur Set ?

Avec un List C'est facile :

List<T> things = ...;
return things.get(0);

Mais, avec un Set il n'y a pas de .get(...) car Set ne sont pas commandés.

118voto

Jacob Marble Points 6121

A Set<T> est un Iterable<T> donc l'itération vers le premier élément fonctionne :

Set<T> things = ...;
return things.iterator().next();

La goyave a une méthode pour ce faire, bien que l'extrait ci-dessus est probablement meilleur .

17voto

Dániel Somogyi Points 316

Puisque les flux sont présents, vous pouvez aussi le faire de cette façon, mais vous devez utiliser la classe java.util.Optional . Optional est une classe enveloppante pour un élément ou explicitement un non-élément (en évitant le Nullpointer).

//returns an Optional.
Optional <T> optT = set.stream().findAny();

//Optional.isPresent() yields false, if set was empty, avoiding NullpointerException
if(optT.isPresent()){
    //Optional.get() returns the actual element
    return optT.get();
}

Edit : Comme j'utilise Optional assez souvent moi-même : Il existe un moyen d'accéder à l'élément ou d'obtenir un élément par défaut, au cas où il ne serait pas présent :
optT.orElse(other) renvoie soit l'élément soit, s'il n'est pas présent, l'élément, other . other peut être null au fait.

4voto

bliako Points 144

Obtenir cualquier d'un ensemble ou d'une collection peut sembler être une demande peu commune - voire arbitraire ou éclectique - mais elle est assez courante lorsqu'on a, par exemple, besoin de calculer statistiques sur les objets Keys ou Values d'une Map et doit initialiser les valeurs min/max . Le site cualquier d'un ensemble ou d'une collection (retourné par Map.keySet() ou Map.values()) sera utilisé pour cette initialisation avant la mise à jour des valeurs min/max au cours de l'année. chaque élément.

Alors, quelles sont les options dont on dispose lorsqu'on est confronté à ce problème et qu'on essaie en même temps de maintenir la mémoire et le temps d'exécution à un niveau bas et un code clair ?

Souvent, vous obtenez l'habituel : " convertir Set en ArrayList et récupérer le premier élément ". Génial ! Un autre tableau de plusieurs millions d'éléments et des cycles de traitement supplémentaires pour récupérer des objets de Set, allouer et remplir il :

HashMap<K,V> map;
List<K> list = new ArrayList<V>(map.keySet()); // min/max of keys
min = max = list.get(0).some_property(); // initialisation step
for(i=list.size();i-->1;){
 if( min > list.get(i).some_property() ){ ... }
 ...
}

On peut aussi utiliser une boucle avec un Iterator, en utilisant un drapeau pour indiquer que min/max doivent être initialisés et une instruction conditionnelle pour vérifier si ce drapeau est activé pour toutes les itérations de la boucle. Cela implique beaucoup de vérifications conditionnelles.

boolean flag = true;
Iterator it = map.keySet().iterator();
while( it.hasNext() ){
  if( flag ){
    // initialisation step
    min = max = it.next().some_property();
    flag = false;
  } else {
    if( min > list.get(i).some_property() ){ min = list.get(i).some_property() }
  ...
  }
}

Ou faire l'initialisation en dehors de la boucle :

HashMap<K,V> map;
Iterator it = map.keySet().iterator();
K akey;
if( it.hasNext() ){
  // initialisation step:
  akey = it.next();
  min = max = akey.value();
  do {
    if( min > list.get(i).some_property() ){ min = akey.some_property() }
  } while( it.hasNext() && ((akey=it.next())!=null) );
}

Mais est-ce que cela vaut vraiment la peine de faire tout ce travail de la part du programmeur (et de configurer l'Iterator de la part de la JVM) chaque fois que min/max est nécessaire ?

La suggestion d'un vieux sportif qui a le sens de l'humour pourrait bien être : "Enveloppez votre carte dans une classe qui garde la trace des valeurs min et max lorsqu'elles sont ajoutées ou supprimées !

Il existe une autre situation qui, d'après mon expérience, n'a pas besoin de cualquier d'un élément de la carte se présente. C'est le cas lorsque la carte contient des objets qui ont une propriété commune - la même pour tous dans cette carte - et que vous devez lire cette propriété . Supposons, par exemple, qu'il existe une carte des bacs de retenue du même histogramme qui ont le même nombre de dimensions. Étant donné une telle carte, vous pouvez avoir besoin de connaître le nombre de dimensions de juste cualquier Histobin dans la carte afin, par exemple, de créer un autre Histobin de mêmes dimensions. Dois-je à nouveau configurer un itérateur et l'éliminer après avoir appelé next() une seule fois ? Je vais ignorer la suggestion de la personne javally-correcte pour cette situation.

Et si tous les problèmes pour obtenir le cualquier entraîne une augmentation insignifiante de la mémoire et des cycles du processeur, alors qu'en est-il de tout le code que l'on doit écrire juste pour obtenir l'information difficile à obtenir ? cualquier élément.

Nous avons besoin de la cualquier élément. Donnez-le nous !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X