关键技术剖析:
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的键和值都不能为空。
001 | import java.util.HashMap; |
002 | import java.util.Hashtable; |
003 | import java.util.Iterator; |
004 | import java.util.LinkedHashMap; |
005 | import java.util.Map; |
006 | import java.util.TreeMap; |
007 | |
008 | |
009 | public class TestMap { |
010 | |
011 | |
012 | public static void init(Map map){ |
013 | if (map != null ){ |
014 | String key = null ; |
015 | for ( int i= 5 ; i> 0 ; i--){ |
016 | key = new Integer(i).toString() + ".0" ; |
017 | map.put(key, key.toString()); |
018 | //Map中的键是不重复的,如果插入两个键值一样的记录, |
019 | //那么后插入的记录会覆盖先插入的记录 |
020 | map.put(key, key.toString() + "0" ); } |
021 | } |
022 | } |
023 | |
024 | public static void output(Map map){ |
025 | if (map != null ){ |
026 | Object key = null ; |
027 | Object value = null ; |
028 | //使用迭代器遍历Map的键,根据键取值 |
029 | Iterator it = map.keySet().iterator(); |
030 | while (it.hasNext()){ |
031 | key = it.next(); |
032 | value = map.get(key); |
033 | System.out.println( "key: " + key + "; value: " + value ); |
034 | } |
035 | //或者使用迭代器遍历Map的记录Map.Entry |
036 | Map.Entry entry = null ; |
037 | it = map.entrySet().iterator(); |
038 | while (it.hasNext()){ |
039 | //一个Map.Entry代表一条记录 |
040 | entry = (Map.Entry)it.next(); |
041 | //通过entry可以获得记录的键和值 |
042 | //System.out.println("key: " + entry.getKey() + "; value: " + entry.getValue()); |
043 | } |
044 | } |
045 | } |
046 | |
047 | public static boolean containsKey(Map map, Object key){ |
048 | if (map != null ){ |
049 | return map.containsKey(key); |
050 | } |
051 | return false ; |
052 | } |
053 | |
054 | public static boolean containsValue(Map map, Object value){ |
055 | if (map != null ){ |
056 | return map.containsValue(value); |
057 | } |
058 | return false ; |
059 | } |
060 | |
061 | public static void testHashMap(){ |
062 | Map myMap = new HashMap(); |
063 | init(myMap); |
064 | //HashMap的键可以为null |
065 | myMap.put( null , "ddd" ); |
066 | //HashMap的值可以为null |
067 | myMap.put( "aaa" , null ); |
068 | output(myMap); |
069 | } |
070 | |
071 | public static void testHashtable(){ |
072 | Map myMap = new Hashtable(); |
073 | init(myMap); |
074 | //Hashtable的键不能为null |
075 | //myMap.put(null,"ddd"); |
076 | //Hashtable的值不能为null |
077 | //myMap.put("aaa", null); |
078 | output(myMap); |
079 | } |
080 | |
081 | public static void testLinkedHashMap(){ |
082 | Map myMap = new LinkedHashMap(); |
083 | init(myMap); |
084 | //LinkedHashMap的键可以为null |
085 | myMap.put( null , "ddd" ); |
086 | myMap.put( null , "aaa" ); |
087 | //LinkedHashMap的值可以为null |
088 | myMap.put( "aaa" , null ); |
089 | output(myMap); |
090 | } |
091 | |
092 | public static void testTreeMap(){ |
093 | Map myMap = new TreeMap(); |
094 | init(myMap); |
095 | //TreeMap的键不能为null |
096 | //myMap.put(null,"ddd"); |
097 | //TreeMap的值不能为null |
098 | //myMap.put("aaa", null); |
099 | output(myMap); |
100 | } |
101 | |
102 | public static void main(String[] args) { |
103 | System.out.println( "采用HashMap" ); |
104 | TestMap.testHashMap(); |
105 | System.out.println( "采用Hashtable" ); |
106 | TestMap.testHashtable(); |
107 | System.out.println( "采用LinkedHashMap" ); |
108 | TestMap.testLinkedHashMap(); |
109 | System.out.println( "采用TreeMap" ); |
110 | TestMap.testTreeMap(); |
111 | |
112 | Map myMap = new HashMap(); |
113 | TestMap.init(myMap); |
114 | System.out.println( "新初始化一个Map: myMap" ); |
115 | TestMap.output(myMap); |
116 | //清空Map |
117 | myMap.clear(); |
118 | System.out.println( "将myMap clear后,myMap空了么? " + myMap.isEmpty()); |
119 | TestMap.output(myMap); |
120 | myMap.put( "aaa" , "aaaa" ); |
121 | myMap.put( "bbb" , "bbbb" ); |
122 | //判断Map是否包含某键或者某值 |
123 | System.out.println( "myMap包含键aaa? " + TestMap.containsKey(myMap, "aaa" )); |
124 | System.out.println( "myMap包含值aaaa? " + TestMap.containsValue(myMap, "aaaa" )); |
125 | //根据键删除Map中的记录 |
126 | myMap.remove( "aaa" ); |
127 | System.out.println( "删除键aaa后,myMap包含键aaa? " + TestMap.containsKey(myMap, "aaa" )); |
128 | //获取Map的记录数 |
129 | System.out.println( "myMap包含的记录数: " + myMap.size()); |
130 | } |
131 | } |
132 | |
133 | 输出结果: |
134 | 采用HashMap |
135 | key: null ; value: ddd |
136 | key: 3.0 ; value: 3.00 |
137 | key: aaa; value: null |
138 | key: 4.0 ; value: 4.00 |
139 | key: 1.0 ; value: 1.00 |
140 | key: 5.0 ; value: 5.00 |
141 | key: 2.0 ; value: 2.00 |
142 | 采用Hashtable |
143 | key: 4.0 ; value: 4.00 |
144 | key: 1.0 ; value: 1.00 |
145 | key: 3.0 ; value: 3.00 |
146 | key: 5.0 ; value: 5.00 |
147 | key: 2.0 ; value: 2.00 |
148 | 采用LinkedHashMap |
149 | key: 5.0 ; value: 5.00 |
150 | key: 4.0 ; value: 4.00 |
151 | key: 3.0 ; value: 3.00 |
152 | key: 2.0 ; value: 2.00 |
153 | key: 1.0 ; value: 1.00 |
154 | key: null ; value: aaa |
155 | key: aaa; value: null |
156 | 采用TreeMap |
157 | key: 1.0 ; value: 1.00 |
158 | key: 2.0 ; value: 2.00 |
159 | key: 3.0 ; value: 3.00 |
160 | key: 4.0 ; value: 4.00 |
161 | key: 5.0 ; value: 5.00 |
162 | 新初始化一个Map: myMap |
163 | key: 3.0 ; value: 3.00 |
164 | key: 4.0 ; value: 4.00 |
165 | key: 1.0 ; value: 1.00 |
166 | key: 5.0 ; value: 5.00 |
167 | key: 2.0 ; value: 2.00 |
168 | 将myMap clear后,myMap空了么? true |
169 | myMap包含键aaa? true |
170 | myMap包含值aaaa? true |
171 | 删除键aaa后,myMap包含键aaa? false |
172 | myMap包含的记录数: 1 |
173 | |
174 | 源码分析: |
175 | 遍历Map有两种方法: |
176 | ( 1 )map的keySet()方法获得键的集合,再调用键集合的iterator方法获得键的迭代器,以此迭代地取出Map中的键,用get方法获得键对应的值,便完成了Map的遍历。代码如下所示: |
177 | //使用迭代器遍历Map的键,根据键取值 |
178 | Iterator it = map.keySet().iterator(); |
179 | while (it.hasNext()){ |
180 | key = it.next(); |
181 | value = map.get(key); |
182 | System.out.println( "key: " + key + "; value: " + value ); |
183 | } |
184 | ( 2 )使用Map的entrySet方法获得Map中记录的集合,每条对象都是一个Map.Entry对象,使用其getKey方法获得记录的键,使用其getValue方法获得记录的值。代码如下所示: |
185 | //或者使用迭代器遍历Map的记录Map.Entry |
186 | Map.Entry entry = null ; |
187 | it = map.entrySet().iterator(); |
188 | while (it.hasNext()){ |
189 | //一个Map.Entry代表一条记录 |
190 | entry = (Map.Entry)it.next(); |
191 | //通过entry可以获得记录的键和值 |
192 | //System.out.println("key: " + entry.getKey() + "; value: " + entry.getValue()); |
由于现在项目中用到了LinkedHashMap,并不是太熟悉就到网上搜了一下。
import
java.util.HashMap;
import
java.util.Iterator;
import
java.util.LinkedHashMap;
import
java.util.Map;
public
class
TestLinkedHashMap {
public
static
void
main(String args[])
{
System.out.println(
"*************************LinkedHashMap*************"
);
Map<Integer,String> map =
new
LinkedHashMap<Integer,String>();
map.put(
6
,
"apple"
);
map.put(
3
,
"banana"
);
map.put(
2
,
"pear"
);
for
(Iterator it = map.keySet().iterator();it.hasNext();)
{
Object key = it.next();
System.out.println( key+
"="
+ map.get(key));
}
System.out.println(
"*************************HashMap*************"
);
Map<Integer,String> map1 =
new
HashMap<Integer,String>();
map1.put(
6
,
"apple"
);
map1.put(
3
,
"banana"
);
map1.put(
2
,
"pear"
);
for
(Iterator it = map1.keySet().iterator();it.hasNext();)
{
Object key = it.next();
System.out.println( key+
"="
+ map1.get(key));
}
}
}
|
运行结果如下:
*************************LinkedHashMap*************
6=apple
3=banana
2=pear
*************************HashMap**************************
2=pear
6=apple
3=banana
分析:LinkedHashmap 的特点是put进去的对象位置未发生变化,而HashMap会发生变化.
再普及下:
java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMap Hashtable LinkedHashMap 和TreeMap.
Map主要用于存储健值对,根据键得到值,因此不允许键重复(重复了覆盖了),但允许值重复。
Hashmap 是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。 HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
Hashtable与 HashMap类似,它继承自Dictionary类,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了 Hashtable在写入时会比较慢。
LinkedHashMap 是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。
TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。
一般情况下,我们用的最多的是HashMap,在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。如果需要输出的顺序和输入的相同,那么用LinkedHashMap 可以实现,它还可以按读取顺序来排列.
HashMap是一个最常用的Map,它根据键的hashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为NULL,允许多条记录的值为NULL。
HashMap不支持线程同步,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致性。如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力。
Hashtable与HashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtable在写入时会比较慢。
LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的。
在遍历的时候会比HashMap慢TreeMap能够把它保存的记录根据键排序,默认是按升序排序,也可以指定排序的比较器。当用Iterator遍历TreeMap时,得到的记录是排过序的。