2 回答

TA貢獻1858條經(jīng)驗 獲得超8個贊
HashMap 不保證其迭代順序。原則上(即規(guī)范允許)鍵的順序是可能的,例如,從一個迭代到下一個迭代,即使映射的內(nèi)容沒有改變,或者迭代順序為鍵與對應(yīng)值的迭代順序不同。
這在HashMap規(guī)范中有說明:
此類不保證地圖的順序;特別是,它不保證訂單會隨著時間的推移保持不變。
在實踐中,如果 HashMap 的初始化和填充方式完全相同,則 HashMap 的迭代順序從一次迭代到下一次,甚至從一次 JVM 調(diào)用到下一次都是穩(wěn)定的。但是,應(yīng)用程序依賴于此是不明智的。創(chuàng)建具有不同初始大小或加載因子的 HashMap 會影響迭代順序,即使映射填充了相同的內(nèi)容。HashMap 實現(xiàn)確實會不時更改,這也會影響迭代順序。即使在 JDK 的補丁或錯誤修復(fù)版本中也會發(fā)生此類更改。不幸的是,歷史表明,當(dāng)?shù)樞虬l(fā)生變化時,應(yīng)用程序會中斷。因此,健壯的應(yīng)用程序應(yīng)該努力避免對 HashMap 迭代順序產(chǎn)生任何依賴。
這在實踐中很難做到。我知道 JDK 的一個(非公開)版本具有隨機化 HashMap 的迭代順序的測試模式。這可能有助于消除這種依賴關(guān)系。
如果您需要在迭代時關(guān)聯(lián) HashMap 的鍵和值,請獲取 HashMap 的 entrySet() 并對其進行迭代。它提供映射條目(鍵值對),因此鍵和值之間的關(guān)系得以保留。
JDK 中的替代 Map 實現(xiàn)提供了良好定義的迭代順序。TreeMap 和 ConcurrentSkipListMap 根據(jù)提供的比較方法對它們的條目進行排序。LinkedHashMap 提供基于插入順序的迭代順序。(它還提供了一種按訪問順序進行迭代的模式,這有時很有用,但其行為往往令人驚訝。)
請注意,Java 9 中引入的不可修改集合(Set.of、Map.of 等)提供了隨機迭代順序。JVM 的一次運行與下一次運行的順序不同。這應(yīng)該有助于應(yīng)用程序避免對迭代順序產(chǎn)生無意的依賴。

TA貢獻1775條經(jīng)驗 獲得超11個贊
讓我們再看一下關(guān)于Map
合約中迭代順序的 Java SE API 語言:
一些地圖實現(xiàn),如 TreeMap 類,對它們的順序做出特定的保證;其他的,比如 HashMap 類,不這樣做。
并且HashMap
:
此類不保證地圖的順序;特別是,它不保證訂單會隨著時間的推移保持不變。
由于明確指出 HashMap 迭代器沒有順序,因此不能假設(shè)即使在對同一方法的調(diào)用之間迭代也將是穩(wěn)定的,更不用說在調(diào)用不同方法keySet()
和values()
.
有幫助的是,Map
有一種方法entrySet()
可以完全滿足您的需要:它以配對鍵和值的方式迭代映射內(nèi)容。這是在您需要依賴該對的兩個部分時使用的方法。
隨著對 Java 許可的更改現(xiàn)在生效,那些認為他們可能總是使用 Oracle 的 Java 實現(xiàn)的個人和組織現(xiàn)在正在尋找替代實現(xiàn)。依賴單一實現(xiàn)的不成文細節(jié)是極其危險的,現(xiàn)在比甲骨文的許可和定價變化之前更是如此。
添加回答
舉報