结构为键值的map_在Java中增加Map值的最有效方法-只需搜索键一次
結(jié)構(gòu)為鍵值的map
這個(gè)問(wèn)題可能被認(rèn)為太基礎(chǔ)了,但是在論壇中經(jīng)常被問(wèn)到。 在本文中,我將討論一種僅在Map ONCE中搜索鍵的方法。
讓我們首先來(lái)看一個(gè)例子。 假設(shè)我正在使用Map創(chuàng)建一個(gè)字符串頻率列表,其中每個(gè)鍵是一個(gè)正在計(jì)數(shù)的String ,值是一個(gè)Integer ,每次添加一個(gè)String都會(huì)遞增。 實(shí)現(xiàn)它的一種直接方法是
這段代碼運(yùn)行很慢,因?yàn)樗诘貓D上包含三個(gè)潛在的昂貴操作,即containsKey() , get()和[put()](http://docs.oracle.com/javase/7/docs/ api / java / util / Map.html#put(K,V)) 。 每個(gè)都需要在地圖中搜索關(guān)鍵字。 現(xiàn)在,讓我們重構(gòu)代碼以獲得更好的性能。
整數(shù)與MutableInteger與AtomicInteger
我們必須調(diào)用三個(gè)昂貴的操作的重要原因之一是使用Integer進(jìn)行計(jì)數(shù)。 在Java中, Integer是不可變的 。 這樣可以防止我們?cè)跇?gòu)造后修改整數(shù)值。 因此,要增加一個(gè)計(jì)數(shù)器,我們必須首先從映射中獲取整數(shù),然后通過(guò)添加一個(gè)整數(shù)來(lái)創(chuàng)建另一個(gè)新整數(shù),然后將其放回映射中。
為了使計(jì)數(shù)器可變,有幾種方法。 一種是簡(jiǎn)單地創(chuàng)建自己的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 ,該方法用于原子增量計(jì)數(shù)器等應(yīng)用程序中。 但是AtomicInteger的主要選擇是如果您希望通過(guò)對(duì)整數(shù)進(jìn)行操作來(lái)實(shí)現(xiàn)線程安全。 因此,它不能用作Integer的替代。 基于此,如果線程安全不是您項(xiàng)目的重要考慮因素,則我不建議您使用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)); }在最壞的情況下,如果之前沒(méi)有看到密鑰,則代碼將搜索密鑰兩次:一次用于檢索,一次用于設(shè)置。 它比上一個(gè)要好得多。 但是我們不應(yīng)該立即滿足并停止。 如果您在Java文檔中選中了[Map.put()](http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#put(K,V))方法,您會(huì)發(fā)現(xiàn)此方法將返回the previous value associated with key 。 這意味著我們可以將檢索和設(shè)置合并為一個(gè)。 但是,您可能想知道:如果不首先檢索計(jì)數(shù)器,如何設(shè)置新計(jì)數(shù)器? 現(xiàn)在,我們終于可以觸摸本文中最棘手的部分:我們可以簡(jiǎn)化一下零頻率計(jì)數(shù)器的放置!
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;}另一個(gè)柜臺(tái)
看起來(lái)將所有必要的操作放入一個(gè)類(lèi)中將對(duì)將來(lái)的使用有所幫助。 因此,我創(chuàng)建了一個(gè)名為Counter的類(lèi)并將其公開(kāi)。 計(jì)數(shù)器定義一個(gè)集合,該集合對(duì)對(duì)象出現(xiàn)在集合中的次數(shù)進(jìn)行計(jì)數(shù)。 假設(shè)您有一個(gè)包含{a, a, b, c}的Counter。 在“ a”上調(diào)用getCount()將返回2,而在keySet()上調(diào)用將返回{a, b, c} 。 此類(lèi)的工作方式類(lèi)似于Map ,但具有不同的方法,可以輕松獲取/設(shè)置/增加對(duì)象的計(jì)數(shù)并使用該計(jì)數(shù)計(jì)算各種函數(shù)。 Counter構(gòu)造函數(shù)和addAll()方法可用于復(fù)制另一個(gè)Counter的內(nèi)容。 根據(jù)IntCounter和AbstractMapBag修改Counter類(lèi)。
Counter上的一些突出操作包括
- crementCount()和decrementCount() :將給定鍵的給定計(jì)數(shù)與當(dāng)前計(jì)數(shù)相加/相減。 如果該鍵以前未出現(xiàn)過(guò),則假定其計(jì)數(shù)為0,因此增量方法會(huì)將其計(jì)數(shù)設(shè)置為給定的數(shù)量。 減量會(huì)將其計(jì)數(shù)設(shè)置為-1。
- getCount() :返回給定鍵的當(dāng)前計(jì)數(shù),如果以前沒(méi)有看到過(guò),則返回0。
- keysAt() , keysAbove()和keysBelow() :返回其計(jì)數(shù)在給定閾值之上,之下或之下的一組鍵。 該集合可能包含0個(gè)元素,但不會(huì)為null。
- argmin ()和argmax() :找到并返回此Counter中具有最小/最大計(jì)數(shù)的密鑰。 如果有幾個(gè)最小/最大計(jì)數(shù),則返回隨機(jī)值。 如果此Counter為空,則返回null。
翻譯自: https://www.javacodegeeks.com/2013/10/most-efficient-way-to-increment-a-map-value-in-java-only-search-the-key-once.html
結(jié)構(gòu)為鍵值的map
總結(jié)
以上是生活随笔為你收集整理的结构为键值的map_在Java中增加Map值的最有效方法-只需搜索键一次的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 阿里巴巴该如何进行营销宝推广阿里巴巴怎么
- 下一篇: 开源mindmap_Java开发人员访谈