2017-04-12 2 views
4

Je cherche à obtenir une valeur minimale à partir d'une liste de cartes en Java. J'utilise la combinaison de flatmap, stream et min pour le faire et ne pas obtenir les résultats attendus. Voici le code Testmin public class {Java 8 flux min ne retourne pas la valeur attendue

public static class TestHolder{ 
    public static Map<String,Integer> getValues(){ 
     Map<String,Integer> map = new HashMap<>(); 
     map.put("a",1); 
     map.put("b",3); 
     map.put("c",2); 

     return map; 

    } 
} 

public static void main(String[] args) { 
    List<Map<String, Integer>> l = new ArrayList<>(); 
    l.add(TestHolder.getValues()); 
    l.add(TestHolder.getValues()); 
    l.add(TestHolder.getValues()); 

    // Getting min 
    int min = l.stream().map((m)->m.values()).flatMap((v)->v.stream()).min(Integer::min).get(); 
    System.out.println(min); 
    } 

} 

sortie est: 2

Bien sûr, la sortie que je suis dans l'attente est 1. Essayer un certain débogage suggère qu'il fournit une sortie une valeur correspondant à "c". i.e. si la carte ressemble

[a->2 , b->3, c->1] 

Puis la sortie que je reçois est 1. La question est pourquoi il n'est pas le tri par des valeurs et de tri plutôt par des touches et me fournissant la sortie inattendue.

Répondre

6

Stream::min attend quelque chose qui adhère au contrat Comparator. Mais Integer::min ne fait pas cela, il retourne juste le minimum de ses deux entrées. Vous devriez utiliser Integer::compare à la place.

+0

Merci, Oliver @ pour la réponse. Comme prévu, vous avez raison. Une question de suivi comment pouvons-nous attraper de telles erreurs/bugs au moment de la compilation? – maneet

+0

@maneet Vous ne pouvez pas, mais vous pouvez écrire des tests. – Flown

+1

@maneet - Ceci est un bug de logique; on ne sait pas comment on pourrait attraper ça au moment de la compilation (étant donné que 'Comparator :: compareTo' renvoie un' int'). –

0

Vous pouvez utiliser la fonction mapToInt() pour convertir Stream<Integer>-IntStream puis il suffit d'appeler min() dessus:

int min = l.stream() 
     .map(Map::values) 
     .flatMap(Collection::stream) 
     .mapToInt(Integer::intValue) 
     .min().orElse(defaultMinValue);