web-dev-qa-db-fra.com

Bon moyen d'obtenir * une * valeur à partir d'un Java Set?

Étant donné un simple Set<T>, Quelle est la bonne façon (rapide, quelques lignes de code) d'obtenir n'importe laquelle la valeur de Set?

Avec un List, c'est simple:

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

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

54
Jacob Marble

UNE Set<T> est un Iterable<T>, donc itérer sur le premier élément fonctionne:

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

La goyave a ne méthode pour ce faire, bien que l'extrait ci-dessus soit probablement mieux .

75
Jacob Marble

Étant donné que les flux sont présents, vous pouvez également procéder de cette façon, mais vous devez utiliser la classe Java.util.Optional. Optional est une classe wrapper pour un élément ou explicitement aucun é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();
}
4
Dániel Somogyi

Obtenir n'importe quel élément d'un ensemble ou d'une collection peut sembler être une demande inhabituelle - si ce n'est arbitraire ou éclectique - mais, c'est assez courant quand un, par exemple , doit calculer statistiques sur les objets Keys ou Values ​​dans une carte et doit initialiser les valeurs min/max. L'élément tout élément d'un ensemble/collection (renvoyé par Map.keySet () ou Map.values ​​()) sera utilisé pour cette initialisation avant la mise à jour. valeurs min/max sur chaque élément .

Alors, quelles options a-t-on face à ce problème tout en essayant de garder la mémoire et le temps d'exécution petits et le code clair?

Souvent, vous obtenez l'habituel: " convertissez Set en ArrayList et obtenez le premier élément ". Génial! Un autre tableau de millions d'articles et de cycles de traitement supplémentaires pour récupérer les objets de Set, allouer tableau et remplissez 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() ){ ... }
 ...
}

Ou on peut utiliser le bouclage avec un Iterator, en utilisant un indicateur pour indiquer que min/max doit être initialisé et une instruction conditionnelle pour vérifier si cet indicateur est défini pour toutes les itérations de la boucle. Cela implique beaucoup de vérification conditionnelle.

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 faites 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 cela vaut-il vraiment toute cette manœuvre au nom du programmeur (et la mise en place de l'itérateur au nom de la JVM) chaque fois que le minimum/maximum est nécessaire?

La suggestion d'un sport ancien javalement correct pourrait bien être: "Enveloppez votre carte dans une classe qui garde une trace des valeurs min et max une fois mises ou supprimées!".

Il y a une autre situation qui d'après mon expérience, le besoin de tout élément d'une carte se pose. C'est lorsque la carte contient des objets qui ont une propriété commune - tout de même pour tous dans cette carte - et vous devez lire cette propriété. Par exemple, supposons qu'il existe une carte des bacs de stockage du même histogramme qui ont le même nombre de dimensions. Étant donné une telle carte, vous devrez peut-être connaître le nombre de dimensions de juste n'importe quelle histobine dans la carte afin, par exemple, de créer une autre histobine de la même dimensions. Dois-je configurer à nouveau un itérateur et le supprimer après avoir appelé next () une seule fois? Je vais ignorer la suggestion de la personne correcte dans cette situation.

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

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

1
bliako