
1 集合概述
1.1 为什么出现集合类
由于面向对象语言对事务的体现都是对象,为了方便对对象进行操作
1.2 数组和集合的区别
- 数组即可以存储引用类型,也可以存储基本类型,但长度不变
- 集合只能存储引用类型,但长度可变
1.3 集合的特点
- 只能存储引用类型
- 长度可变
1.4 集合的基础体系结构
Java中提供了多种集合类,进程操作不同的数据结构,集合类肯定有共性内容,向上提取
2 Collection集合
Collection集合是集合的顶层接口,子体系存在有序和无序,存在唯一和有重复
2.1 Collection集合的常用方法
2.1.1 添加方法
public boolean add(E e):添加一个元素
public boolean addAll(Collection c):添加一个集合中的元素
2.1.2 删除方法
public void clear():移除集合中的所有元素
public boolean remove(Object obc):删除指定元素
public boolean removeAll(Collection<?> c):删除一个集合的元素,只要一个元素被移除就返回true
2.1.3 获取方法
Iterator<E> iterator():迭代集合中所有元素
public int size():获取集合中的元素个数
2.1.4 判断方法
public boolean contains(Object obj):判断集合是否包含此元素
public boolean containsAll(Collection<?> c):判断集合中是否包含执行元素的集合,只有包含全部元素返回true
public boolean isEmpty():判断集合是否为空
2.1.5 交集
public boolean retainAll(Collection<?> c):保留集合中和输入集合一样的元素,集合发生改变返回true,不发生改变为false
2.1.6 集合转数组
public Object[] toArray():
2.1.7 数组转集合
public static<T> asList(T...a):Arratys数组工具类的方法
3 List集合
3.1 List集合的特点
- 有序
- 存在索引,通过索引获取具体元素
- 元素可重复,运行元素为null
3.2 List的特有方法
3.2.1 添加方法
public void add(E e,int index):在指定索引处添加元素
3.2.2 获取方法
public E get(int index):获取指定索引处的元素
3.2.3 删除方法
public E remove(int index):删除指定索引处的元素
3.2.4 修改方法
public E set(int index,E e):修改指定索引处的元素并返回被修改的元素
3.2.5 listIterator迭代器特有功能-逆向遍历
public Object previous():遍历list集合从后往前获取元素
public boolean hasPrevious():获取下一个元素
问题:
- 产生并发修改异常:对象的并发修改,但不允许此种修改时,抛出异常
产生原因:迭代器是依赖集合而存在的,判断成功后,集合中新增了元素,迭代器不知道,即报错- 迭代器遍历集合时,集合不能修改元素。
解决方案:集合遍历元素,集合修改元素(普通for循环)
3.3 List的子类的特点
3.3.1 ArrayList特点
- 底层是数据结构是数组,查询快,增删慢
- 线程不安全,效率高
3.3.2 Vector特点
- 底层数据结构是数组,查询快,增删慢
- 线程安全,效率低
3.3.3 LinkedList特点
- 底层数据结构是双向链表,查询慢,增删快
- 线程不安全,效率高
- 特有方法:
1.添加功能
public void addFirst(E e):在开头添加元素
public void addLast(E e):在末尾添加元素
2.获取功能
public void getFirst(E e):获取开头元素
public void getLast(E e):获取末尾元素
3.删除功能
public void removeFirst(E e):删除开头元素
public void removeLast(E e):删除末尾元素
4 Set集合
4.1 Set集合特点
- 无序(存储和取出元素的顺序不一致)
- 唯一,运行元素为null
4.2 Set子类的特点
4.2.1 HashSet类(无序和唯一)
- 不保证set的迭代顺序;
- 特别不保证该顺序永恒
- 元素唯一
4.2.1.1 HashSet如何保证元素顺序唯一的
- 底层数据结构是哈希表(元素是链表的数组)–实际上依赖于hashMap实现
- 哈希值一般与对象的成员变量相关
- 哈希表依赖于哈希值存储
- 添加功能底层依赖两个方法
int hashCode()
boolean equeals(Object obj)
- 实现步骤:
- 首先进行哈希值得比较,利用该对象的hashCode()方法获取该对象的哈希值
- 如果相同,进行地址值的比较或者equeals方法
- 返回true,就不添加set集合
- 返回false,添加进set集合
- 不同,添加元素进set集合
- 如果相同,进行地址值的比较或者equeals方法
- 首先进行哈希值得比较,利用该对象的hashCode()方法获取该对象的哈希值
4.2.2 LinkedHashSet类(有序和唯一)
- 链表保证元素有序
- 哈希表保证元素唯一
4.2.3 TreeSet类
-
使用TreeSet集合需要自定义的对象的定义排序方式和保证唯一的方法,不同的排序对应不同的保证唯一的方法,元素不能为null
-
底层数据结构是红黑树(红黑树是一种自平衡的二叉树)
4.2.3.1 排序和唯一
按照某种规则进行排序:
- 使用元素的自然排序对元素进行排除(Comparable)-自然排序
- 根据创建set时提供的Comparator进行排序(Comparator)-比较器排序
唯一:
- 根据比较方法的返回值是否是0决定
具体取决于使用的构造方法:
- 空参构造:自然排序,Comparable compareTo()方法
- 有参构造:比较器排序,接收Comparator接口的子类,compare()方法
4.2.3.2 实现过程
通过观察TreeSet的add方法,最终发现需要依赖于TreeMap的put()方法
自然排序:
- 唯一:根据成员变量值都相同即为同一元素
- 要求:
- 真正的自然排序比较的是compareTo()方法,而此方法是定义在Comparable接口中,要使用该方法,存放的元素对象必须实现Comparable接口
//空参构造
TreeSet<Person> hs = new TreeSet<Person>();
//实现Comparable接口
public class Person implements Comparable<Person> {
//自定义比较规则
@Override
public int compareTo(Person o) {
if(null == o){
return 0;
}
if(!(o instanceof Person)){
return 0;
}
int num = (this.getAge()-o.getAge() == 0) ? this.getName().compareTo(o.getName()) : this.getAge()-o.getAge();
return num;
}
比较器排序:在创建TreeSet对象时构造方法需要传入Comarator接口实现类
- 要求:
- 需要定义一个Comparator比较器接口实现类,重写compare()方法,在该方法中定义规则
- 直接使用匿名内部类或者lambda表达式
TreeSet<Person> hs = new TreeSet<Person>((Person p1,Person p2)->{
int num = p1.getName().length() - p2.getName().length();
int num1 = num == 0 ? p1.getName().compareTo(p2.getName()) : num;
int num2 = num1 == 0 ? p1.getAge() - p2.getAge() :num1;
return num2;
});
Person s1 = new Person();
Person s2 = new Person();
s1.setAge(22);
s1.setName("枫林");
s2.setAge(28);
s2.setName("枫林");
hs.add(s1);
hs.add(s2);
for(Person s : hs){
System.out.println(s.toString());
}
5 Collections工具类
5.1 Collections的概述
针对集合操作的工具类
5.2 Collections的常用方法
public static <T> void sort(List<T> list)排序,默认按自然排序
public static <T> int binarySearch(List<?> list,T key);二分查找
public static <T> T max(Collection<?> coll);最大值
public static void reverse(List<?> list);反转
public static void shuffle(List<?> list);随机置换