JAVA集合1(List和比较器)
一.集合的分类
java 中针对数组的缺陷,提供了一种比数组灵活、使用方便的接口和类,它们位于 java.util 包,称为集合框架。
Java 中集合体系:
本篇我们先学习collections下的List接口
Iterable 接口,凡是实现了此接口的对象都能成为 for-each-loop 的目标。
for(数据类型 变量名 : 循环对象){
//循环体
}
//变量是循环对对象的值,不是索引
for (Object score:vector
) {
Student student = (Student) score;
sum+=student.getScore();
}
iterator() 方法返回一个类型的迭代器。
我们主要先研究java.util.Collection
java.util.Collection
public interface Collection<E>
extends Iterable<E>
从类的声明我们可以看到, Collection 接口继承了 Iterable 接口。也就意味着,实现了
Collection 接口的类也间接实现了 Iterable 接口,也就是说它们都能作为 for-each-loo
p 的循环对象
Collection 是集合层次结构中的根接口。集合表示一组对象,对象称为集合的元
素。有些集合允许重复元素,有些则不允许。 有些是有序的,有些是无序的(不保证
顺序)
方法名 | 返回值 | 描述 |
---|---|---|
add(E e) | boolean | 添加元素 |
addAll(Collection<? extends E> c) | boolean | 将集合c中的所有元素添加到此集合中 |
clear() | void | 清除所有元素 |
contains(Object o) | boolean | 集合中是否包含此元素 |
containsAll(Collection<?> c) | boolean | 集合中是否包含c集合中的所有元素 |
方法名 | 返回值 | 描述 |
---|---|---|
isEmpty() | boolean | 集合中是否有元素,如果没有返回true |
iterator() | Iterator | 继承自Iterable接口,返回集合的迭代器 |
remove(Object o) | boolean | 删除集合中的某个元素 |
removeAll(Collection<?> c) | boolean | 删除集合c中包含的所有元素 |
retainAll(Collection<?> c) | boolean | 保留集合c中的元素 |
size() | int | 返回此集合中的元素数 |
toArray() | Object[] | 返回一个包含此集合中所有元素的数组 |
二.子接口
子接口很多,主要研究 List 、 Set 、 Queue
1.Queue(队列)
public interface Queue<E>
extends Collection<E>
2.方法
方法名 | 返回值 | 描述 |
---|---|---|
add(E e) | boolean | 如果可以在不违反容量限制的情况下立即将指定元素插入此队列,则在成功时返回 true. 当前没有可用空间抛出一个 IllegalStateException。 |
offer(E e) | boolean | 如果可以在不违反容量限制的情况下立即插入,则将指定元素插入此队列。 |
element() | E | 检索但不删除此队列的头部,此方法的不同之处peek仅在于如果此队列为空,它会引发异常。 |
peek() | E | 检索不删除此队列的头,如果此队列为空,则返回 null ,如果不为空返回队列的头。 |
poll() | E | 检索并删除此队列的头,如果此队列为空,则返回 null。 |
remove() | E | 检索并删除此队列的头。 此方法与 poll 不同之处在于,如果此队列为空,它将抛出异常。 |
注意:QUEUE接口不允许插入NULL元素,也不允许包含重复的元素
2.Deque(双端队列)
public interface Deque<E>
extends Queue<E>
方法:
方法名 | 返回值 | 描述 |
---|---|---|
addFirst(E e) | void | 插入此双端队列的前面。 |
addLast(E e) | void | 双端队列的末尾插入元素,和 add(E e) 类似。 |
getFirst() | E | 检索,但不删除,第一个元素。 |
getLast() | E | 检索,但不删除,最后一个元素。 |
pop() | E | 删除并返回此deque的第一个元素。 |
push(E e) | void | 相当于 addFirst(E) 。 |
removeFirstOccurrence(Object o) | boolean | 从此双端队列中删除第一次出现的指定元素。如果双端队列不包含该元素,则它保持不变。 |
removeLastOccurrence(Object o) | boolean | 从此双端队列中删除最后一次出现的指定元素。如果双端队列不包含该元素,则它保持不变。 |
需要注意的是,Deque接口不是线程安全的,如果在多线程中使用,需要采取适当的同步措施
Deque接口主要特点包括:
- 双向插入和删除:
Deque
允许在队列的两端进行元素的插入和删除操作。你可以在队列的头部(前面)和尾部(后面)添加和移除元素。 - 可以用作栈:由于可以在队列的头部和尾部进行元素操作,
Deque
可以轻松地用作栈(先进后出,LIFO)的数据结构。push
和pop
方法允许在队列的头部添加和删除元素,模拟栈的行为。 - 可以用作队列:与栈不同,
Deque
也可以用作队列(先进先出,FIFO)的数据结构。offer
和poll
方法允许在队列的尾部添加和删除元素,模拟队列的行为。 - 支持双端迭代:
Deque
提供了双端迭代的功能,你可以从队列的头部或尾部开始迭代元素,或者使用iterator()
方法来获取一个标准的迭代器。 - 不允许空元素:通常情况下,
Deque
不允许包含空(null
)元素。 - 有实现类:Java 提供了多个实现
Deque
接口的类,包括LinkedList
和ArrayDeque
等。
3.Set
public interface Set<E>
extends Collection<E>
不包含重复元素的集合, 可以存 null 。
of 方法和 copyOf ,都是 static 方法返回一个不可修改的 Set 集合
Collection set = Set.of("a", "b", "c");
// Set set = Set.copyOf();
不可修改 Set 集合
它们是不可修改的。不能添加或删除元素。
不允许 null 元素。尝试使用 null 元素创建它们会导致 NullPointerException
需要注意的是这里的无法修改是指没有修改集合中值的操作,即使是覆盖原来的值也不可以
会出现UnsupportedOperationException报错
常用子类:HashSet 和 TreeSet
List
有序集合(也称为序列 )。 该集合用户可以精确控制列表中每个元素的插入位置。 用户
可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素
List 通常允许重复的元素、允许 null 元素
1.方法
方法名 | 返回值 | 描述 |
---|---|---|
add(int index, E element) | void | 将指定的元素插入此列表中的指定位置。 |
addAll(int index, Collection<? extends E> c) | boolean | 将指定集合中的所有元素插入到此列表中的指定位置。 |
get(int index) | E | 返回此列表中指定位置的元素。 |
indexOf(Object o) | int | 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回 -1。 |
lastIndexOf(Object o) | int | 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回 -1。 |
remove(int index) | E | 删除该列表中指定位置的元素,返回被删除的元素。 |
set(int index, E element) | E | 用指定的元素(可选操作)替换此列表中指定位置的元素,返回被替换的值。 |
subList(int fromIndex, int toIndex) | List | 返回此列表中指定的 fromIndex (含)和 toIndex 之间的元素集合。 |
default sort(Comparator c) | void | 按照 c 比较器进行自然排序。 |
static copyOf(Collection coll) | List | 按照迭代顺序返回一个不可修改的 List。 |
static of() | List | 返回包含任意数量元素的不可修改列表。 |
主要子类, ArrayList 、 LinkedList 、 Vector
Vector
-
Vector 类实现了可扩展的对象数组。 像数组一样,它包含可以使用整数索引访问的组件。 但是, Vector的大小可以变化。
-
Vector 是同步的,是线程安全的。
-
Vector 继承了 AbstractList 类,实现了 List 接口
-
内部是使用数组存储数据,也就是说在内存中开辟一个连续的空间
-
默认大小是10,当容量不足时,默认扩容方式是按倍增长( capacity * 2)可以自定义默认容量以及每次扩展多少容量
子类
Stack
Stack 类代表后进先出(LIFO)堆栈的对象, Stack 继承自 Vector 所以它有所有 Vecto
r 中的方法。
常用方法:
public class Stack<E> extends Vector<E>
方法
方法名 | 返回值 | 描述 |
---|---|---|
empty() | boolean | 此堆栈是否为空。 |
peek() | E | 返回此堆栈顶部的对象,而不从堆栈中删除它。 |
pop() | E | 返回并删除此堆栈顶部的对象。 |
push(E item) | E | 将 item 添加到堆栈的顶部。 |
search(Object o) | int | 返回对象在此堆栈上的位置(从1开始计数),如果对象不在堆栈中,则返回 -1。 |
三.比较器
问题:如何比较集合中两个对象的顺序(按照年龄)
通过集合自带的soft方法,
1.comparator
接口的实现比较器顺序
利用匿名类
sort(vector,new Comparator() { @Override public int compare(Object o1, Object o2) { if (o1 instanceof Student stu1 &&o2 instanceof Student stu2){ if (stu1.getAge()< stu2.getAge())return -1; else if(stu1.getAge()> stu2.getAge())return 1; else return 0; }throw new ClassCastException("类型不匹配"); } });
简化lambda表达式
vector.sort((o1,o2)->{ if (o1 instanceof StudentList stu1 &&o2 instanceof StudentList stu2){ return stu1.getAge()- stu2.getAge(); }throw new ClassCastException("类型不匹配"); });
2.自然比较(comparable)
接口实现重写compareTo方法
public int compareTo(Object o) throws RuntimeException {
if (o instanceof Student stu) {
//比较权重
if (this.age > stu.age) {
return 1;
} else if (this.age < stu.age) {
return -1;
}
if (this.score > stu.score) {
return 1;
} else if (this.score < stu.score) {
return -1;
}
return this.name.compareTo(stu.name);
}
throw new CompareException("类型不匹配");
}
自然比较
private static void sort(Student[] stus) {
// 冒泡
for (int i = 0; i < stus.length - 1; i++) {
// 每次比较的次数
for (int j = 0; j < stus.length - 1 - i; j++) {
// 比较
if (stus[j].compareTo(stus[j + 1]) > 0) {
// 交换
Student temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
}