2017-04-12 97 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);