Map集合概述和特点
- Map接口特点(键值对)
- 将键映射到值的对象
- 一个映射不能包含重复的键(多对一)键可多而值不可多
- 每个键最多只能映射到一个值
- Map接口和Collection接口的不同
- Map是双列的,Collection是单列的
- Map的键唯一,Collection的子体系Set是唯一的
- Map集合的数据结构值针对键有效,跟值无关;
Collection集合的数据结构是针对元素有效
依赖关系
我们可以看下hashSet和HashMap的依赖关系。
hashSet的add方法
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
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;
}
结论:hashSet调用了HashMap方法。
Map集合的功能——增删功能
增加
//增加 put()方法
Map<String,Integer> map = new HashMap<>();
Integer i1 = map.put("xiaoming",20);//返回Null
Integer i2 = map.put("xiaohong",21);
Integer i3 = map.put("xiaoqiang",22);
Integer i4 = map.put("xiaoming",22); //如果之前有了就返回被覆盖值
//特点:如果键是第一次存储,就直接存储元素,并返回null,不是的话,就用值替换掉,返回以前的值
删除
//删除 clear() 移除所有的键值对元素
//remove(Object key):根据键删除键值对元素,并把值返回
```java
Integer value = map.remove("xiaoming");//删除元素,返回键对应的值
判断
- boolean containsKey(Object key):判断集合是否包含指定的键
- boolean containsValue(Object value):判断集合是否包含指定的值
- boolean isEmpty():判断集合是否为空
获取 - Set<Map.Entry<K,V>> entrySet():
- V get(Object key):根据键获取值
- Set keySet():获取集合中所有键的集合,
- Collection values():获取集合中所有值的集合
长度 - int size():返回集合中的键值对的个数
Map集合的遍历之键找值
没有迭代器,所以不能用迭代器iterator
方法一:
获取所有键的集合
遍历键的集合,获取到每一个键
根据键找值
HashMap<String, Integer> hm = new HashMap<>();
hm.put("张三", 23);
hm.put("李四", 24);
hm.put("王五", 25);
hm.put("赵六", 26);
Set<String> keySet = hm.keySet(); //获取集合中所有的键
Iterator<String> it = keySet.iterator(); //获取迭代器
while(it.hasNext()) { //判断单列集合中是否有元素
String key = it.next(); //获取集合中的每一个元素,其实就是双列集合中的键
Integer value = hm.get(key); //根据键获取值
System.out.println(key + "=" + value); //打印键值对
}
//等同于
for(String key : hm.keySet()) { //增强for循环迭代双列集合第一种方式
System.out.println(key + "=" + hm.get(key));
}
方法二:
Map.Entry对象
获取所有键值对对象的集合
遍历键值对对象的集合,获取到每一个键值对对象
根据键值对对象找键和值
Set<Map.Entry<String,Integer>> entryDet = map.entrySet();
//获取每个对象
Iterator<Map.Entry<String,Integer>> it = entry.iterator();
while(it.hasNext()){
Map.Entry<String,Integer> en = it.next();
String key = en.getKey();
Integer value = en.getValue();
System.out.println(key + "="+value);
}
//等同于
for(Map.Entrt<String,Integer> en : map.entrySet()){
String key = en.getKey();
Integer value = en.getValue();
System.out.println(key + "="+value);
}
LinkedHashMap
LinkedHashMap和HashMap的特点是一样的,不过多一个特点是,保证如何存就如何取,那么查询就肯定慢一点
TreeMap集合键
TreeMap<String,Integer> tm = new TreeMap<>();
public static void main(String[] args) {
//demo1();
TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getName().compareTo(s2.getName()); //按照姓名比较
return num == 0 ? s1.getAge() - s2.getAge() : num;
}
});
tm.put(new Student("张三", 23), "北京");
tm.put(new Student("李四", 13), "上海");
tm.put(new Student("赵六", 43), "深圳");
tm.put(new Student("王五", 33), "广州");
System.out.println(tm);
}