用Java递增Map值的最有效方法–仅搜索一次键
這個問題可能被認為太基礎了,但是在論壇上經常被問到。 在本文中,我將討論一種僅在Map ONCE中搜索鍵的方法。
讓我們首先來看一個例子。 假設我正在使用Map創建一個字符串頻率列表,其中每個鍵是一個正在計數的String ,值是一個Integer ,每次添加一個String都會遞增。 實現它的一種直接方法是
這段代碼運行很慢,因為它在地圖上包含三個潛在的昂貴操作,即containsKey() , get()和[put()](http://docs.oracle.com/javase/7/docs/ api / java / util / Map.html#put(K,V)) 。 每個都需要在地圖中搜索關鍵字。 現在,讓我們重構代碼以獲得更好的性能。
整數與MutableInteger與AtomicInteger
我們必須調用三個昂貴的操作的重要原因之一是使用Integer進行計數。 在Java中, Integer是不可變的 。 它阻止我們在構造后修改整數值。 因此,要增加一個計數器,我們必須首先從映射中獲取整數,然后通過添加一個整數來創建另一個新整數,然后將其放回映射中。
為了使計數器可變,有幾種方法。 一種是簡單地創建自己的MutableInteger ,就像我在下面顯示的那樣。
public class MutableInteger {private int val;public MutableInteger(int val) {this.val = val;}public int get() {return val;}public void set(int val) {this.val = val;} }另一種方法可能是在Java中使用AtomicInteger ,該方法用于原子增量計數器等應用程序中。 但是AtomicInteger的主要選擇是如果您希望通過對整數進行操作來實現線程安全。 因此,它不能用作Integer的替代。 基于此,如果您的項目不是線程安全性的重要考慮因素,則我不建議您使用AtomicInteger 。
僅搜索一次密鑰
使用MutableInteger之后 ,我們可以將上面的代碼更改為
if (map.containsKey(string)) {MutableInteger count = map.get(string);count.set(count.get() + 1); } else {map.put(string, new MutableInteger(1)); }要么
MutableInteger count = map.get(string); if (count != null) {count.set(count.get() + 1); } else {map.put(string, new MutableInteger(1)); }在最壞的情況下,如果以前沒有看到過密鑰,則代碼將搜索密鑰兩次:一次用于檢索,一次用于設置。 它比上一個要好得多。 但是我們不應該立即滿足并停止。 如果您在Java文檔中選中了[Map.put()](http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#put(K,V))方法,您會發現此方法將返回the previous value associated with key 。 這意味著我們可以將檢索和設置合并為一個。 但是,您可能想知道:如果不首先檢索計數器,如何設置新計數器? 現在,我們終于可以觸摸本文中最棘手的部分:我們可以簡化放置零頻率計數器的工作!
public int incrementCount(K key, int count) {MutableInteger tmpCount = new MutableInteger(0);MutableInteger oldCount = map.put(key, tmpCount);if (oldCount != null) {count += oldCount.get();}tmpCount.set(count);return count;}另一個柜臺
看起來將所有必要的操作放入一個類中將對將來的使用有所幫助。 因此,我創建了一個稱為Counter的類并將其公開。 計數器定義一個集合,該集合對對象出現在集合中的次數進行計數。 假設您有一個包含{a, a, b, c}的Counter。 在“ a”上調用getCount()將返回2,而在keySet()上調用將返回{a, b, c} 。 此類的工作方式類似于Map ,但是具有不同的方法來輕松獲取/設置/增加對象的計數以及使用該計數來計算各種函數。 Counter構造函數和addAll()方法可用于復制另一個Counter的內容。 根據IntCounter和AbstractMapBag修改Counter類。
Counter上的一些突出操作包括
- gainCount()和decrementCount() :將給定鍵的給定計數加/減到當前計數中。 如果之前沒有看到該鍵,則假定它的計數為0,因此增量方法會將其計數設置為給定的數量。 減量會將其計數設置為-1。
- getCount() :返回給定鍵的當前計數,如果以前沒有看到過,則返回0。
- keysAt() , keysAbove()和keysBelow() :返回其計數在給定閾值之上,之下或之下的一組鍵。 該集合可能包含0個元素,但不會為null。
- argmin ()和argmax() :找到并返回此Counter中具有最小/最大計數的密鑰。 如果有幾個最小/最大計數,則返回隨機值。 如果此Counter為空,則返回null。
翻譯自: https://www.javacodegeeks.com/2013/10/most-efficient-way-to-increment-a-map-value-in-java-only-search-the-key-once.html
總結
以上是生活随笔為你收集整理的用Java递增Map值的最有效方法–仅搜索一次键的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Amazon Elastic Map R
- 下一篇: 银行买理财亏了怎么办?