Java 集合框架提供了一套性能优良、使用方便的接口和类,他们都位于 java.util
包中。Java 集合框架由3大类接口构成(Map接口
、List接口
、Set接口
)。
java.lang.lterable
接口是 Java 标准库中的一个接口,用于表示可迭代的集合类。实现了 lterable
接口的类可以使用 Java 中的 for-each
循环来遍历其元素,使其具有可迭代的特性。
返回值类型 | 方法名 | 描述 |
---|---|---|
Iterator | iterator() | 返回一个迭代器,用于遍历集合中的元素。 |
void | forEach(Consumer super E> action) | 对集合中的每个元素执行给定操作。 |
Spliterator | spliterator() | 返回一个拆分器,用于对集合中的元素进行分割迭代。 |
例子
import java.util.*;
public class VectorExample {
public static void main(String[] args) {
Vector<Student> students = new Vector<Student>();
students.add(new Student("犯困桃子", 10, 11));
students.add(new Student("小羊呆呆", 20, 11));
students.add(new Student("中科盛康人才", 5, 11));
students.add(new Student("小羊", 30, 11));
students.add(new Student("盛康人才", 1, 11));
// 比较排序
Collections.sort(students, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
return Integer.compare(s1.getMath(), s2.getMath());
}
});
// 使用 for-each迭代输出
for (Student student : students) {
System.out.println(student);
}
students.get(3).setName("三娃"); // 设置名称
students.insertElementAt(new Student("五娃", 20, 17), 4); // 指定下标插入
System.out.println(students.size());
students.remove(students.size() - 1); // 删除最后一个元素
// 使用 iterator() 输出
Iterator<Student> iterator = students.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
Collection
接口是 Java.util
包下的一个接口,用于表示一组对象是集合。它是 Java 集合框架中的根接口,继承了 lterable
接口,因此它可以用于遍历集合中的元素。Collection
接口提供了一组通用的方法,用于对集合进行基本的操作。
方法名 | 返回值 | 描述 |
---|---|---|
add(E e) | boolean | 添加元素 |
addAll(Collection extends E> c) | boolean | 将集合c中的所有元素添加到此集合中 |
clear() | void | 清除所有元素 |
contains(Object o) | boolean | 集合中是否包含指定元素 |
containsAll(Collection> c) | boolean | 集合是否包含指定集合中的所有元素 |
isEmpty() | boolean | 集合是否为空 |
iterator() | Iterator | 返回集合的迭代器 |
remove(Object o) | boolean | 删除集合中的某个元素 |
removeAll(Collection> c) | boolean | 删除集合中与指定集合中相同的所有元素 |
retainAll(Collection> c) | boolean | 保留集合中与指定集合中相同的元素 |
size() | int | 返回集合中的元素数 |
toArray() | Object[] | 返回包含集合中所有元素的数组 |
Collection
接口实现的类包括常见的 ArrayList
、LinkedList
、HashSet
、TreeSet
、LinkedHashSet
等。
public interface Queue<E>
extends Collection<E>
设计用于在处理之前保留元素的集合。 除了基本的 Collection
操作之外,队列还提供额外的插入,提取和检查操作,不可以存 null。
下面是常用的Queue接口方法及其描述:
方法名 | 返回值类型 | 描述 |
---|---|---|
add(E e) | boolean | 将指定元素插入此队列 。如果队列已满,则会抛出IllegalStateException 异常 |
offer(E e) | boolean | 将指定元素插入此队列 。 如果队列已满,则会返回false |
remove() | E | 检索并删除此队列的头部 。如果队列为空,则会抛出NoSuchElementException 异常 |
poll() | E | 检索并删除此队列的头部,如果此队列为空,则返回null |
element() | E | 检索但不删除此队列的头部 。如果队列为空,则会抛出NoSuchElementException 异常 |
peek() | E | 检索但不删除此队列的头部,如果此队列为空,则返回null |
size() | int | 返回队列中的元素数 |
contains(Object o) | boolean | 如果此队列包含指定元素,则返回true |
clear() | void | 移除此队列中的所有元素 |
toArray() | Object[] | 返回包含此队列所有元素的数组;返回数组按照队列元素排列顺序 |
上述方法是 Queue
接口中常用的方法,通过实现该接口,并重写其中的方法,即可定义自己的队列实现类。Queue
接口实现的类有很多,例如常用的有 LinkedList
、ArrayDeque
等。
Queue 接口不允许插入 null 元素,也不允许包含重复的元素。
public interface Deque<E>
extends Queue<E>
继承了 Queue
,支持两端(首尾)元素插入和移除的线性集合。
方法名 | 返回值类型 | 描述 |
---|---|---|
addFirst(E e) | void | 在双端队列的前面插入元素 |
addLast(E e) | void | 在双端队列的末尾插入元素,类似于add(E e) |
getFirst() | E | 检索但不删除双端队列的第一个元素 |
getLast() | E | 检索但不删除双端队列的最后一个元素 |
pop() | E | 删除并返回双端队列的第一个元素 |
push(E e) | void | 相当于addFirst(E e),在双端队列的前面插入元素 |
removeFirstOccurrence(Object o) | boolean | 从双端队列中删除第一次出现的指定元素,如果不存在则保持不变 |
removeLastOccurrence(Object o) | boolean | 从双端队列中删除最后一次出现的指定元素,如果不存在则保持不变 |
public interface Set<E>
extends Collection<E>
集合中的对象并不能保存重复的对象,也就是说 Set
接口可以储存一组唯一、无序的对象。
在Java中,Set
是一种集合接口,它继承自Collection
接口。Set集合的主要属性如下:
无序性:
Set集合中的元素是无序排列的,不会按照插入顺序或者其他特定顺序进行存储。这是因为Set集合通常基于哈希表或红黑树实现,以提供快速的插入、删除和搜索操作。
唯一性:
Set集合中不允许包含重复的元素。当添加重复元素时,Set集合会自动拒绝并保留唯一性。
不允许使用索引:
Set集合没有提供索引访问元素的方法,因为它的元素是无序的。如果需要按索引访问元素,应该使用List集合。
添加、删除和包含操作的性能较高:
由于Set集合通常使用哈希表或红黑树实现,可以在常数时间内执行添加、删除和包含操作。
允许使用null元素:
Set集合允许存储一个null元素。但需要注意,HashSet和LinkedHashSet不保证存储顺序,而TreeSet不允许存储null元素。
常见的Set集合实现类有:
HashSet
:基于哈希表实现,具有较好的查找性能,不保证元素的存储顺序。LinkedHashSet
:基于哈希表和链表实现,按插入顺序保留元素,具有较好的遍历性能。TreeSet
:基于红黑树实现,按照元素的自然顺序或者指定的Comparator进行排序。
of
方法和copyOf
,都是static
方法返回一个不可修改的Set
集合。
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, Serializable
实现了 Set
接口,底层实现是 HashMap
。不保证迭代顺序,允许 null
元素。
HashSet
的特性:
add
的值已存在( equals
方法返回 true
,基本数据类型自动装箱)返回 false
HashSet
中存的是对象,需要重写此对象类中的 equals
和 hashCode()
方法
- HashSet内部使用哈希表来存储元素,这使得插入、删除和查找元素的操作效率非常高。如果你需要对集合进行频繁的插入、删除和查找操作,并且不关心元素的顺序,那么HashSet可以提供较好的性能。
- 当需要存储唯一元素、不关心元素顺序、需要快速的插入、删除和查找操作时,选择HashSet是一个不错的选择。
public class TreeSet<E>
extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, Serializable
TreeSet
使用红黑树数据结构
来实现元素的排序和储存。TreeSet
中的元素按照自然排序或指定的比较器(Comparator)进行排序,并且不允许重复的元素,不允许 null
元素。
TreeSet
的特性:
如果使用
无参构造
则 Set 集合中的元素要具备可比较行(实现 Comparable 接口)
如果使用构造(比较器)
则 Set 集合中的元素按照比较器比较顺序排序
TreeSet常用的方法
方法 | 描述 | 返回类型 |
---|---|---|
add(E e) | 向集合中添加指定元素 | boolean |
remove(Object o) | 从集合中移除指定元素 | boolean |
contains(Object o) | 检查集合是否包含指定元素 | boolean |
isEmpty() | 检查集合是否为空 | boolean |
size() | 返回集合中元素的数量 | int |
clear() | 清空集合中的所有元素 | void |
iterator() | 返回一个迭代器,用于遍历集合中的元素 | Iterator |
first() | 返回集合中的第一个(最小)元素 | E |
last() | 返回集合中的最后一个(最大)元素 | E |
lower(E e) | 返回集合中严格小于指定元素的最大元素 | E |
floor(E e) | 返回集合中小于或等于指定元素的最大元素 | E |
higher(E e) | 返回集合中严格大于指定元素的最小元素 | E |
ceiling(E e) | 返回集合中大于或等于指定元素的最小元素 | E |
headSet(E toElement) | 返回集合中小于指定元素的部分视图 | SortedSet |
tailSet(E fromElement) | 返回集合中大于等于指定元素的部分视图 | SortedSet |
subSet(E fromElement, E toElement) | 返回集合中在指定范围内的部分视图 | SortedSet |
请注意,TreeSet
是SortedSet
接口的实现类,因此它具有一些额外的方法,如 first()
、last()
、lower()
、floor()
、higher()
、ceiling()
和subSet()
。这些方法可用于根据元素的自然排序或提供的比较器来执行特定的操作和查询。
示例
import java.util.TreeSet;
public class TreeSetExample {
public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet<>();
// 添加元素到集合中
treeSet.add(5);
treeSet.add(10);
treeSet.add(2);
treeSet.add(8);
treeSet.add(3);
System.out.println("TreeSet: " + treeSet); // [2, 3, 5, 8, 10]
// 获取最小元素
int firstElement = treeSet.first();
System.out.println("First Element: " + firstElement); // 2
// 获取最大元素
int lastElement = treeSet.last();
System.out.println("Last Element: " + lastElement); // 10
// 获取严格小于指定元素的最大元素
int lowerValue = treeSet.lower(6);
System.out.println("Lower Value: " + lowerValue); // 5
// 获取小于或等于指定元素的最大元素
int floorValue = treeSet.floor(5);
System.out.println("Floor Value: " + floorValue); // 5
// 获取严格大于指定元素的最小元素
int higherValue = treeSet.higher(4);
System.out.println("Higher Value: " + higherValue); // 5
// 获取大于或等于指定元素的最小元素
int ceilingValue = treeSet.ceiling(5);
System.out.println("Ceiling Value: " + ceilingValue); // 5
// 获取在指定范围内的部分视图
TreeSet<Integer> subSet = (TreeSet<Integer>) treeSet.subSet(3, 8);
System.out.println("SubSet: " + subSet); // [3, 5]
}
}
有序集合(也称为序列 )。 该集合用户可以精确控制列表中每个元素的插入位置。 用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。
List
通常允许重复的元素、允许null
元素
方法名 | 返回值类型 | 描述 |
---|---|---|
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 比较器进行自然排序 (JDK 8) |
static copyOf(Collection coll) | List | 按照迭代顺序返回一个不可修改的 List (JDK 10) |
static of() | List | 返回包含任意数量元素的不可修改列表 (JDK 9) |
示例
import java.util.List;
import java.util.Scanner;
public class ListExample01 {
public static void main(String[] args) {
// List不可修改
List commodity = List.of("棉花糖", "气球", "风筝", "饼干", "巧克力");
Scanner input = new Scanner(System.in);
System.out.println("请输入你要查询的商品信息");
String str = input.next();
if (commodity.contains(str)) {
String information = (String) commodity.get(commodity.indexOf(str));
System.out.println(information);
} else {
System.out.println("暂时没有这个商品");
}
}
}
主要子类: ArrayList
、 LinkedList
、 Vector
、Stack
等。
Vector
类是一种动态数组,它可以自动扩展和缩小数组的大小,实现了 List
接口,且所有的方法都是同步的(线程安全的),适用于多线程环境中的操作。
Vector
类的特点:
动态数组
:Vector的大小可以根据需要自动增长或减小。当添加元素超过当前容量时,Vector会自动重新分配内部数组的大小以容纳更多的元素。默认大小为10
,扩容为*2
。线程安全
:Vector是线程安全的,意味着多个线程可以同时对Vector进行读取和写入操作,而不会导致数据不一致的问题。Vector中的方法都使用了同步关键字来确保线程安全性。支持随机访问
:Vector类支持通过索引值来访问集合在的元素,具有常数时间度的随机访问特性。可以包含重复元素
可以插入 null
import java.util.Comparator;
import java.util.Iterator;
import java.util.Vector;
public class VectorExample02 {
public static void main(String[] args) {
Vector<Student> students = new Vector<Student>();
students.add(new Student("犯困桃子", 10, 91));
students.add(new Student("小羊呆呆", 20, 72));
students.add(new Student("中科盛康人才", 5, 35));
students.add(new Student("小羊", 30, 50));
students.add(new Student("盛康人才", 1, 11));
students.add(new Student("张三", 23, 90));
students.add(new Student("李四", 24, 80));
students.add(new Student("王五", 43, 70));
students.add(new Student("赵六", 24, 80));
students.add(new Student("田七", 25, 50));
students.sort(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return (sum(o1) - sum(o2)) * -1 ;
}
});
// Iterator iterator = students.iterator();
// while (iterator.hasNext()) {
// Student student = iterator.next();
// System.out.println(student + "\t" + avg(student));
// }
for (Student student : students) {
System.out.println("" + student + "\t 平均成绩:" + avg(student));
}
}
// 计算总成绩
public static int sum(Student student) {
return student.getTotal();
}
// 计算平均分
public static double avg(Student student) {
return (student.getTotal() / 2.0);
}
}
Stack
类代表后进先出(LIFO)
堆栈的对象, Stack
继承自 Vector
所以它有所有 Vector
中的方法。
public class Stack<E> extends Vector<E>
Stack 常用方法:
方法名 | 返回值类型 | 描述 |
---|---|---|
empty() | boolean | 判断此堆栈是否为空 |
peek() | E | 返回此堆栈顶部的对象,而不从堆栈中删除它 |
pop() | E | 返回并删除此堆栈顶部的对象 |
push(E item) | E | 将指定对象添加到堆栈的顶部 |
search(Object o) | int | 返回对象在此堆栈上的从1开始的位置,如果对象不在堆栈中,则返回 -1 |
示例
import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
// 向Stack添加元素
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
// Stack 弹出元素
System.out.println(stack.pop()); // 4
// Stack 查看但不弹出
System.out.println(stack.peek()); // 3
// 判断是否为空
System.out.println(stack.isEmpty()); // false
// 查找元素所在位置
System.out.println(3); // 3
System.out.println(stack); // [1, 2, 3]
}
}
ArrayList
是 Java 编程语言中的一个类,位于 java.util
包中。它是一个动态数组,可以根据需要自动调整大小。ArrayList
通过插入和删除元素来维护内部数组的大小,并提供了许多有用的方法来操作列表数据。可以存 null
。
以下是ArrayList的一些主要特点和常用方法:
动态大小
:ArrayList可以根据需要动态增加或减少其大小,无需手动管理数组的大小。
允许重复元素
:ArrayList可以包含重复的元素。
随机访问
:可以使用索引访问ArrayList中的元素,通过get(index)方法获取指定位置的元素。
增删操作
:可以使用add(element)方法在列表末尾添加元素,使用remove(index)方法删除指定位置的元素。
数组转换
:可以使用toArray()方法将ArrayList转换为数组,或者使用Arrays.asList(array)方法将数组转换为ArrayList。
示例
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ArrayListExample {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("小羊呆呆");
list.add("犯困桃子");
list.add("中科盛康人才");
list.add("桃子");
list.add("张三");
list.add("盛康人才");
/**
* 错误删除元素,删除除倒数第二个元素外都会报错'ConcurrentModificationException(并发修改异常)'
*/
//for (String str : list) {
// if ("张三".equals(str)) {
// list.remove(str);
// }
//}
System.out.println(list); // [小羊呆呆, 犯困桃子, 中科盛康人才, 桃子, 盛康人才]
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String s = iterator.next();
if ("桃子".equals(s)) {
// 利用iterator方法删除元素,如果使用list.remove会报错
iterator.remove();
continue;
}
System.out.println(s);
}
// 判断是否包含某个元素
System.out.println(list.contains("小羊呆呆")); // true
// 寻找对应元素下标
System.out.println(list.indexOf("犯困桃子")); // 1
// 输出所有元素
System.out.println(list); // [小羊呆呆, 犯困桃子, 中科盛康人才, 盛康人才]
// subList()返回的是原始列表的一个视图(view),而不是一个新的独立列表。
// 这意味着对返回的子列表进行的任何修改都会反映在原始列表中,并且对原始列表的修改也会影响到子列表。
List<String> strings = list.subList(1, 3);
System.out.println(strings); // [犯困桃子, 中科盛康人才]
strings.set(0, "桃子姐姐");
System.out.println(list); // [小羊呆呆, 桃子姐姐, 中科盛康人才, 盛康人才]
System.out.println(strings.contains("小羊呆呆")); // false
strings.clear();
System.out.println(list.size()); // 2
}
}
ArrayList
是非线程安全的,默认容量为10
,默认每次扩容为1.5
倍。
构造方法
ArrayList类提供了多种构造方法来创建ArrayList对象。以下是一些常用的构造方法:
ArrayList()
:创建一个空的ArrayList对象,默认初始容量为10。ArrayList<String> list = new ArrayList<>();
ArrayList(int initialCapacity)
:创建一个具有指定初始容量的ArrayList对象。ArrayList<String> list = new ArrayList<>(20);
ArrayList(Collection extends E> c)
:创建一个包含指定集合中的元素的ArrayList对象。List<String> collection = Arrays.asList("Apple", "Banana", "Orange");
ArrayList<String> list = new ArrayList<>(collection);
ArrayList(ArrayList extends E> c)
:创建一个包含指定ArrayList中的元素的ArrayList对象。ArrayList<String> originalList = new ArrayList<>();
originalList.add("Apple");
originalList.add("Banana");
originalList.add("Orange");
ArrayList<String> newList = new ArrayList<>(originalList);
这些构造方法允许你根据不同的需求来创建ArrayList对象。你可以选择根据默认大小创建一个空列表,指定初始容量,或者使用现有的集合来初始化列表。
需要注意的是,尖括号中的类型参数E表示ArrayList中元素的类型。在实际使用时,根据需要替换为实际的类型。
LinkedList
类是 Java 集合框架中的一个双向链表实现
,它实现了 List
接口。与 ArrayList
相比,LinkedList
在插入和删除元素时具有更好的性能,但在访问和搜索元素时较差。
LinkedList
支持实现所有 List
接口可选列表的操作,并允许元素值是任何数据,包括 null
。
构造方法
LinkedList类提供了以下几个构造方法:
LinkedList()
:创建一个空的LinkedList对象。// 创建一个空的LinkedList对象
LinkedList<String> emptyList = new LinkedList<>();
System.out.println("Empty List: " + emptyList); // 输出:Empty List: []
LinkedList(Collection extends E> c)
:创建一个包含指定集合中的元素的LinkedList对象,元素按照集合的迭代器返回顺序添加到列表的末尾。// 创建一个包含指定集合中的元素的LinkedList对象
LinkedList<Integer> numbers = new LinkedList<>(List.of(1, 2, 3, 4, 5));
System.out.println("Numbers: " + numbers); // 输出:Numbers: [1, 2, 3, 4, 5]
示例
import java.util.Arrays;
import java.util.LinkedList;
public class LinkedListExample {
public static void main(String[] args) {
// 创建一个空的LinkedList对象
LinkedList<String> linkedList = new LinkedList<>();
// 添加元素
linkedList.add("apple");
linkedList.addFirst("banana");
linkedList.addLast("orange");
System.out.println("LinkedList: " + linkedList); // 输出:LinkedList: [banana, apple, orange]
// 转换成数组
Object[] array = linkedList.toArray();
System.out.println("Array: " + Arrays.toString(array)); // 输出:Array: [banana, apple, orange]
// 获取元素
String firstElement = linkedList.getFirst();
String lastElement = linkedList.getLast();
String secondElement = linkedList.get(1);
System.out.println("First element: " + firstElement); // 输出:First element: banana
System.out.println("Last element: " + lastElement); // 输出:Last element: orange
System.out.println("Second element: " + secondElement); // 输出:Second element: apple
// 判断是否包含元素
boolean containsApple = linkedList.contains("apple");
boolean containsGrape = linkedList.contains("grape");
System.out.println("Contains apple: " + containsApple); // 输出:Contains apple: true
System.out.println("Contains grape: " + containsGrape); // 输出:Contains grape: false
// 删除元素
linkedList.removeFirst();
linkedList.removeLast();
linkedList.remove("apple");
System.out.println("LinkedList after removal: " + linkedList); // 输出:LinkedList after removal: []
// 判断是否为空
boolean isEmpty = linkedList.isEmpty();
System.out.println("Is empty: " + isEmpty); // 输出:Is empty: true
// 获取列表的大小
int size = linkedList.size();
System.out.println("Size of LinkedList: " + size); // 输出:Size of LinkedList: 0
}
}