2017-08-17 64 views
1

我有以下代碼。我想了解它是否會對內存進行任何更改。使用臨時變量使用收集器

方法1:使用收藏家,我可以直接返回地圖像這樣:

List<Customer> customerList = new ArrayList<>(); 
    customerList.add(new Customer("1", "pavan")); 
    customerList.add(new Customer("2", "kumar")); 

    return customerList.stream().collect(Collectors.toMap(t->t.getId(), t->t)); 

方法2:使用一個明確的地圖,收集結果,就像這樣:

Map<String,Customer> map = new HashMap<String, Customer>(); 
    map = customerList.stream().collect(Collectors.toMap(t->t.getId(), t->t));  
    return map; 

相比第一,如果我迭代了一百萬次,第二種方法對內存/ GC有什麼影響?

+0

在你的第二個例子,我想你可能意味着使用.forEach()和put()在地圖上? (如果沒有,你實例化一個沒有任何東西的地圖:))順便說一下,Guava提供了Maps.uniqueIndex,這是寫這個相同代碼的稍微短一些的方法。我很確定這些開銷幾乎相同。 – EvanM

+0

是的,我可以做到這一點。但我想了解第二個代碼是否與GC性能有關 – pppavan

+0

是的 - 它們幾乎完全相同。收集器也創建了一個HashMap,但是對於尋找重複數據有點奇怪。你的第二個片段忽略重複。應該幾乎完全相同的GC開銷。 – EvanM

回答

0

在第二種方法中,您正在實例化一個Map,並將該引用重新分配給由stream.collect()調用返回的引用。 顯然,由「map」引用的第一個Map對象會丟失。

第一種方法沒有這個問題。

總而言之,這在內存使用情況方面略有差異,但考慮到您有一百萬個條目需要迭代,這可能忽略不計。

1

除了在第二個示例中實例化一個不需要的Map實例之外,這兩段代碼都是相同的。您立即將您創建的Map引用替換爲由流返回的引用。編譯器很可能會將其作爲冗餘代碼來消除。

streams API的collect方法將爲您實例化Map;代碼已經很好的優化了,這是你自己使用Stream API的好處之一。

要回答您的具體問題,您可以根據需要多次迭代代碼的兩部分,並且不會對GC影響產生任何影響。

+0

將GC擱置一會兒;有差異和*潛在*這個代碼甚至可以改善,據我所知... – Eugene

+0

噢該死! Simon Ritter :)多麼驚喜;我可能在YouTube上觀看了您最近的所有視頻。儘管如此,我發現這個代碼可以改進,我已經爲該 – Eugene

+0

添加了一個答案:-)。我同意(正如您在答覆中發佈的那樣)可以改進代碼。 – Speakjava

1

有代碼是到目前爲止不完全相同;特別Collectors.toMap說,它會返回一個Map

上有型,可變性,串行化,或者地圖的線程安全沒有保證退換。

有絕對沒有保證什麼那麼以往任何時候都返回Map實際上是一個HashMap。它可以是其他任何東西 - 任何其他Map在這裏;所以將它分配給HashMap就錯了。

然後就是你建立Collector的方式。它可以被簡化爲:

customerList.stream().collect(Collectors.toMap(Customer::getId, Function.identity())); 

的方法參考Customer::getId,而不是lambda表達式,將創建少一個方法(因爲lambda表達式被去糖的方法和方法的引用都沒有)。

此外,如果在多個地方使用Function.identity()代替t -> t將創建對象。閱讀this

然後有一個事實如何HashMap內部工作。如果您未指定default size,則可能需要重新調整大小 - 這是一項昂貴的操作。這意味着你可以把12項進入它的下一個大小調整之前 - 默認Collectors.toMap將與默認16項Map0.75一個load_factor開始。

您不能省略使用Collectors.toMap,因爲供應商始終從HashMap::new開始 - 使用默認的16個條目和0.75的load_factor。

知道了這一點,你可以將整個流:

Map<String, Customer> map = new HashMap<String, Customer>((int)Math.ceil(customerList.size()/0.75)); 
customerList.forEach(x -> map.put(x.getId(), x));