Map:元素是键值对key-value的集合
Map的遍历方式:
1.键遍历 keySet()方法,返回Map中所有key集合,类型为Set集合
@Test
public void keySetTest() {
Map<String, String> map = new HashMap<>();
map.put("name1", "zhangSan");
map.put("name2", "liSi");
map.put("name3", "wangWu");
map.put("name4", "wangMaZi");
Set<String> set = map.keySet();
set.forEach((key) -> {
System.out.println("map的key是"+key);
System.out.println("map的值是"+map.get(key));
});
}
2.值遍历 values()方法,返回Map中所有value集合,类型为Collection类型
@Test
public void valuesTest() {
Map<String, String> map = new HashMap<>();
map.put("name1", "zhangSan");
map.put("name2", "liSi");
map.put("name3", "wangWu");
map.put("name4", "wangMaZi");
Collection<String> collection = map.values();
collection.forEach((value) -> System.out.println("map的值是"+value));
}
Map实现类:
1.HashMap(链表数组结构):线程不安全,查询速度快,允许使用null作为key或者value
2.LinkedHashMap:HashMap的子类,遍历的时候按照键值对的添加顺序遍历
3.TreeMap:自动按照key排序,属于SortedMap的实现类
4.Hashtable:线程安全,速度慢,不允许使用null作为key或者value
5.Properties:Hashtable的子类,键和值都是String类型的,常用于配置文件的读取
HashMap和Hashtable区别:
主要区别有:线程安全性,同步以及速度。
1.HashMap可以接收null作为它的key和value值,而Hashtable则不行。
2.HashMap是非synchronized,而Hashtable是synchronized的,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable,而如果没有正确同步的话,多个线程是不可能共享一个HashMap的。(另:java5提供了ConcurrentHashMap,它是Hashtable的替代,比Hashtable的扩展性更好)
3.HashMap底层是Hash链表结构,因此并不能保证随着时间的推移Map中的元素次序是不变的。
4.由于Hashtable是线程安全的也是synchronized的,所以在单线程环境下它比HashMap速度要慢,如果不需要同步,只需要一个单线程,推荐使用HashMap
5.两者迭代器不同。HashMap的迭代器Iterator是fail-fast迭代器,而HashTable的enumerator迭代器不是fail-fast机制。
fail-fast机制和fail-safe机制总结:
fail-fast:(主要应用于HashMap,Vector,ArrayList,HashSet等)
fail-fast机制是在遍历一个集合的时候,当集合结构被修改,则会抛出Concurrent Modification Exception异常
fail-fast会在一下两种情况下抛出Concurrent Modification Exception异常:
1.单线程环境:集合被创建后在遍历的过程中修改了结构
2.多线程环境:当一个线程在遍历这个集合的时候,另一个线程对这个集合的结构进行了修改
方式一:会抛异常
@Test
public void test() {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
Iterator it = list.iterator();
int m;
while (it.hasNext()) {
m = (int) it.next();
System.out.println(m);
list.remove(m);
}
}
此时会抛出异常java.util.ConcurrentModificationException
方式二:使用迭代器的remove方法不会抛异常并且成功删除指定元素
@Test
public void test() {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
Iterator it = list.iterator();
while (it.hasNext()) {
if((int)it.next()==3){
it.remove();
}
}
for(int i:list){
System.out.println(i);
}
}
fail-safe:(主要应用于CopyWriteArrayList,CncurrentHashMap等)
fail-safe机制指的是任何对集合结构的修改都会在一个复制的集合上进行修改,因此不会抛出Concurrent Modification Exception异常
但是fail-safe机制存在两个问题:1.需要复制集合,产生大量的无效对象,开销大
2.无法保证读取的数据是目前原始数据结构中的数据