1、java集合可以分为Collection和map体系
Collection接口:单列数据,定义了存取一组对象的方法的集合
1)List
:
元素有序、可重复的集合
2)Set
:
元素无序、不可重复的集合
Map
接口:
双列数据,保存具有映射关系“
key-value
对”的集合
2、了解
Collection
接口中的方法,这些方法也同样适用于Set 集合, List 和 Queue 集合。因为Collection 接口是 List、Set 和 Queue 接口的父接口。
3、
Iterator 接口
Iterator
对象称为迭代器
(
设计模式的一种
)
,主要用于遍历
Collection
集合中的元素。
Collection
接口继承了
java.lang.Iterable
接口,该接口有一个
iterator()
方法,那么所 有实现了Collection
接口的集合类都有一个
iterator()
方法,用以返回一个实现了 Iterator接口的对象。
4、
List
接口
JDK API
中
List
接口的实现类常用的有:
ArrayList
、
LinkedList
和
Vector
。
1)
ArrayList
ArrayList
是对象引用的一个
”
变长
”
数组
JDK1.7
:
ArrayList
像饿汉式,直接创建一个初始容量为
10
的数组
JDK1.8
:
ArrayList
像懒汉式,一开始创建一个长度为
0
的数组,当添加第一个元 素时再创建一个始容量为10
的数组
Arrays.asList(…) 方法返回值是一个固定长度的 List 集合
2)
LinkedList
双向链表
,内部没有声明数组,而是定义了
Node
类型的
first
和
last
,(Node是它数据存储的基本单位), 用于记录首末元素。
同时,定义内部类
Node
,作为
LinkedList
中保存数据的基本结构。Node
除了保存数据,还定义了两个变量:
prev
变量记录前一个元素的位置
next
变量记录下一个元素的位置
3)vector
默认大小是10,上面两个都是线程不安全的,
Vector
是线程安全的
注意:
Vector
每次扩容请求其大
小的
2
倍空间,而
ArrayList
是
1.5
倍。向list中添加元素要重写equals方法。
5、Set接口
Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals() 方法。set底层用的是map实现。
1)hashset
特点:不能保证元素的排列顺序 (不是随机性,每次遍历都是一样的顺序)、HashSet 不是线程安全的 、集合元素可以是 null
向HashSet中添加元素的过程:(七上八下)
----当向
HashSet
集合中存入一个元素时,
HashSet
会调用该对象的
hashCode()
方法 来得到该对象的 hashCode
值,然后根据
hashCode
值,通过某种散列函数决定该对象 在 HashSet
底层数组中
的存储位置。(这个散列函数会与底层数组的长度相计算得到在 数组中的下标,并且这种散列函数计算还尽可能保证能均匀存储元素,越是散列分布, 该散列函数设计的越好)
----如果两个元素的hashCode()
值相等,会再继续调用
equals
方法,如果
equals
方法结果为true
,添加失败;如果为
false
,那么会保存该元素,但是该数组的位置已经有元素了,那么会通过
链表的方式
继续链接。
----如果两个元素的
hashCode()
返回值不相等,则认为是不一样的元素,hashSet
将会把它们存储在不同的位置(以链表的方式),但依然可以添加成功。
HashSet
集合判断两个元素相等的标准
:
两个对象通过
hashCode()
方法比较相等,并且两个对象的 equals()
方法返回值也相等。
注意:底层也是数组,初始容量为
16
,当如果使用率超过
0.75
,(
16*0.75=12
)就会扩大容量为原来的2
倍。(
16
扩容为
32
,依次为
64,128....
等)。数组中存放的位置一样,hash值不一定一样。
结论:复写
equals
方法的时候一般都需要同时复写
hashCode
方法
注意:
2)
LinkedHashSet
在原有的hashset的基础上,每个元素添加了两个指针,分别指向前后元素,保证打印顺序就是添加顺序。
3)TreeSet
TreeSet 可以确保集合元素处于排序状态。TreeSet底层使用
红黑树结构存储数据.
TreeSet
两种排序方法:
自然排序
和
定制排序
。默认情况下,
TreeSet
采用自然排序。
TreeSet
的自然排序要求元素所属的类实现
Comparable
接口
定制排序,通过
Comparator
接口来实现。需要重写compare(T o1,T o2)
方法。
通过compareto比较元素是否相等,不再是equals方法,也不会用到hashcode。
6、map
Map
中的
key
用
Set
来存放,
不允许重复
,即key所在的
类,须重写hashCode()
和
equals()
方法。
1) HashMap
JDK 7及以前版本:HashMap是数组(Entry数组)+链表结构(即为链地址法),数组是直接创建的,长度16。
JDK 8
版本发布以后:
HashMap
是数组(Node数组)
+
链表
+
红黑树(用到TreeNode)实现(当链表数量大于8时,且数组长度大于64,结构转化为红黑树,否则只是扩容)。数组是put一个元素之后创建的,数组长度16。
向
HashMap中添加元素的过程:首先用到了向
HashSet
中添加元素的过程.首先根据key进行hash值的计算。
2)
LinkedHashMap
LinkedHashMap是hashmap的子类,在此基础上,使用了一对双向链表来记录添加的顺序,迭代顺序与Key-Value 对的插入顺序一致。
LinkedHashMap是hashmap的子类,在此基础上,使用了一对双向链表来记录添加的顺序,迭代顺序与Key-Value 对的插入顺序一致。
3)TreeMap
底层使用红黑树结构存储数据,TreeMap的key排序:自然排序和定制排序。
TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。
4)
Hashtable
默认元素是11,是一个古老的Map实现类,是线程安全的,它的rehash比起hashmap需要重新计算哈希值
5)Properties
是Hashtable的子类,该对象用于处理属性文件。Properties里的key和value都是字符串类型。
注意:HashMap最多允许一条记录的的键为Null,允许多条记录的值为Null;而HashTable和ConcurrentHashmap不允许记录的键或值为空
若子类不重写hashcode方法,那么原始object的hashcode 方法是用来求对象的内存地址
若子类不重写equals方法,那么原始object的equals 方法是用来比较对象的内存地址
7、Collections
Collections
是一个操作
Set
、
List
和
Map
等集合的工具类.
里面有一些同步控制方法。
问题一:
HashMap 的底层数组长度总是2的n次方的原因有两个,即当 length=2^n 时:
1)不同的hash值发生碰撞的概率比较小,这样就会使得数据在table数组中分布较均匀,空间利用率较高,查询速度也较快;
2)h&(length - 1) 就相当于对length取模,而且在速度、效率上比直接取模要快得多,即二者是等价不等效的,这是HashMap在速度和效率上的一个优化。