1. 先看看map的定义:
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。 

2. Map的神奇在于有这么一对键值对。由static interface:Map.Entry<K,V>支撑

 

3. 常用的map实现类:

类名 说明 备注
HashMap 基于散列表的实现(取代了HashTable) 如无意外情况,默认选择用他
LinkedHashMap 类似HashMap,只HashMap慢一点;而迭代访问反而挂更快 对于需要定期清理的元素以节省空间
TreeMap 基于红黑树实现,被排序 往往通过key来排序
WeakhashMap 弱键映射 映射之外没有指向某个key,则此key会被垃圾回收
IdentityHashMap 使用==代替equals()对KEY进行比较 专为解决特殊问题

 map通过HashCode()和 equals()来保证key的唯一性。所以如果你打算把某个自己的类当做KEY,请你遵守HashCode 和 equals规则 

 

4. 性能测试: 

 HashMap:
小数据量(<10000)通常插入是获取的2-3倍效率,随着数据量的增长,插入速度回明显变慢。遍历(iterator),获取(get)速度无明显影响

 TreeMap:
小数据量插入(set)是(get)的2-7倍,插入速度会伴随数据量增长明显变慢。遍历,获取速度无明显影响,略慢于HashMap;

LinkedHashMap:
小数据量存取相当,数据增大,遍历和获取无明显影响,插入同TreeMap

IdentityHashMap:
因为用的==而不是equeals来比较,所以数据量基本对速度无明显影响,获取(get)略劣于其他map

WeakHashMap:
小数据量插入是获取的2-3倍,随着数据量增加而变慢 

当然,小数据量查询之下,还是HashMap最优  

 

5. 关于内存分配:

容量:表中的桶位数(因为Bruce喜欢bucket,建议这个就不要看解释,反而迷糊)
初始容量:表在创建时所拥有的桶位数(表用于维护key)
尺寸:表中当前存储的项数
负载因子:尺寸/容量,空表是0,半满是0.5。负载轻,冲突小,降低迭代速度。(因为只有到达了负载因子,才重新再散列,总再散列,冲突自然就小 )

关于WeakhashMap:

int size = 1000; 
        WeakHashMap&lt;String,String> map =
              new WeakHashMap<String,String>();
         String[] keys = new String[size];
        for(int i =0;i&lt;size;i++) {
            String key=i+"", value = i+"";//备注A
            if(i%2==1)keys[i]=key;
            map.put(key, value);
        }
        System.out.println(map.size());
        System.gc();
        System.out.println(map.size()); 

自己动手:
1. 把 备注A改成 value=key 试试
2. 把 WeakHashMap 改成HashMap试试  

 

6.一些工具MAP:

System.getenv()  返回一个不能修改的当前系统环境的字符串映射视图。(这个很有用);

Collections.synchronizedMap : 返回同步的Map;

EnumMap 虽然并不保证,但他可能比HashMap更快;

javax.management.Attribute    他不是map,善于伪装。

 

小结:

1. HashMap 通常是你的第一选择

2. 通常我们说HashMap是没有排序的,但如果你放置KEY为Integer类型呢?

3. hashCode 不是个简单问题,如果你准备把一个类当做KEY,并且尝试实现Comparable接口,你会发现一些这个类的有趣用法,将让你的代码变得优雅。