2017-04-12 128 views
4

我期待从java地图列表中获取最小值。我正在使用flatmap,stream和min的组合来执行此操作,而不是获得预期的结果。下面是代码 公共类TestMin {Java 8 stream min不返回期望值

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); 
    } 

} 

输出是:2

当然,这我期待的输出为1。尝试一些调试顾名思义是提供对应于一个值的输出“C”。即如果地图看起来像

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

然后我得到的输出为1 的问题是,为什么它不是由值进行排序,并通过按键,而排序,并提供我意想不到的输出。

回答

6

Stream::min期望遵守Comparator合同。但Integer::min没有这样做,它只是返回其两个输入的最小值。您应该使用Integer::compare来代替。

+0

感谢,奥利弗@您的答复。正如所料,你是对的。后续问题我们如何在编译时捕获这些错误/错误? – maneet

+0

@maneet你不能,但你可以写测试。 – Flown

+1

@maneet - 这是一个逻辑错误;目前还不清楚在编译时如何能够捕捉到这个(因为Comparator :: compareTo'返回一个int)。 –

0

你可以使用mapToInt()功能转换Stream<Integer>IntStream,然后就打电话min()它:

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