1、Java集合概述
1.1、介绍
- Java集合分为两个体系,分别是Collection和Map
- Collection接口:单列数据,就是没有Key,只有Value,包含子接口List和Set
- Map接口:双列数据,保存Key-Value数据
1.2、Collection接口
- Collection存储单列数据,包含子接口List和Set
- List接口三个实现类:Vector、ArrayList、LinkedList
- Set接口实现类:HashSet、LinkedHashSet、TreeSet(SortedSet接口时Set接口的子接口,TreeSet类是SortedSet接口的实现类)
1.3、Map接口
- Map接口与Collection接口并列存在,用于保存具有映射关系的数据Key-Value
- Map中的Key不允许重复,作为Key的类,要重写hashCode()和equals()方法
- 常用实现类:HashMap,TreeMap(实现SortedMap接口,SortedMap接口时Map的子接口),LinkedHashMap、Properties
2、List接口
2.1、概述
- List中的数据有序可重复,每个数据都有索引
- 常用实现类有ArrayList,LinkedList,Vector
2.2、ArrayList
- JDK1.7中的ArrayList属于饿汉式,在创建ArrayList对象时直接初始化容量为10的数组
- JDK1.7中的ArrayList属于懒汉式,在创建ArrayList对象时创建长度为0的数组,当添加第一个数据时在创建初始容量为10的数组
- Arrays.asList()方法返回的不是ArrayList集合,也不是Vector实例,而是一个固定长度的List集合
- 每次扩容请求为当前的1.5倍
2.3、LinkedList
- LinkedList内部没有使用数组来存储,而是使用双向链表来实现
- 定义Node内部类来存储数据
- 定义Node的first和last用于记录队首队尾
- 定义Node的prev和next来指向前一个和后一个元素
- LinkedList插入删除速度快,但是查找效率低
2.4、Vector
- Vector实现了线程安全,内部使用synchronized实现,所以消耗比较大
- 每次扩容请求为当前的2倍
2.5、List接口面试题
1、ArrayList和LinkedList异同
- 两者都线程不安全,执行效率高
- ArrayList基于动态数组,查询速度快,插入、删除效率低
- LinkedList基于双向链表,查询速度要遍历链表效率低,插入和删除速度快
2、ArrayList和Vector的区别
- 二者之间几乎没有什么区别
- 最大的区别就是Vector实现了线程安全,是同步类,开销比较大,效率较低
- Vector每次扩容2倍,ArrayList1.5倍
3、Set接口
3.1、概述
- Set接口时Collection接口的子接口,相对于Collection,Set接口没有提供额外的方法
- Set集合不允许添加重复的元素,如果两个元素相同,那么添加操作失败
- 判断两个对象是否相同,使用的是equals()方法
3.2、HashSet
3.2.1、HashSet介绍
- HashSet按照hash结果来确定存储位置,不能保证元素的排列顺序
- 线程不安全
- 集合中的元素可以是null
- 集合中判断元素(对象)是否想等的依据是hashCode()方法,如果hashCode方法返回结果一致,那么两个元素的equals(方法返回值也相等
- 对于集合中存储类类(元素),要重写equals()和hashCode()方法,且要实现相等的对象必须要有想等的散列码
3.2.2、HashSet添加过程
- 当向HashSet存入一个元素时,Hash首先调用hashCode()方法得到哈希码,根据哈希码,通过某种散列函数决定元素在底层数据中的存储位置(散列函数要求结果是下标,并且尽可能使得均匀存储元素,分布散列)
- 如果两个元素的哈希码一致,那么使用equals()方法判断两个对象是否一致,如果一致则插入失败,否则通过链表形式存储(即与前一个哈希值一样的元素构成链表)
- hashCode()返回结果不一致,但是equals()返回true的情况,也是可以存储的,直接按照返回的哈希码存储在不同的位置(其实有点违反原则了)
3.2.3、重写hashCode和equals方法原则
- 同一个对象多次调用hashCode(),返回的结果应该一致
- equals()返回true的两个对象,hashCode()返回结果应该一致
- equals()中用来比较的所有Field(属性),都应该用来结算hashCode值
- 应当遵“相等对象必须具有相等散列码”原则
- 重写equals的时候一般需要重写hashCode
3.3、LinkedHashSet
- LinkedHashSet是HashSet的子类
- 和HashSet一样使用哈希值来决定元素的存储位置,不同的是使用双向链表来维护元素的次序,使得元素看起来是按照插入顺序保存的
- LinkedHashSet因为要维护双向链表,所以性能比HashSet差
3.4、TreeSet
3.4.1、介绍
- TreeSet是SortedSet接口的实现类,SortedSet接口时Set接口的子接口
- TreeSet可以保证Set集合中的元素处于排序状态,按照排序大小来存储
- 可以自定义排序方法,传入Comparator比较器即可,或者使用自然排序(默认情况)
- 采用红黑树作为存储结构(自平衡二叉查找树)
- 不能存放相同的元素,如果两个元素(对象)一样,那么只存一个
- 存储的元素有序且查找速度快(用红黑树存着肯定快啊)
3.4.2、排序
- TreeSet会调用集合元素的compareTo方法来比较元素之间的大小,然后默认按照升序排列
- 如果一个对象要存储到TreeSet中,那么必须要实现TreeSet方法
- 将对象存入TreeSet方法中时,要重写该对象对应的equals方法,保证该方法与compareTo方法由一致的结果:也就是两个对象使用equals方法判断后,如果返回结果为true,那么compareTo方法应该返回0
- 可以根据一个对象中多个属性来排序,即一个属性相等之后,按照下一个属性来排序
4、Map接口
4.1、概述
- Map与Collection并列存在,用于保存具有Key-Value关系的数据
- Key和Value可以是任何引用类型的数据
- Map的常用实现类有HashMap,LinkedHashMap,Properties,TreeMap(TreeMap是SortedMap接口的实现类,SortedMap是Map的子接口)
4.2、HashMap
4.2.1、HashMap介绍
- HashMap是使用频率最高的Map实现类
- 允许使用null作为key,null作为value
- 构成key的集合是Set,无序,不可重复,在key的类中要重写equals和hashCode方法
- 构成value的集合是Collection,无序,可重复,在value的类中要重写equals方法(用于判断value是否一致,因为不需要使用value来确定存储位置,所以不需要重写hashCode方法)
- 一个key-value构成一个entry
- 构成entry的集合是Set,无序,不可重复
- key相等的标准:两个key通过equals方法返回true,且hashCode也一样
- value想等的标准:两个value通过equals方法返回true
4.2.2、HashMap原理
4.2.3、面试题
1、负载因子大小及其影响
- 当数据规模增长到(底层数组总长*负载因子)时,便会触发扩容机制,参考其它语言,将其设置为0.75(0.7~0.75),此时平均检索长度接近于常数
- 负载因子的大小决定了HashMap的密度
- 负载因子大,数据密度大,发生碰撞的概率高(数据很多了才扩容,肯定碰撞啊),查询或插入是比较的次数多,性能下降
- 负载因子小,数据密度小,发生碰撞大概率低,但是很容易触发扩容(就是数据很少也要扩容),扩容是要消耗资源的,性能下降2.
2、阈值
- JDK1.8中链表长度大于阈值时将链表转为红黑树
3、get/put方法过程
4.3、LinkedHashMap
- LinkedHashMap是HashMap的子类,在HashMap的基础上使用双向链表来记录添加时的顺序
- 由于使用的链表结构,迭代时按照插入顺序进行
- 由于使用了链表结构记录插入顺序信息,性能较HashMap会下降
4.4、TreeMap
- TreeMap可以根据需要对键值进行排序
- 底层使用红黑树实现
- 自然排序:TreeMap的Key需要实现Comparable接口,且所有的Key应当是同一个类的对象,否则抛出ClassCastException异常
- 定制排序:创建TreeMap时传入Comparator对象,该对象负责对Key进行排序
- 两个Key相等的标准:通过compareTo或compare方法返回0
4.5、Hashtable
- Hashtable是古老的Map实现类,实现了线程同步,线程安全,使用synchronized实现
- Hashtable实现原理和HashMap一样,功能相同,底层使用哈希表结构存储,查询速度快,但是相对于HashMap,效率要低一点
- 与HashMap不同,Hashtable不允许null作为key和value
- 与HashMap一样,Hashtable不保证顺序
- Hashtable判断key相等、value相等的标准与HashMap一致
4.6、Properties
- Properties是Hashtable的子类,用于处理属性文件
- 属性文件中的值一般都是key和value都是字符串类型,所以Properties中的key和value也是字符串类型
- 存取数据时使用setProperty(String key, String value)和getProperty(String key)方法