簡體   English   中英

Collections.emptyMap()vs new HashMap()

[英]Collections.emptyMap() vs new HashMap()

我可以使用Collections.emptyMap()一些情況是什么? 文檔說如果我希望我的集合是不可變的,我可以使用這個方法。

為什么我想要一個不可變的空集合? 有什么意義?

Effective JavaItem#43 - "Return empty arrays or collections, not null"演示了返回一個空集合,甚至可能演示使用Collections類上的這些emptyList()emptySet()emptyMap()方法獲得一個空集合還具有不可變的額外好處。 第15項 "Minimize Mutability"

來自Collections-emptySet-Collections-emptyList-Collections

它是一種編程習語。 這適用於不想要空變量的人。 因此,在初始化集合之前,他們可以使用空集。

注意:下面的代碼只是一個示例(根據您的使用情況進行更改):

private Set myset = Collections.emptySet();

void initSet() {
   myset = new HashSet();
}
void deleteSet() {
   myset = Collections.emptySet();
}

這些方法提供了幾個優點:

  1. 它們更簡潔,因為您不需要顯式地鍵入集合的泛型類型 - 它通常只是從方法調用的上下文中推斷出來。

  2. 它們更有效率,因為它們不會打擾創建新對象; 他們只是重用現有的空和不可變對象。 這種效果通常很小,但偶爾(很少,很少)很重要。

根據我的個人經驗,在API需要參數集合的情況下非常有用,但您無需提供任何參數。 例如,您可能有一個看起來像這樣的API,並且不允許空引用:

public ResultSet executeQuery(String query, Map<String, Object> queryParameters);

如果你有一個不帶任何參數的查詢,那么創建一個HashMap肯定有點浪費,它涉及分配一個數組,當你可以傳入實際上是常量的'Empty Map'時,它的實現方式在java.util.Collections

為什么我想要一個不可變的空集合? 有什么意義?

這里有兩個不同的概念,一起看時看起來很奇怪。 當你分別處理這兩個概念時,它會更有意義。

  • 首先,您應該盡可能使用不可變集合而不是可變集合。 其他地方都有很好的文獻記載

  • 其次,您應該更喜歡使用空集合而不是使用null作為標記。 這里有很好的描述 這意味着您將擁有更清晰,更易於理解的代碼,並且可以減少隱藏錯誤的位置。

因此,當您擁有需要地圖的代碼時,最好傳遞一個空地圖而不是空來表示沒有地圖。 大多數情況下,當您使用地圖時,最好使用不可變地圖。 所以這就是為什么有一個便利函數來創建一個不可變的空映射。

有幾種情況您更喜歡使用不可變的地圖,列表,集合或其他類型的集合。

首先 ,可以說是最重要的用例是,無論何時返回查詢結果或返回結果集(或列表或映射)的計算,您都應該使用不可變數據結構。

在這種情況下,我更喜歡返回這些的不可變版本,因為這更加清楚地反映了計算結果集的事實不變性 - 無論您以后如何處理數據,您從查詢中收到的結果集都不應該更改。

第二個常見用例是當您需要提供參數作為方法或服務的輸入時。 除非您希望通過服務或方法修改輸入集合(這通常是一個非常糟糕的設計理念),否則在許多情況下傳入不可變集合而不是可變集合可能是合理且安全的選擇。

我認為它是“按價值傳遞”的慣例。

更一般地說 - 只要數據跨越模塊或服務邊界,就使用不可變數據結構是一種明智的做法。 這使得更容易推理(不可變)輸入/輸出和可變內部狀態之間的差異。

這樣做的一個非常有益的副作用是提高模塊/服務的安全性和線程安全性,並確保更清晰地分離關注點。

使用Collections.empty*()方法的另一個好理由是它們明顯缺乏冗長。 在Java7之前的時代,如果你有一個通用的集合,你必須在整個地方撒上泛型類型的注釋。

只需比較這兩個聲明:

Map<Foo, Comparable<? extends Bar>> fooBarMap = new HashMap<Foo, Comparable<? extends Bar>>();

與:

Map<Foo, Comparable<? extends Bar>> fooBarMap = Collections.emptyMap();

后者顯然在兩個重要方面取得了可讀性:

  1. 在第一個聲明中,空映射的整個實例化都隱藏在泛型類型聲明的噪聲中,使得基本上無關緊要的聲明比它需要的更加神秘。
  2. 除了在右側顯着缺少泛型類型注釋之外,第二個版本明確指出地圖被初始化為空地圖。 另外 - 知道這個方法返回一個不可變的映射,現在我更容易通過搜索/fooBarMap =/找到fooBarMap被賦予另一個非空值的位置。

首先,您可以通過參考共享來逃避。 new HashMap()等將需要一個已分配的對象,並且可能需要一些額外的元素來保存數據,但是您只需要一個不可變空集合的副本(列表,集合,映射或任何其他類似)。 當您調用的方法需要接受Map但不需要編輯它時,這是一個明顯的選擇。

我建議查看Josh Bloch的Effective Java ,它列出了一些非常好的不可變對象屬性(包括線程安全性)。

當你有一個返回immutable collection的函數並且在某些情況下沒有數據要返回時,它可能很有用,所以不是返回null而是返回emptyMap()

它使您的代碼更容易,並防止NullPointerException

為什么我想要一個不可變的空集合? 有什么意義?

出於同樣的原因,你可以在某些時候使用Collections.unmodifiableMap() 如果用戶嘗試修改異常,您希望返回拋出異常的Map實例。 這只是一個特例:空地圖。

大多數情況下,我們使用constructor來創建新的empty map 但是Collections methods使用static method java.util.Collections.emptyMap()創建empty map提供了一些優勢。

  1. 它們更簡潔,因為您不需要顯式地鍵入集合的泛型類型 - 它通常只是從方法調用的上下文中推斷出來。

  2. 它們更有效率,因為它們不會打擾創建新對象; 他們只是重用現有的空和不可變對象。 這種效果通常很小,但偶爾(很少,很少)很重要。

為什么我想要一個不可變的空集合? 有什么意義?

出於同樣的原因,您可能需要不可變對象。 主要是因為您知道多個線程可以訪問對象的同一個實例並且它們都將看到相同的值,因此您可以在晚上安然入睡。 在集合中沒有項目仍然是一個有效的值,您可能希望維護它。

暫無
暫無

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

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