Map集合的特点:
Map集合以键值对的形式保存数据
Map没有继承Collection接口
键(key)不能重复唯一,如果键的值相同那么就会覆盖原来的值
值(value)值可以重复
先来学map的遍历方式
Map集合没是先转成Set集合,在通过迭代获取元素
第一种:keySet是键的集合,Set里面的类型即key的类型
将Map中所有的键存入到set集合中。因为set具备迭代器。所有可以迭代方式取出所有的键,再根据get方法。获取每一个键对应的值。 keySet():迭代后只能通过get()取ke
@Test
public void test01() {
//创建HashMap集合
Map<String,Integer> phone = new HashMap<String,Integer>();
phone.put("Apple", 7299);
phone.put("SAMSUNG", 6000);
phone.put("Meizu", 2698);
phone.put("Xiaomi", 2400);
//遍历map集合
Set<String> set = phone.keySet();
//利用set的遍历方式
for(String key:set) {
//通过key获取值
Integer value = phone.get(key);
System.out.println(key+"-->"+value);
}
}
第二种:entrySet是 键-值 对的集合,Set里面的类型是Map.Entry
Set<Map.Entry<K,V>> entrySet() //返回此映射中包含的映射关系的 Set 视图。 Map.Entry表示映射关系。entrySet():迭代后可以e.getKey(),e.getValue()取key和value。返回的是Entry接口
@Test
public void test02() {
//创建HashMap集合
Map<String,Integer> phone = new HashMap<String,Integer>();
phone.put("Apple", 7299);
phone.put("SAMSUNG", 6000);
phone.put("Meizu", 2698);
phone.put("Xiaomi", 2400);
//遍历map集合
Set<Entry<String,Integer>> set = phone.entrySet();
for(Entry<String, Integer> entry:set) {
//获取key
String key = entry.getKey();
Integer value = entry.getValue();
//输出
System.out.println(key+"--->"+value);
}
}
以上就是map集合的遍历的方式:
map集合可以转为set集合
使用set集合的迭代器遍历或者是增强for或者是普通for遍历
再来学习map集合里面的重要部分
HashMap
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>,,Cloneable, java.io.Serializable
可以发现HashMap继承了AbstractMap这个抽象类又实现了Implements(实现)Map的接口
HashTable
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable
可以发现HashMap和HashTable两个类继承不同
不同点:
HashMap继承AbstartMap
HashTable继承了Dictionary
相同点:
实现了Map接口,意味着它们都支持key-value键值对操作。支持“添加key-value键值对”、“获取key”、“获取value”、“获取map大小”、“清空map”等基本的key-value键值对操作。
实现了Cloneable接口,意味着它能被克隆。
实现了java.io.Serializable接口,意味着它们支持序列化,能通过序列化去传输
两者继承不同决定了HashMap和HashTable的之间不同
Dictionary:
public abstract
class Dictionary<K,V> {}
其一:这个类是一个抽象类没有继承或者实现;里面提供了Enumeration(枚举类)去遍历的方法所以‘由于Hashtable也实现了Map接口,所以,它即支持Enumeration遍历,也支持Iterator遍历(同时也实现了Map接口)
通过源码可以发现HashTable几乎所有的方法都有**synchronized**这个关键字;所以HashTable是线程安全的
支持多线程
但是HashMap的函数则是非同步的,它不是线程安全的;
若要在多线程中使用HashMap,需要我们额外的进行同步处理。 对HashMap的同步处理可以使用Collections类提供的synchronizedMap静态方法,或者直接使用java.util.concurrent包里的ConcurrentHashMap类(这以后会写)
其二:对null值的处理不同
下面是HashTable的保存key-value的方法:
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
//如果value为空那么此方法就会抛出空指针异常
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
addEntry(hash, key, value, index);
return null;
}
根据上面的源码可以发现HashTable的key和value都不能为空,如果为空那么会抛出
NullPointerException(空指针异常)
下面是HashMap的put方法:
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
//// 空表,需要初始化
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
HashMap的key、value都可以为null
Hashtable的key或value,都不能为null!否则,会抛出异常NullPointerException。
HashMap的key、value都可以为null