簡體   English   中英

java.util.Map values()方法的性能

[英]java.util.Map values() method performance

我有一張這樣的地圖,其中包含幾百萬個條目:

private final Map<String, SomeItem> tops = new HashMap<>();

我需要獲取值列表,這可以通過調用java.util.Map values()方法來完成。

問題

每次我調用此方法時都會創建值集合,或者它是預先計算的,從性能角度來看,它可以保存多次以進行調用?

問題是在我的情況下Map有數百萬個元素,並且我不想每次調用values()都創建新列表

以下是java.util.HashMapMap.values()的復制實現:

public Collection<V> values() {
    Collection<V> vs = values;
    if (vs == null) {
        vs = new Values();
        values = vs;
    }
    return vs;
}

這清楚地表明,除非有必要,否則不會創建值集合。 因此,不應因調用values()而造成額外的開銷

這里重要的一點可能是: 沒關系!


但是首先,請參考到目前為止的其他答案:在這里返回的集合通常是“緩存的”,因為它是惰性創建的,然后,將返回相同的實例。 例如,考慮HashMap類中的實現:

public Collection<V> values() {
    Collection<V> vs;
    return (vs = values) == null ? (values = new Values()) : vs;
}

甚至AbstractMap文檔 (大多數Map實現基於該文檔 )中指定了(作為合同的一部分,作為實現規范):

該集合是在第一次調用此方法時創建的,並響應於所有后續調用而返回。 沒有執行同步,因此有幾次機會對該方法的多次調用不會全部返回相同的集合。


但是現在,有人可能會說實施可能會在以后更改。 HashMap類的實現可以更改,或者可以切換到另一種不擴展AbstractMap且以不同方式實現的Map實現。 當前這樣實現的事實本身(本身)並不能保證它總是這樣實現。

因此,更重要的一點(以及無關緊要的原因)是, values()方法確實應該返回一個集合視圖 Map接口文檔中所述

Map界面提供了三個集合視圖 ,這些視圖允許將地圖的內容作為一組鍵,一組值或一組鍵-值映射來查看。

特別Map#values()方法文檔

返回此映射中包含的值的Collection視圖。 集合由地圖支持,因此對地圖的更改會反映在集合中,反之亦然。

我無法想象實現包含處理Map所有值的視圖的合理方法。


例如,假設HashMap中的實現是這樣的:

public Collection<V> values() {
    return new Values();
}

然后,它將在每次調用時返回一個新的集合。 但是創建此集合根本涉及處理值。

或這樣說:調用此方法的成本與地圖的大小無關 無論地圖包含10個元素還是10000個元素,它基本上都需要創建單個對象。

正如其他人提到的那樣,您可以通過查看代碼來看到這一點。 您還可以編寫一個快速示例來向自己證明。 下面的代碼將打印正確的10次,因為對象標識的值始終相同。

public static void main(String[] args) {
    Map<String, String> myMap = new HashMap();
    Collection<String> lastValues = myMap.values();
    for (int i=0; i < 10; i++) {
        System.out.println(lastValues == myMap.values());
        lastValues = myMap.values();
    }
}

下面的代碼將在第一次打印true,然后在接下來的9次false。

public static void main(String[] args) {
    Map<String, String> myMap = new HashMap();
    Collection<String> lastValues = myMap.values();
    for (int i=0; i < 10; i++) {
        System.out.println(lastValues == myMap.values());
        lastValues = myMap.values();
        myMap = new HashMap();
    }
}

閱讀此主題后,還有一個建議,如果Map頂部聲明的內容未更改-您可以使用google guava ImmutableMap對象。 有關更多信息-UnmodifiableMap(Java Collections)與ImmutableMap(Google)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM