程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 【Simple Java】Java Maps的9個常見問題,simplemaps

【Simple Java】Java Maps的9個常見問題,simplemaps

編輯:JAVA綜合教程

【Simple Java】Java Maps的9個常見問題,simplemaps


一般來說,Map是一種由鍵值對組成的數據結構,其中鍵(key)在Map中是不能重復的;

本篇文章總結了9個最常見的問題(關於Java Map及其實現類);

出於簡單考慮,在代碼例子中我將不使用泛型,因此,我將僅僅寫上Map而不是寫上Map<K, V>,且Map中的Key和Value都是可以比較的,意味著K和V都實現了Comparable接口;

1.Map轉List

在Java中,Map接口提供了三個集合視圖,即key set, value set,和key-value set。它們都可以轉成List集合,如下代碼所示:

// key list
List keyList = new ArrayList(map.keySet());
// value list
List valueList = new ArrayList(map.valueSet());
// key-value list
List entryList = new ArrayList(map.entrySet());

2.迭代遍歷Map中的key-value

迭代遍歷Map中的鍵值對是最基本的操作。在Java中,鍵值對信息存儲在Map.Entry類中。通過調用Map.entrySet()方法會返回鍵值對集合,因此最有效的遍歷Map中的鍵值對如下代碼所示:

for(Entry entry: map.entrySet()) {
    // get key
    K key = entry.getKey();
    // get value
    V value = entry.getValue();
}

當然,也可以通過迭代器遍歷,如下代碼:

while(itr.hasNext()) {
    Entry entry = itr.next();
    // get key
    K key = entry.getKey();
    // get value
    V value = entry.getValue();
}

3.Map中的元素按Key排序

對Map中的元素按key排序是另一個經常使用的操作。有一種方法是將Map中的元素放進List集合,然後通過一個比較器對集合進行排序,如下代碼示例:

        List list = new ArrayList(map.entrySet());
        Collections.sort(list, new Comparator() {
            public int compare(Entry e1, Entry e2) {
                return e1.getKey().compareTo(e2.getKey());
                }
            });
        }

另一種方法是使用SortedMap,其提供了對Key進行排序的功能;前提是Map中的Key需要實現Comparable接口或者通過構造方法傳入比較器;

TreeMap是SortedMap的一個實現類,它的構造方法能夠接收一個比較器,以下代碼展示了如何將普通Map轉成SortedMap:

SortedMap sortedMap = new TreeMap(new Comparator() {
    @Override
    public int compare(K k1, K k2) {
    return k1.compareTo(k2);
    }
});
sortedMap.putAll(map);

4.Map中的元素按Value排序

同樣可以參考前面的將Map的元素放進List集合然後傳入比較器進行排序,不過這次要比較的對象是Entry.getValue()。如下代碼所示:

List list = new ArrayList(map.entrySet());
Collections.sort(list, new Comparator() {
    @Override
    public int compare(Entry e1, Entry e2) {
        return e1.getValue().compareTo(e2.getValue());
    }
});

對於這個問題,當map中的value都是唯一的情況,我們仍然可以使用sorted map來排序,在這種情況下,你可以將key賦值給value,value賦值給key來實現該功能;但是這種解決方法十分受限,非常不建議使用;

5.初始化一個不可修改的Map

當你想要使用Map來存儲一些常量時,將他們存儲到一個不可修改的Map是一個好習慣。這種防御性編程技術會幫助你創建一個能安全使用且線程安全的map;

我們可以使用靜態代碼塊來初始化一個靜態不可變的map,如下代碼:

public class Test {
private static final Map map;
    static {
        map = new HashMap();
        map.put(1, "one");
        map.put(2, "two");
    }
}

然而以上代碼是有問題的,即使map被聲明成static final,我們仍然可以操作該map,如Test.map.put(3,"three");因此,這不是不可變的map;

為了創建一個不可變的map,我們需要一個額外的map對象,將它作為入參傳入Collections.unmodifiableMap方法中,然後得到一個不可變的Map,如下代碼:

public class Test {
private static final Map map;
static {
Map aMap = new HashMap();
aMap.put(1, "one");
aMap.put(2, "two");
map = Collections.unmodifiableMap(aMap);
}
}

此時,當我們運行Test.map.put(3,"three")將拋出UnsupportedOperationException異常;

Google的Guava庫支持多種方式創建不可變的Map,想學習的可以參考其官方使用手冊;

6.HashMap, TreeMap, 和Hashtable的區別

HashMap, TreeMap, 和Hashtable是Map接口的三個主要實現類,它們之間的主要區別如下:

  • 是否有序。HashMap和HashTable不會保證元素的有序性,隨著時間推移,元素的順序可能會發生改變;然而TreeMap是有序的,會根據自然順序或依據比較器排序;
  • key- value限制。HashMap允許key和value為null(key只能有一個為null,因為key不能重復)。HashTable不允許key 或value為null;TreeMap如果使用自然順序或者比較器不允許key為null,使用null key將拋出異常;另外,在TreeMap中value是可以為null的;
  • 是否同步。只有Hashtable是同步的,其它的不是。如果線程安全不在考慮范圍的話,強烈建議使用HashTable。

另一個比較完整的比較如下:

它們之間的更多比較信息可參考如下鏈接:

http://www.programcreek.com/2013/03/hashmap-vs-treemap-vs-hashtable-vs-linkedhashmap/

7.反向查找Map

有時候,我們需要key和value都唯一,這種情況允許我們創建一個雙向查找Map,也就是說,可以通過唯一的value去查找唯一的Key,遺憾的是,JDK並不支持該數據結構;

Apache Common Collections 和 Guava 提供了對雙向查找Map的支持,被叫做BidiMap和BiMap,它們規定了key和value必須是1對1的關系。

8.Map淺拷貝

大部分Map實現類都提供了構造方法,用於對另外一個Map的復制,但是這個復制操作不是同步的,意味著一個線程在對Map進行復制操作的時候,另一個線程可能會對它結構性的修改(增刪該等操作);為了阻止意外的非同步操作,應該事先使用Collections.synchronizedMap()方法去創建一個同步Map,如下:

Map copiedMap = Collections.synchronizedMap(map);

另外一種淺拷貝方法是使用clone()方法,然而它並不被集合框架作者Josh Bloch推薦;他曾在一次訪談中談到關於”拷貝構造方法VS克隆方法“,他說:

I often provide a public clone method on concrete classes because people expect it. ... It’s a shame that Cloneable is broken, but it happens. ... Cloneable is a weak spot, and I think people should be aware of its limitations.

9.創建一個空Map

如果是不可變Map,使用Collections工具類創建,如下:

map = Collections.emptyMap();

否則,直接new,如下:

map = new HashMap();

 

譯文鏈接:http://www.programcreek.com/2013/09/top-9-questions-for-java-map/

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved