1.无序,键值对,键不能重复,值可以重复,这里的无序指的也是插入的顺序和读取的顺序是不一样的,和set集合一样。
2. 键重复则覆盖,没有继承Collection接口,它单独继承Map接口,和list,set不一样,这两个继承collection接口
初始容量16,负载因子0.75,扩容增量1倍
先获取所有键的Set集合,再遍历(通过键获取值)取出保存所有Entry的Set,再遍历此Set即可。
1. 线程不安全,最常用,速度快
2. 内部采用数组来存放数据

流程图中绿色标出的部分为JDK8新增的处理逻辑,目的是在Table[i]中的Node节点数量大于8时,通过红黑树提升查找速度。
jdk1.8之前的链表结构示意图

jdk1.8 后的红黑树示意图

在这里,不得不说一下,什么是红黑树
1. 每个节点要么红要么黑
2. 根节点是黑色
3 .每个叶子节点都是黑色(叶子是NULL节点表示 或 NIL节点表示)。
4. 如果一个节点是红色的,那么它的子节点必须是黑色的子节点。(即不存在两个连续的红色节点)
5. 从任一节点到其每个叶子结点(NULL节点或 NIL节点)的所有简单路径都包含相同数目的黑色节点。
红黑树其实就是以第一个数据作为判断依据,后面进来的数据与其做比较,比他小的就在这个数的左边,比这个数大的就在右边,然后继续往下走,接在下面一步一步往下走,这就是红黑树。

这里提供一个可视化红黑树网址
点我跳转红黑树
https://www.cs.usfca.edu/~galles/visualization/RedBlack.html说完红黑树,我们来说一下jdk1.8之前的hashmap的原理怎么样的
首先在hashmap的底层有一个叫桶的数组,默认长度为16,这数组并不是保存的我们进来的元素,而是保存一个指向数据节点的一个指针,引用,首先通过key值hash运算,得到hashcould值,然后确定在数组上的位置,然后数据进来一个一个往下面的链表挤,往下挤,无论你有多少的元素我都一直往下挤。
而在jdk1.8后,先进行一个判断,判断你的元素长度是否大于8,如果小于8是一个链表结构,如果大于8是一个红黑树的结构,红黑树结构上面已经说了,所以这就是jdk1.8之后的一个区别,这样的结构使得map的速度更快了。
线程安全,不太常用,与vector类似,将所有数据加一把锁,性能很高
线程安全,比HashTable性能高,jdk1.8之前采用16把分段锁,将数据加锁,jdk1.8之后是每一个在数组的桶加锁,每一个桶一把锁,有多少桶就加多少锁,中间在赋值的时候才用的是cas,比较并替换。
key值按一定的顺序排序,添加或获取元素时性能较HashMap慢,因为需求维护内部的红黑树,用于保证key值的顺序
继承HashMap
LinkedHashMap是有序的,且默认为插入顺序
当我们希望有顺序地去存储key-value时,就需要使用LinkedHashMap了
代码实现
- Map<String, String> linkedHashMap = new LinkedHashMap<>();
- linkedHashMap.put("name1", "josan1");
- linkedHashMap.put("name2", "josan2");
- linkedHashMap.put("name3", "josan3");
- Set<Entry<String, String>> set = linkedHashMap.entrySet();
- Iterator<Entry<String, String>> iterator = set.iterator();
- while(iterator.hasNext()) {
- Entry entry = iterator.next();
- String key = (String) entry.getKey();
- String value = (String) entry.getValue();
- System.out.println("key:" + key + ",value:" + value);
- }
- package com.zking.test;
-
- import java.util.HashMap;
- import java.util.Hashtable;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.concurrent.ConcurrentHashMap;
-
- import org.junit.Before;
- import org.junit.Test;
-
- public class Maptest {
-
- private Map<String, String> map = new HashMap<>();
-
- @Before
- public void setup() {
- map.put("1", "李凝");
- map.put("2", "张山");
- map.put("3", "吴飞");
- map.put("4", "徐民");
- }
-
- @Test
- public void demo1() {
- System.out.println(map.get("3"));
- }
-
- @Test
- public void demo() {
- map.put("5", "zs");
- System.out.println(map.get("1"));
- System.out.println(map.get("5"));
- }
-
- @Test
- public void demo2() {
- Iterator<String> it = map.keySet().iterator();
- while (it.hasNext()) {
- String key = it.next();
- System.out.println(map.get(key));
- }
- // 获取value值
- }
-
- @Test
- public void demo9() {
- Iterator<Entry<String, String>> it = map.entrySet().iterator();
- while (it.hasNext()) {
- Entry<String, String> entry = it.next();
- System.out.println(entry.getKey() + ": " + entry.getValue());
- }
- // 获取key+value值
- }
-
- @Test
- public void demo10() {
- map.forEach((key, val) -> System.out.println(key + ":" + val));
- // foreach遍历出key+value值
- }
-
- @Test
- public void demo11() {
- if (!map.containsKey("4")) {
- map.put("4", "徐民");
- }
- map.putIfAbsent("4", "白牙");
- // map.putIfAbsent()如果这元素存在就不覆盖,put如果存在就覆盖
- // 使用 put 方法添加键值对,如果 map 集合中没有该 key 对应的值,则直接添加,
- // 并返回 value;如果已经存在对应的值,则会覆盖旧值,value 为新的值,返回值为 value。
- //
- // 2.使用 putIfAbsent 方法添加键值对,如果 map 集合中没有该 key 对应的值,则直接添加,
- // 并返回 null,如果已经存在对应的值,则依旧为原来的值,返回值为 value(旧的值)。
- map.forEach((key, val) -> System.out.println(key + ":" + val));
- }
-
- @Test
- public void demo3() {
- Map<String, String> map = new HashMap<>();
- map.put("1", "李凝");
- map.put("2", "张山");
- map.put("3", "吴飞");
- map.put("4", "徐民");
-
- Iterator<Entry<String, String>> it = map.entrySet().iterator();
- while (it.hasNext()) {
- Entry<String, String> next = it.next();
- System.out.println(next.getKey() + " : " + next.getValue());
- }
- // 迭代器遍历出元素
- }
-
- @Test
- public void demo4() {
- // 对已存在的key为1的记录进行了覆盖
- map.put("1", "微信");
- System.out.println(map.get("1"));
- }
-
- @Test
- public void demo5() {
-
- // 如果指定的key值不存在,则加入map
- if (!map.containsKey("2")) {
- map.put("2", "rest");
- }
-
- // 更简单的方式
- String val = map.putIfAbsent("2", "rest");
-
- System.out.println(map.get("2"));
- System.out.println(val);
- }
-
- @Test
- public void demo6() {
- map.remove("1");
-
- map.forEach((key, val) -> System.out.println(key + ":" + val));
- //删除方法
- }
-
- @Test
- public void demo12() {
- Hashtable<String, String> table = new Hashtable();
- table.put("1", "指针");
- table.forEach((key, val) -> System.out.println(key + ": " + val));
- // Hashtable
- }
-
- @Test
- public void demo13() {
- ConcurrentHashMap<String, String> table = new ConcurrentHashMap<>();
- table.put("1", "指针");
- table.forEach((key, val) -> System.out.println(key + ": " + val));
- }
- // ConcurrentHashMap
-
- }
- private TreeMap<String,Student> treeMap;
-
- @Before
- public void setup() {
- treeMap = new TreeMap<String,Student>(new Comparator<String>() {
-
- @Override
- public int compare(String o1, String o2) {
- // TODO Auto-generated method stub
- // 负数 0 正数
- return o1.compareTo(o2);
- }
-
-
- });
- treeMap.put("1", new Student(1, "zs", 0));
- treeMap.put("2", new Student(3, "ls", 0));
- treeMap.put("3", new Student(2, "ww", 0));
- treeMap.put("4", new Student(4, "zl", 0));
- }
-
- @Test
- public void demo1() {
- treeMap.forEach((key, val) -> System.out.println(key + ":" + val));
- }
-