目录
无序、key唯一、value允许重复、key和value允许为null。
[2.1 JDK 1.7](#2.1 JDK 1.7)
[2.2 JDK 1.8](#2.2 JDK 1.8)
[2.3 关键参数](#2.3 关键参数)
[2.4 关键计算](#2.4 关键计算)
[3.1 初始化](#3.1 初始化)
[3.2 扩容](#3.2 扩容)
[4.1 根据key存入value](#4.1 根据key存入value)
[4.2 根据key获取value](#4.2 根据key获取value)
[4.3 判断Map](#4.3 判断Map)
[4.4 根据key替换value](#4.4 根据key替换value)
[4.5 根据key删除value](#4.5 根据key删除value)
[4.6 遍历Map](#4.6 遍历Map)
一、什么是Map?
(1)Map是一种键值对集合,每一个元素都包含一个 键对象(key) 和一个 值对象(value)。
(2)Map集合中,键不允许重复,值可以重复。 (比如身份证与姓名)
(3)键和值是一一对应的,通过键可以找到与之对应的唯一的值。
(4)key和value必须是引用数据类型。
二、实现类HashMap
1.关键特点
无序、key唯一、value允许重复、key和value允许为null。
2.数据结构
2.1 JDK 1.7
数组+单向链表
在链表中插入元素,采用【头插法】
2.2 JDK 1.8
数组+单向链表+红黑树
在链表中插入元素时,采用【尾插法】
2.3 关键参数
(1)Node<K, V>[ ] table:
保存KV键值对的数组,每个KV键值对都被封装成一个Node对象。
数组容量决定了HashMap对内存的占用大小。
(2)float loadFactor:
加载因子(填充因子)。
加载因子默认为0.75,代表HashMap对数组容量的使用率为75%,超过该使用率,则数组需要进行扩容。
加载因子决定了HashMap对数组的使用率,加载因子越高,则表示允许填满的元素就越多,集合的空间利用率就越高,但是冲突的机会增加。反之,越小则冲突的机会就会越少,但是空间很多就浪费。
(3)int threshold:
扩容阈值。
用于判断数组是否需要进行扩容。
扩容阈值threshold = 数组容量 × 加载因子。
(4)size : int
KV键值对的数量。
2.4 关键计算
(1)hash()函数:
(h = key.hashCode()) ^ (h >>> 16):在key原有哈希值的基础上,与哈希值的高16位进行异或运算,计算出的哈希值更佳散列,不易出现哈希冲突。
(2)下标计算:JDK 1.7 :hash % 数组长度。
JDK 1.8:(数组长度 - 1) & hash。提高性能--数组长度必须为2的N次幂。
3.扩容方式
3.1 初始化
(1)public HashMap():加载因子默认为为0.75。
(2)public HashMap(int initialCapacity, float loadFactor):指定容量和加载因子。
3.2 扩容
(1)添加第一个KV键值对,数组如果为空,则默认扩容为16。
(2)加入元素时,如果链表长度大于阈值(默认为 8)并且数组长度小于64,会产生数组扩容;*2。
(3)添加元素后,当HashMap中的元素个数超过【数组大小 × 加载因子(LoadFactor)】时,原数组扩容2倍。例如:加载因子(LoadFactor)的默认值为0.75,数组容量默认为16,当HashMap中元素个数超过16 × 0.75=12的时候,数组的容量扩容为16×2 =32;
4.常见方法
4.1 根据key存入value
(1)V put(K key, V value):存入【KV键值对】,如果key存在,则覆盖【原value值】,保存后,返回【原value值】。
(2)void putAll(Map m):将【指定map】中的所有KV键值对,存入【当前map】。
(3)V putIfAbsent(K key, V value):如果key不存在,则保存value,并返回【null】;如果key已经存在,则不保存value,并返回【原value值】。
4.2 根据key获取value
(1)V get(Object key):根据key,返回【value值】;如果key不存在,则返回【null】。
(2)V getOrDefault(Object key, V defaultValue):根据key,返回【value值】;如果key不存在,则返回【默认值】。
4.3 判断Map
(1)boolean containsKey(Object key):判断key是否存在。
(2)boolean containsValue(Object value):判断value是否存在。
(3)boolean isEmpty():判断map中的【KV键值对】数量是否为0。
(4)int size():获取map中的【KV键值对】数量。
4.4 根据key替换value
(1)V replace(K key, V value):根据key,替换value,并返回【原value值】;如果key不存在,则返回【null】。
(2)boolean replace(K key, V oldValue, V newValue):根据key和value,替换value,修改成功,返回【true】;如果key和value不存在,则替换失败,返回【false】。
4.5 根据key删除value
(1)V remove(Object key):根据key,删除【KV键值对】,并返回【原value值】。
(2)boolean remove(Object key, Object value):根据key和value,删除【KV键值对】,则删除成功,返回【true】;如果key和value不存在,则删除失败,返回【false】。
(3)clear():清除map中的键值对。
4.6 遍历Map
(1)Set<K> keySet():获取所有key。
(2)Collection<V> values():获取所有value。
(3)Set<Map.Entry<K,V>> entrySet():获取所有【KV键值对】,每个【KV键值对】使用【Entry类型的对象】封装。
java
public class Demo01 {
public static void main(String[] args) {
//HashMap 无序,且key是唯一的,value是可重复的
HashMap<String,String> hashMap=new HashMap<>();
hashMap.put("110","北京");
hashMap.put("120","天津");
hashMap.put("130","河北");
hashMap.put("610","陕西");
hashMap.put("610","甘肃");
hashMap.put("620","甘肃");
System.out.println(hashMap);
}
}
java
public class Demo02 {
public static void main(String[] args) {
HashMap<String, String> hashMap = new HashMap<>();
insertElement(hashMap);
//selectElement(hashMap);
deleteElement(hashMap);
}
public static void insertElement(HashMap<String, String> hashMap) {
System.out.println("========进入到添加方法中========");
//1.V put(K key, V value)存键值对,如果集合不存在此键,直接存,返回值为null
//当存在此键时,返回值为上一次的键对应的value,用此value覆盖
String item1 = hashMap.put("110", "北京");
String item2 = hashMap.put("110", "天津");
hashMap.put("130", "河北");
hashMap.put("610", "陕西");
System.out.println("第一次存返回值:" + item1);
System.out.println("第二次存返回值:" + item2);
//void putAll(Map m)
HashMap<String, String> hashMap1 = new HashMap<>();
hashMap1.put("620", "甘肃");
hashMap1.put("630", "宁夏");
hashMap1.put("610", "内蒙");
//将指定map中的所有KV键值对,存入到当前map;
hashMap.putAll(hashMap1);
System.out.println(hashMap);
//V putIfAbsent(K key,V value)如果存在此键,返回值为键对应的旧值,如果不存在则存返回null
String oldValue = hashMap.putIfAbsent("611", "西安");
System.out.println("putIfAbsent再次存610的键:" + oldValue);
System.out.println(hashMap);
}
public static void selectElement(HashMap<String, String> hashMap) {
System.out.println("=======进入到查看方法中=======");
System.out.println("目前map中的元素为:" + hashMap);
//V get(Object key)根据key,返回value值,如果key不存在,则返回null
String value1 = hashMap.get("120");
System.out.println("键120对应的值为" + value1);
//V getOrDefault(Object key,V defaultValue)
//根据key,返回value值,如果key不存咋,则返回默认值
String value2 = hashMap.getOrDefault("120", "不知道");
System.out.println("键120对应的值为:" + value2);
//boolean containsKey(Object key)判断key是否存在
boolean b1 = hashMap.containsKey("611");
System.out.println("键611是否存在:" + b1);
//boolean containsValue(Object value)判断value是否存在
boolean b2 = hashMap.containsValue("宁夏");
System.out.println("值宁夏是否存在:" + b2);
//boolean isEmpty()判断map中的【KV键值对】数量是否为0
System.out.println("集合map是否为空:" + hashMap.isEmpty());
//int size()获取map中的【KV键值对】数量
System.out.println("集合的size:" + hashMap.size());
}
public static void deleteElement(HashMap<String, String> hashMap){
System.out.println("========进入到删除和修改方法中========");
System.out.println("目前map中的元素为:" + hashMap);
//V replace(K key, V value)根据key,替换value,并返回【原value值】;如果key不存在,则返回【null】
String value=hashMap.replace("110","北京");
System.out.println(value);
System.out.println("修改后的hashmap:"+hashMap);
//boolean replace(K key, V oldValue, V newValue)
//根据key和value,替换value,修改成功,返回【true】;如果key和value不存在,则替换失败,返回【false】;
boolean b1=hashMap.replace("610","内蒙","陕西");
System.out.println(b1);
System.out.println("修改后的hashmap:"+hashMap);
//V remove(Object key)根据key,删除【KV键值对】,并返回【原value值】
String str=hashMap.remove("130");
System.out.println(str);
System.out.println("删除后的hashmap:"+hashMap);
//boolean remove(Object key, Object value)
//根据key和value,删除【KV键值对】,则删除成功,返回【true】;如果key和value不存在,则删除失败,返回【false】;
boolean b2=hashMap.remove("630","陕西");
System.out.println(b2);
System.out.println("删除后的hashmap:"+hashMap);
//clear()
hashMap.clear();
System.out.println("清空后:"+hashMap);
}
}
java
public class Demo03 {
public static void main(String[] args) {
HashMap<String,String> hashMap=new HashMap<>();
hashMap.put("110","北京");
hashMap.put("120","天津");
hashMap.put("130","河北");
hashMap.put("610","陕西");
hashMap.put("620","甘肃");
System.out.println(hashMap);
//1.Set<K> keySet()获取所有的键
Set<String> keys = hashMap.keySet();
for (String key : keys) {
String value = hashMap.get(key);
System.out.printf("键为:%s - 值为%s\n", key, value);
}
//2.获取所有的value Collection<V> values()
Collection<String> values = hashMap.values();
System.out.println(values);
//3.获取所有的键值对集合对象
Set<Map.Entry<String, String>> entries = hashMap.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey() + "==" + entry.getValue());
}
}
}