一般来讲,Map是一个由键值对组成的数据结构,且在集合中每一个键是惟一的。下面就以K和V来表明键和值,来讲明一下java中关于Map的九大问题。
0、将Map转换为List类型
在java中Map接口提供了三种集合获取方式:Key set,,value set, and key-value set
.。它们均可以经过构造方法或者
addAll()
方法来转换为List类型。下面代码就说明了如何从Map中构造ArrayList:
// 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()); |
一、经过
Entry
遍历Map
java中这种以键值对存在的方式被称为
Map.Entry。
Map
.
entrySet()
返回的是一个
key-value
集合,这是一种很是高效的遍历方式。
for(Entry entry: map.entrySet()) {
// get key K key = entry.getKey();
// get value V value = entry.getValue();
}
Iterator 咱们也常常用到,尤为是在JDK1.5之前
Iterator itr = map.entrySet().iterator();
while(itr.hasNext()) {
Entry entry = itr.next();
// get key K key = entry.getKey();
// get value V value = entry.getValue();
}
二、经过Key来对Map排序
排序须要对Map的ke进行频繁的操做,一种方式就是经过比较器(
comparator
)来实现:
List list = new ArrayList(map.entrySet());
Collections.sort(list, new Comparator() {
@Override public int compare(Entry e1, Entry e2) {
return e1.getKey().compareTo(e2.getKey()); } });
另一种方法就是经过
SortedMap
,但必需要实现
Comparable
接口。
SortedMap sortedMap = new TreeMap(new Comparator() {
@Override public int compare(K k1, K k2) {
return k1.compareTo(k2); } });
sortedMap.putAll(map);
三、对value对Map进行排序
这与上一点有些相似,代码以下:
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()); } }); |
四、初始化一个static 的常量Map
当你但愿建立一个全局静态Map的时候,咱们有如下两种方式,并且是线程安全的。
而在Test1中,咱们虽然声明了map是静态的,可是在初始化时,咱们依然能够改变它的值,就像
Test1.map.put(3,"three");
在Test2中,咱们经过一个内部类,将其设置为不可修改,那么当咱们运行
Test2.map.put(3,"three")
的时候,它就会抛出一个
UnsupportedOperationException
异常来禁止你修改。
public class Test1 {
private static final Map map;
static { map = new HashMap();
map.put(1, "one"); map.put(2, "two");
} }
public class Test2 {
private static final Map map;
static { Map aMap = new HashMap();
aMap.put(1, "one");
aMap.put(2, "two");
map = Collections.unmodifiableMap(aMap);
} }
五、HashMap, TreeMap, and Hashtable之间的不一样
在Map接口中,共有三种实现:HashMap,TreeMap,Hashtable。
它们之间各有不一样,详细内容请参考《
HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap
》一文。
六、Map中的反向查询
咱们在Map添加一个键值对后,意味着这在Map中键和值是一一对应的,一个键就是对应一个值。可是有时候咱们须要反向查询,好比经过某一个值来查找它的键,这种数据结构被称为
bidirectional map
,遗憾的是JDK并无对其支持。
Apache和
Guava 共同提供了这种
bidirectional map
实现,它在实现中它规定了键和值都是必须是1:1的关系。
七、对Map的复制
java中提供了不少方法均可以实现对一个Map的复制,可是那些方法不见得会时时同步。简单说,就是一个Map发生的变化,而复制的那个依然保持原样。下面是一个比较高效的实现方法:
Map copiedMap = Collections.synchronizedMap(map);
固然还有另一个方法,那就是克隆。可是咱们的java鼻祖
Josh Bloch
却不推荐这种方式,他曾经在一次访谈中说过关于Map克隆的问题:在不少类中都提供了克隆的方法,由于人们确实须要。可是克隆很是有局限性,并且在不少时候形成了没必要要的影响。(原文《
Copy constructor versus cloning
》)
八、建立一个空的Map
若是这个map被置为不可用,能够经过如下实现
map = Collections.emptyMap();
相反,咱们会用到的时候,就能够直接
map = new HashMap();