集合
前言: 我们学习过
数组
,即
固定长度的,数组长度一旦确定,这个数组最多存放多少个元素确定,无法做到自动扩容的用来
存储一组元素的容器。但是,有时候我们不知道需要存储的数据是多少时,就不能够使用数组来存储了,而是使用集合来存储数据。
一、List集合
1.1 定义
1、集合只能存放对象
2、集合与数组的不同在于:集合可变长度,不限制元素的类型,存储任意类类型的数据,也可以限定元素的类型——泛型
3、集合可以自动扩容
1.2 集合的类结构图
集合分为两大体系:
1、Collection接口:存储的单一对象
(1)List接口:可重复,有序(次序,有下标)
(2)Set接口:唯一,无序(次序,没有下标)
2、Map接口:存储的key/value键值对
(1)key任意数据类型,value任意数据类型
(2)key:唯一,value可重复
因此,我们大多数使用集合时是使用Collection接口下的list集合或者set集合。在Collection接口下,有着许多方法提供给我们解决问题,例如:
增删查改:add( ),addAll( ),remove( ),removeAll( ),clear( )
辅助方法:size( ),isEmpty( ),contains( )
(1)增加
(2)删除
(3)对比
两个对象比较:
理论: 两个对象是否是同一个对象: == equals() 都是在比较地址码是否一样,在实际开发中: 两个对象是否是同一个对象: 1. 如果地址码是否一样, 2. 两个对象的属性值是否一样
对自定义的类类型, 重写Object的equlas()方法, 重写hashCode()
(1)Set集合判断一个对象是否相等
- 判断两个对象的hashCode是否一样, 如果hashCode一样, 进行equlas()判断
- 如果hashCode一样,equals()返回true, 表示是同一个对象
- 如果hashCode不一样, 不会判断eqauls() , 不是同一个对象
- 如果hashCode一样,但是eqauls() 返回false, 不是同一个对象
(2)List判断两个对象是否相等
调用 对象equlas() 方法判断, 如果equals() 返回true, 表示同一个对象, 与hashCode无关
(4)哈希码值
将集合中元素的值转换成哈希码值。
(5)判断空集合
(6)元素的个数
1.3 ArrayList集合
定义:
ArrayList: 数组结构,查询效率高,对修改(插入元素,删除元素)效率低
public ArrayList():构造一个初始容量为十的空列表
Vector与ArrayList的区别:
- Vector是jdk1.0出现的,老版本java使用的集合,注重安全,是线程安全的;
ArrayList是jdk1.2之后使用,注重性能,是非线程安全的.
- 当长度扩充时,Vector直接扩充一倍,而ArrayList是扩充50%
ArrayList默认长度为10个,当存满10个时,长度会自动扩充50%
1.4 LinkedList集合
定义:
LinkedList: 双向链表结构,查询效率低,修改效率高
结论:ArrayList集合和LinkedList集合都是Collection接口下的集合,因此,在Collection接口的所有方法中,ArrayList集合和LinkedList集合都适用。
(1)单向链表
查询效率很低:查找某个点,只能头节点一个一个往下找
(2)双向链表
每个节点:既可以往前找,也可以往后找, 提高查询效率
二、set集合
2.1 简介
Set接口没有提供Collection接口额外的方法,但实现Set接口的集合类中的元素是不可重复的。
JDKAPI中所提供的Set集合类常用的有:
HashSet:散列存放(重点)
TreeSet:有序存放(重点)
LinkedHashSet: 有次序
2.2 HashSet集合
(1)HashSet的实现原理
- 是基于HashMap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap。封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
- 当我们试图把某个类的对象当成 HashMap的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的equals(Object obj)方法和 hashCode() 方法很重要,而且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们通过 equals() 方法比较也应该返回 true。通常来说,所有参与计算 hashCode() 返回值的关键属性,都应该用于作为 equals() 比较的标准。
- HashSet的其他操作都是基于HashMap的。
例子:
如何把同一个对象在HashSet集合中存入两次?
代码:
public class HashSetDemo {
public static void main(String[] args) {
// 创建 HashSet对象
Set set = new HashSet();
//加入元素到 HashSet 中
set.add("F");
set.add("B");
set.add("D");
set.add("E");
set.add("C");
set.add("B");//当添加相同的元素时,因为Set集合的元素时唯一的,所以会覆盖之前的B
System.out.println("set 最初的内容:" + set);
//删除元素
set.remove("F");
System.out.println("set 被改变之后:" + set);
}
}
结果:
通过上面的例子,我们发现Set的特点是无序的,元素是唯一的,我们放元素的顺序是”F—B—D—E–C”,而获取的顺序是”B-C-D-E-F”,同样我们发现Set集合的元素是唯一的,我们往Set集合放了两个”B”,但是在Set集合中只有一个”B”。
(2)hashCode()和equals()的比较
因为hashCode()和equals()方法的返回值共同决定了两个对象是否相等,所以覆写着两个方法时一般要保证两个方法的返回值保证兼容。
重写hashCode()和equals()方法的基本规则:
1、 如果两个对象通过equals()方法比较时返回true,则两个对象的hashCode()方法返回值应该也相等。
2、 对象中用作equals()比较标准的成员变量(属性),也应该参与到hashCode的计算。
2.3 TreeSet集合
(1) TreeSet实现原理
TreeSet使用红黑树结构对加入的元素进行排序存放,所以放入TreeSet中元素必须是可**“排序”**的。
(2) 可排序的对象
TreeSet可是采用两种方法实现排序:自然排序
和 定制排序
。默认情况,TreeSet采用自然排序。
TreeSet调用调用集合元素的CompareTo()方