HashMap、HashTable、LinkedHashMap和TreeMap的区别

Java为数据结构中的映射定义了一个接口java.util.Map,它有四个实现类,分别是HashMap、HashTable、LinkedHashMap和TreeMap。本节实例主要介绍这4中实例的用法和区别。
关键技术剖析:
Map用于存储键值对,根据键得到值,因此不允许键重复,值可以重复。
l  (1)HashMap是一个最常用的Map,它根据键的hashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为null,不允许多条记录的值为null。HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。如果需要同步,可以用Collections.synchronizedMap(HashMap map)方法使HashMap具有同步的能力。
l  (2)Hashtable与HashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,然而,这也导致了Hashtable在写入时会比较慢。
l  (3)LinkedHashMap保存了记录的插入顺序,在用Iteraor遍历LinkedHashMap时,先得到的记录肯定是先插入的。在遍历的时候会比HashMap慢。有HashMap的全部特性。
l  (4)TreeMap能够把它保存的记录根据键排序,默认是按升序排序,也可以指定排序的比较器。当用Iteraor遍历TreeMap时,得到的记录是排过序的。TreeMap的键和值都不能为空。
  
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
  
  
public class TestMap {
   
   
    public static void init(Map map){
       if (map !=  null ){
          String key =  null ;
          for ( int i= 5 ; i> 0 ; i--){
             key =  new Integer(i).toString() +  ".0" ;
             map.put(key, key.toString());
             //Map中的键是不重复的,如果插入两个键值一样的记录,
             //那么后插入的记录会覆盖先插入的记录
             map.put(key, key.toString() +  "0" );         }
       }
    }
   
    public static void output(Map map){
       if (map !=  null ){
          Object key =  null ;
          Object value =  null ;
          //使用迭代器遍历Map的键,根据键取值
          Iterator it = map.keySet().iterator();
          while (it.hasNext()){
             key = it.next();
             value = map.get(key);
             System.out.println( "key: " + key +  "; value: " + value );
          }
          //或者使用迭代器遍历Map的记录Map.Entry
          Map.Entry entry =  null ;
          it = map.entrySet().iterator();
          while (it.hasNext()){
             //一个Map.Entry代表一条记录
             entry = (Map.Entry)it.next();
             //通过entry可以获得记录的键和值
             //System.out.println("key: " + entry.getKey() + "; value: " + entry.getValue());
          }
       }
    }
   
    public static boolean containsKey(Map map, Object key){
       if (map !=  null ){
          return map.containsKey(key);
       }
       return false ;
    }
   
    public static boolean containsValue(Map map, Object value){
       if (map !=  null ){
          return map.containsValue(value);
       }
       return false ;
    }
   
    public static void testHashMap(){
       Map myMap =  new HashMap();
       init(myMap);
       //HashMap的键可以为null
       myMap.put( null , "ddd" );
       //HashMap的值可以为null
       myMap.put( "aaa" null );
       output(myMap);
    }
   
    public static void testHashtable(){
       Map myMap =  new Hashtable();
       init(myMap);
       //Hashtable的键不能为null
       //myMap.put(null,"ddd");
       //Hashtable的值不能为null
       //myMap.put("aaa", null);
       output(myMap);
    }
   
    public static void testLinkedHashMap(){
       Map myMap =  new LinkedHashMap();
       init(myMap);
       //LinkedHashMap的键可以为null
       myMap.put( null , "ddd" );
       myMap.put( null , "aaa" );
       //LinkedHashMap的值可以为null
       myMap.put( "aaa" null );
       output(myMap);
    }
   
    public static void testTreeMap(){
       Map myMap =  new TreeMap();
       init(myMap);
       //TreeMap的键不能为null
       //myMap.put(null,"ddd");
       //TreeMap的值不能为null
       //myMap.put("aaa", null);
       output(myMap);
    }
  
    public static void main(String[] args) {
       System.out.println( "采用HashMap" );
       TestMap.testHashMap();
       System.out.println( "采用Hashtable" );
       TestMap.testHashtable();
       System.out.println( "采用LinkedHashMap" );
       TestMap.testLinkedHashMap();
       System.out.println( "采用TreeMap" );
       TestMap.testTreeMap();
      
       Map myMap =  new HashMap();
       TestMap.init(myMap);
       System.out.println( "新初始化一个Map: myMap" );
       TestMap.output(myMap);
       //清空Map
       myMap.clear();
       System.out.println( "将myMap clear后,myMap空了么?  " + myMap.isEmpty());
       TestMap.output(myMap);
       myMap.put( "aaa" "aaaa" );
       myMap.put( "bbb" "bbbb" );
       //判断Map是否包含某键或者某值
       System.out.println( "myMap包含键aaa?  " + TestMap.containsKey(myMap,  "aaa" ));
       System.out.println( "myMap包含值aaaa?  " + TestMap.containsValue(myMap,  "aaaa" ));
       //根据键删除Map中的记录
       myMap.remove( "aaa" );
       System.out.println( "删除键aaa后,myMap包含键aaa?  " + TestMap.containsKey(myMap,  "aaa" ));
       //获取Map的记录数
       System.out.println( "myMap包含的记录数:  " + myMap.size());
    }
}
  
输出结果:
采用HashMap
key:  null ; value: ddd
key:  3.0 ; value:  3.00
key: aaa; value:  null
key:  4.0 ; value:  4.00
key:  1.0 ; value:  1.00
key:  5.0 ; value:  5.00
key:  2.0 ; value:  2.00
采用Hashtable
key:  4.0 ; value:  4.00
key:  1.0 ; value:  1.00
key:  3.0 ; value:  3.00
key:  5.0 ; value:  5.00
key:  2.0 ; value:  2.00
采用LinkedHashMap
key:  5.0 ; value:  5.00
key:  4.0 ; value:  4.00
key:  3.0 ; value:  3.00
key:  2.0 ; value:  2.00
key:  1.0 ; value:  1.00
key:  null ; value: aaa
key: aaa; value:  null
采用TreeMap
key:  1.0 ; value:  1.00
key:  2.0 ; value:  2.00
key:  3.0 ; value:  3.00
key:  4.0 ; value:  4.00
key:  5.0 ; value:  5.00
新初始化一个Map: myMap
key:  3.0 ; value:  3.00
key:  4.0 ; value:  4.00
key:  1.0 ; value:  1.00
key:  5.0 ; value:  5.00
key:  2.0 ; value:  2.00
将myMap clear后,myMap空了么?   true
myMap包含键aaa?   true
myMap包含值aaaa?   true
删除键aaa后,myMap包含键aaa?   false
myMap包含的记录数:   1
  
源码分析:
遍历Map有两种方法:
1 )map的keySet()方法获得键的集合,再调用键集合的iterator方法获得键的迭代器,以此迭代地取出Map中的键,用get方法获得键对应的值,便完成了Map的遍历。代码如下所示:
//使用迭代器遍历Map的键,根据键取值
         Iterator it = map.keySet().iterator();
         while (it.hasNext()){
            key = it.next();
            value = map.get(key);
            System.out.println( "key: " + key +  "; value: " + value );
         }
2 )使用Map的entrySet方法获得Map中记录的集合,每条对象都是一个Map.Entry对象,使用其getKey方法获得记录的键,使用其getValue方法获得记录的值。代码如下所示:
         //或者使用迭代器遍历Map的记录Map.Entry
         Map.Entry entry =  null ;
         it = map.entrySet().iterator();
         while (it.hasNext()){
            //一个Map.Entry代表一条记录
            entry = (Map.Entry)it.next();
            //通过entry可以获得记录的键和值
            //System.out.println("key: " + entry.getKey() + "; value: " + entry.getValu

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值