Map接口
* 接口的特点
* 1.双列集合的顶级接口
* 2.Map集合以"对"为单位进行存储,其中一个key,一个value
* 3.key和value之间的关系是"映射关系"
* 4.key和value的泛型类型可以相同,也可以不同
* 5.在映射关系中,key不可以重复,value可以重复
* 接口的位置
* java.util
* 接口的方法
* V put(K key,V value)
* 将指定的值与此映射中的指定键关联(可选操作)。
* void clear()
* 从此映射中移除所有映射关系(可选操作)。
* boolean containsKey(Object key)
* 如果此映射包含指定键的映射关系,则返回 true。
* boolean containsValue(Object value)
* 如果此映射将一个或多个键映射到指定值,则返回 true。
* V get(Object key)
* 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
* boolean isEmpty()
* 如果此映射未包含键-值映射关系,则返回 true。
* V remove(Object key)
* 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
* int size()
* 返回此映射中的键-值映射关系数
* Set<K> keySet()
* 返回此映射中包含的键的 Set 视图。
* Collection<V> values()
* 返回此映射中包含的值的 Collection 视图。
* Set<Map.Entry<K,V>> entrySet()
* 返回此映射中包含的映射关系的 Set 视图。
* default void forEach(BiConsumer<? super K, ? super V> action)
* 针对map进行遍历
Map.Entry<K,V>接口
* 接口的特点
* 以key和value封装对象的集合
* 接口的位置
* Map接口中的Entry<K,V>
* 接口的方法
* K getKey()
* 返回与此项对应的键。
* V getValue()
* 返回与此项对应的值。
HashMap类
* 类的特点
* 1.HashMap集合的底层数据结构是"哈希表"
* JDK7.0(包含)以前:存储链表对象的数组
* JDK8.0(包含)以后:存储链表对象或者红黑树对象的数组
* 2.HashMap集合可以存储null值和null键,使用键或值的时候需要进行非空校验,防止空指针异常
* 3.HashMap集合是无序的集合
* 4.HashMap集合无法保证元素在集合中的位置永远不会改变
* 5.HashMap集合是线程不安全的,只适用于单线程程序,如果在多线程中进行使用,需要手动添加线程安全
* 类的位置
* java.util
* 类的构造器
* public HashMap()
* 构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
* 类的方法
* 详见Map接口的常用方法
HashMap集合元素存储过程的源码分析(基于JDK8.0):
* 1.相关名词解释
* 桶:底层数组的实时长度
* 桶元素:底层数组中存储的元素(null,链表对象,红黑树)
* 初始容量:底层数组的初始长度
* 加载因子:底层数组的进行扩容前阈值的参数
* 阈值:底层数组扩容前的标准
* 阈值 = (int)(底层数组长度 * 加载因子)
* 2.涉及成员变量,成员常量和方法的局部变量的备忘录
* 成员变量或成员常量:
* DEFAULT_INITIAL_CAPACITY(int):底层数组默认的初始长度
* MAXIMUM_CAPACITY(int):底层数组最大长度
* DEFAULT_LOAD_FACTOR(float):默认的加载因子
* TREEIFY_THRESHOLD(int):树化标准之一,链表对象的判断条件
* UNTREEIFY_THRESHOLD(int):链表化标准,红黑树结构中结点对象的数量
* MIN_TREEIFY_CAPACITY(int):树化标准之一,底层数组进行树化最小长度
* table(Node<K,V>[]):底层数组
* entrySet(Set<Map.Entry<K,V>>):底层键值对对象的集合
* size(int):集合中元素的数量
* modCount(int):集合中元素的计数器变量
* threshold(int):扩容前的阈值变量
* loadFactor(float):加载因子变量
* putVal()的局部变量:
* hash(int):通过key的hashCode重新计算的hash值
* key(K):待添加元素的键
* value(V):待添加元素的值
* tab(Node<K,V>[]):待存储操作的底层数组
* p(Node<K,V>):待存储元素在底层数组中待存储的索引位置上的桶元素
* n(int):待存储操作底层数组的长度
* i(int):待存储元素在底层数组中待存储的索引位置
* e(Node<K,V>):当前红黑树对象或链表对象的下一位对象
* k(K):待存储元素在底层数组中待存储的索引位置上的桶元素的key
* resize()的局部变量:
* oldTab(Node<K,V>[]):待重置前操作的底层数组
* oldCap(int):待重置前操作底层数组的长度
* oldThr(int):待重置前操作底层数组的阈值
* newCap(int):待重置后操作底层数组的长度
* newThr(int):待重置后操作底层数组的阈值
* hash(Object key)的局部变量
* h(int):key的hashCode值
* treeifyBin()的局部变量:
* n(int):底层待操作数组的长度
* index(int):
* e(Node<K,V>):
* 3.底层数组的初始容量和初始加载因子
* 初始容量和初始加载因子是多少取决于创建对象时的构造器
* (1)HashMap()
* 初始容量:创建对象时没有进行初始化操作,会在第一次添加元素时进行初始化操作,初始容量为16
* 初始加载因子:0.75
* (2)HashMap(int initialCapacity)
* 初始容量:自定义
* 初始加载因子:0.75
* (3)HashMap(int initialCapacity, float loadFactor)
* 初始容量:自定义
* 初始加载因子:自定义
* (4)HashMap(Map<? extends K,? extends V> m)
* 初始容量:参数集合的长度
* 加载因子:参数集合长度的加载因子
* 4.第一次添加元素时的扩容规则
* 扩容规则:16
* 5.如何确认元素在底层数组中的索引位置
* (1)将key的hashCode值重新计算hash值
* 代码:(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16)
* 解释:hash值的补码32位中,高16位的补码和hashCode值的高16位补码相同,低16位是hashCode值的高16位补码和hashCode值
* 的低16位补码进行按位异或
* 目的:重新计算hashCode是为了将元素可以更加均匀分布在各个桶之间
* (2)根据hash值和底层数组长度计算存储的索引位置
* 代码:(n - 1) & hash
* 解释:将hash值和底层数组长度-1进行按位与,得到结果是该元素在底层数组中存储的索引位置
* 6.后续添加元素时的扩容规则
* 扩容规则:
* 原来底层数组长度 << 1
* 7.底层数组中链表对象何时进行红黑树对象的转换(树化)
* (1)链表对象长度达到8时
* (2)底层数组长度达到64
* 8.底层数组中红黑树对象何时进行链表对象的转换(链表化)
* (1)红黑树结构中结点对象的数量降至6个
* 9.JDK7.0和JDK8.0的区别
* (1)底层数组的桶元素内容不同
* JDK7.0(包含)以前:null,链表对象
* JDK8.0(包含)以后:null,链表对象,红黑树对象
* (2)底层数组的数据类型不同
* JDK7.0(包含)以前:Entry<K,V>[]
* JDK8.0(包含)以后:Node<K,V>[]
* (3)无参构造器底层数组的初始容量不同:
* JDK7.0(包含)以前:16
* JDK8.0(包含)以后:创建对象时没有进行初始化操作,会在第一次添加元素时进行初始化操作,初始容量为16\
* (4)hash算法不同:
* JDK7.0(包含)以前:
* h ^= k.hashCode();
* h ^= (h >>> 20) ^ (h >>> 12);
* h ^ (h >>> 7) ^ (h >>> 4);
* JDK8.0(包含)以后:
* (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16)
* (5)底层数组的扩容规则:
* JDK7.0(包含)以前:
* 2 * 原来底层数组长度
* JDK8.0(包含)以后:
* 原来底层数组长度 << 1
*
*
* 默认的加载因子为什么是0.75?
* 默认加载因子 (.75) 在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询(时间)成本;加载
* 因子过低虽然减少了查询(时间)开销,但同时也增加了空间成本;
LinkedHashMap类
* 类的特点
* 1.LinkedHashMap集合的底层数据结构是"哈希表+链表"
* 链表的作用:维护元素的有序性
* 2.LinkedHashMap集合是有序的集合
* 3.LinkedHashMap集合可以存储null值和null键,使用键或值的时候需要进行非空校验,防止空指针异常
* 4.LinkedHashMap集合是线程不安全的,只适用于单线程程序,如果在多线程中进行使用,需要手动添加线程安全
* 类的位置
* java.util
* 类的构造器
* public LinkedHashMap()
* 构造一个带默认初始容量 (16) 和加载因子 (0.75) 的空插入顺序 LinkedHashMap 实例。
* 类的方法
* 详见Map接口的常用方法
TreeMap类
* 类的特点
* 1.TreeMap集合底层的数据结构是"红黑树结构"
* 2.TreeMap集合可以根据映射关系中键的自然顺序进行排序,或者根据创建映射时提供的 Comparator进行排序,具体取决于使用的构造方法。
* 3.TreeMap集合无序的集合
* 4.TreeMap集合不可以存储null键,存储时需要针对每个键进行非空校验,防止空指针异常,并且TreeMap集合可以存储null值,但获取
* 时需要针对每个值进行非空校验,防止空指针异常
* 5.TreeMap集合是线程不安全的,适用于单线程程序,如果在多线程中进行使用需要手动添加线程安全
* 类的位置
* java.util
* 类的构造器
* public TreeMap()
* 使用键的自然顺序构造一个新的、空的树映射。
* public TreeMap(Comparator<? super K> comparator)
* 构造一个新的、空的树映射,该映射根据给定比较器进行排序
* 类的方法
* 详见Map集合的常用方法
Hashtable类
* 类的特点
* 1.Hashtable集合底层的数据结构是"哈希表"
* 哈希表:存储链表对象的数组
* 2.Hashtable集合不可以存储null键和null值,需要在存储元素时进行非空校验,防止空指针异常
* 3.Hashtable集合是无序集合
* 4.Hashtable集合无法保证元素的顺序永远不会改变
* 5.Hashtable集合是线程安全的,适用于多线程程序,如果在单线程中进行使用,执行效率过低
* 类的位置
* java.util
* 类的构造器
* public Hashtable()
* 用默认的初始容量 (11) 和加载因子 (0.75) 构造一个新的空哈希表。
* 类的方法
* 常见Map集合的常见方法
HashMap和Hashtable之间的区别:
* 1.null键和null值是否可以存储不同
* HashMap:可以
* Hashtable:不可以
* 2.线程安全性不同
* HashMap:线程不安全
* Hashtable:线程安全
* 3.使用无参构造器创建对象时底层数组的初始容量不同
* HashMap:
* JDK7.0(包含)以前:16
* JDK8.0(包含)以后:先不进行初始化,在第一次添加元素时初始化16
* Hashtable:11
* 4.底层数组存储桶元素不同
* HashMap:
* JDK7.0(包含)以前:null,链表对象
* JDK8.0(包含)以后:null,链表对象,红黑树对象
* Hashtable:
* null,链表对象
* 5.底层数组的扩容规则不同:
* HashMap:
* JDK7.0(包含)以前:
* 2 * 原来底层数组长度
* JDK8.0(包含)以后:
* 原来底层数组长度 << 1
* Hashtable:
* JDK6.0(包含)以前:
* 原来底层数组长度 * 2 + 1;
* JDK7.0(包含)以后:
* (原来底层数组长度 << 1) + 1
Properties类
* 类的特点
* Properties 类表示了一个持久(存储在硬盘中)的属性集(配置文件)。
* 类的位置
* java.util
* 类的构造器
* public Properties()
* 创建一个无默认值的空属性列表。
* 类的方法
* public String getProperty(String key)
* 用指定的键在此属性列表中搜索属性。
* public void load(InputStream inStream)
* 从输入流中读取属性列表(键和元素对)。
* public void load(Reader reader)
* 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
* public Set<String> stringPropertyNames()
* 返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键
并发和并行:
* 并发:在同一时间段内发生的多件事情
* 并行:在同一时间发生的多件事情
*
* 进程和线程:
* CPU核心执行规则:每个核心在所有进程中进行高速无规则的切换动作
* 进程:操作系统中的应用程序,每个应用程序至少包含一条进程,程序进程由CPU核心进行控制
* 线程:每个进程中的线程,每条进程至少包含一条线程,程序线程由CPU核心中的线程进行控制
Thread类
* 类的特点
* 线程 是程序中的执行线程
* 类的位置
* java.lang
* 类的构造器
* public Thread()
* 分配新的 Thread 对象。
* public Thread(String name)
* 分配新的 Thread 对象。
* public Thread(Runnable target)
* 分配新的 Thread 对象
* public Thread(Runnable target,String name)
* 分配新的 Thread 对象
* 类的方法
* public static Thread currentThread()
* 返回对当前正在执行的线程对象的引用。
* public final String getName()
* 返回该线程的名称。
* public static void sleep(long millis)
* 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
* public void run()
* 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;
* 否则,该方法不执行任何操作并返回。
* public void start()
* 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。