(五)集合与集合框架
4、List接口:
(1)概述:
继承了 Collection 接口,是常用的一种集合类型。
属于java.util包,使用需要导包
(2)特点:
- List是一种有序集合
例如,向集合中存储的元素顺序是8、2、5。那么集合中就是按照这个顺序进行存储的
- List一种带索引的集合
可以通过元素的下标索引,精确查找对应的元素数据
- List集合可以存放重复元素
可以把相同的数据,在List集合中多次保存
(3)主要的实现类:
ArrayList<E>、LinkedList<E>、Vector<E>
(4)常用方法:
所继承的Collection中的方法就不多介绍了,主要是它特有的方法
1.
get(int index)
用法:获取列表中指定索引位置的元素(索引从 0 开始)。
参数:
index
为元素索引,需满足0 ≤ index < size()
,否则抛出IndexOutOfBoundsException
。返回值:索引对应的元素(类型为 List 的泛型
E
)。调用者:List 实现类的实例(如 ArrayList、LinkedList)。
示例:
List<String> list = Arrays.asList("A", "B", "C"); String elem = list.get(1); // 返回 "B"
2.
set(int index, E element)
用法:替换指定索引位置的元素,并返回被替换的旧元素。
参数:
index
:目标索引(0 ≤ index < size()
)。
element
:新元素。返回值:被替换的旧元素(类型为
E
)。调用者:List 实现类的实例。
示例:
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3)); Integer old = list.set(2, 9); // 替换索引2的元素为9,返回旧元素3 System.out.println(list); // [1, 2, 9]
3.
add
方法(含重载)List 提供两种
add
方法,支持在指定位置或末尾添加元素:(1)
add(E e)
用法:在列表末尾添加元素(允许重复,保持插入顺序)。
返回值:
boolean
,始终为true
(List 允许添加元素)。示例:
List<String> list = new ArrayList<>(); list.add("Java"); // 列表变为 ["Java"]
(2)
add(int index, E element)
用法:在指定索引位置插入元素,原索引及后续元素后移(
index
范围:0 ≤ index ≤ size()
)。返回值:
void
。示例:
List<String> list = new ArrayList<>(Arrays.asList("a", "b")); list.add(1, "c"); // 插入后列表:["a", "c", "b"]
4.
addAll
方法(含重载)支持批量添加元素,可指定插入位置:
(1)
addAll(Collection<? extends E> c)
用法:将集合
c
的所有元素添加到列表末尾。返回值:
boolean
,true
表示列表因添加而改变。示例:
List<Integer> list1 = new ArrayList<>(Arrays.asList(1, 2)); List<Integer> list2 = Arrays.asList(3, 4); list1.addAll(list2); // list1变为 [1, 2, 3, 4]
(2)
addAll(int index, Collection<? extends E> c)
用法:将集合
c
的所有元素插入到列表的指定索引位置,原元素后移。返回值:
boolean
,true
表示列表有变化。示例:
List<String> list1 = new ArrayList<>(Arrays.asList("x", "y")); List<String> list2 = Arrays.asList("a", "b"); list1.addAll(1, list2); // list1变为 ["x", "a", "b", "y"]
5.
remove
方法(含重载)支持移除指定元素或指定索引的元素:
(1)
remove(Object o)
用法:移除列表中第一个与
o
相等的元素(通过equals()
判断)。返回值:
boolean
,true
表示成功移除。示例:
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "a")); list.remove("a"); // 移除第一个"a",列表变为 ["b", "a"]
(2)
remove(int index)
用法:移除指定索引位置的元素,后续元素前移。
参数:
index
需满足0 ≤ index < size()
。返回值:被移除的元素(类型为
E
)。示例:
List<Integer> list = new ArrayList<>(Arrays.asList(10, 20, 30)); Integer removed = list.remove(1); // 移除20,列表变为 [10, 30]
6.
indexOf(Object o)
用法:返回列表中第一个与
o
相等的元素的索引(无则返回-1
)。判断依据:通过
equals()
方法,null
元素用==
判断。返回值:
int
,元素索引或-1
。调用者:List 实现类的实例。
示例:
List<String> list = Arrays.asList("a", "b", "a"); int idx = list.indexOf("a"); // 返回 0(第一个"a"的位置)
7.
lastIndexOf(Object o)
用法:返回列表中最后一个与
o
相等的元素的索引(无则返回-1
)。返回值:
int
,元素索引或-1
。示例:
List<String> list = Arrays.asList("a", "b", "a"); int idx = list.lastIndexOf("a"); // 返回 2(最后一个"a"的位置)
8.
subList(int fromIndex, int toIndex)
用法:返回列表中从
fromIndex
(包含)到toIndex
(不包含)的子列表视图(非新集合,而是原列表的一部分引用)。参数:
fromIndex
:起始索引(0 ≤ fromIndex ≤ toIndex
)。
toIndex
:结束索引(toIndex ≤ size()
)。若参数越界,抛出
IndexOutOfBoundsException
;若fromIndex > toIndex
,抛出IllegalArgumentException
。返回值:
List<E>
,子列表视图。注意:对子列表的修改会直接影响原列表,反之亦然。
示例:
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); List<Integer> sub = list.subList(1, 4); // 子列表为 [2, 3, 4] sub.set(0, 9); // 子列表变为 [9, 3, 4],原列表变为 [1, 9, 3, 4, 5]
9.
retainAll(Collection<?> c)
用法:保留列表中与集合
c
共有的元素(即仅保留交集),移除其他元素。返回值:
boolean
,true
表示列表因调用而改变(至少移除了一个元素)。调用者:List 实现类的实例(继承自 Collection 接口)。
示例:
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4)); Collection<Integer> c = Arrays.asList(2, 4, 6); boolean changed = list.retainAll(c); // 列表变为 [2, 4],changed = true
案例展示:
public static void main(String[] args) {
//1.创建List集合对象
List<String> list = new ArrayList<>();
//2.添加元素,默认尾部添加
list.add("hello1");
list.add("hello2");
list.add("hello3");
list.add("hello1");
System.out.println(list);
//3.指定位置添加元素
// add(int index,String s)
list.add(1, "world");
System.out.println(list);
//3.删除索引位置为2的元素
//boolean f = list.remove(2);
//System.out.println("remove(2): " + f);
//System.out.println("after remove: " + list);
//4.修改指定位置元素
list.set(0, "briup");
System.out.println(list);
//5.借助get方法遍历集合
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("-----------------");
//6.使用foreach遍历
for(Object obj : list){
System.out.println(obj);
}
System.out.println("-----------------");
//7.使用迭代器遍历
Iterator<String> it = list.iterator();
while(it.hasNext()){
String str = it.next();
System.out.println(str);
}
}
5、ArrayList类:
(1)概述:
是接口List的实现类,最常用的List集合类型
(2)特点:
ArrayList 类底层使用数组来实现数据的存储,所以它的特点是:增删慢,查找快。
(3)业务场景:
适用于查找多,增删少的系统,如学生管理,一年增删一次
(4)方法:
主要是重写的实现的List接口与Collection接口中的方法
6、LinkedList类:
(1)概述:
接口List的常用实现类
(2)特点:
底层采用双向链表来存储,具有增删快,查找慢的特点
(3)业务场景:
需要大量增删操作的系统
(4)方法:
将指定元素插入此列表的开头:void addFirst(E e)
将指定元素添加到此列表的结尾 :void addLast(E e)
返回此列表的第一个元素 :E getFirst()
返回此列表的最后一个元素:E getLast()
移除并返回此列表的第一个元素 :E removeFirst()
移除并返回此列表的最后一个元素 :E removeLast()
从此列表所表示的堆栈处弹出一个元素 :E pop()
将元素推入此列表所表示的堆栈 :void push(E e)
案例:
public class Test054_Node {
public static void main(String[] args) {
//1.实例化集合对象
//注意,要测试LinkedList中的方法,必须用LinkedList引用指向LinkedList对象
LinkedList<String> list = new LinkedList<>();
String s1 = "hello";
String s2 = "world";
String s3 = "nihao";
//2.往集合中添加元素并输出
list.add(s1);
list.add(s2);
list.add(s3);
System.out.println("list: " + list);
System.out.println("------------");
//3.往头、尾节点添加元素
list.addFirst("first");
list.addLast("last");
System.out.println("list: " + list);
System.out.println("------------");
//4.获取头尾节点元素
System.out.println("getFirst: " + list.getFirst());
System.out.println("getLast: " + list.getLast());
System.out.println("------------");
//5.删除头尾节点元素
list.removeFirst();
list.removeLast();
System.out.println("list: " + list);
}
}
//程序运行效果:
list: [hello, world, nihao]
------------
list: [first, hello, world, nihao, last]
------------
getFirst: first
getLast: last
------------
list: [hello, world, nihao]
7、Vector类:
(1)概述:
是List接口的实现类
(2)特点:
底层采用动态数组,线程安全
8、数据结构的相关内容:简单介绍,有兴趣的下来自己多练习算法题
(1)概述:
数据结构是计算机科学中研究数据组织、存储和操作的一门学科。它涉及了如何组织和存储数据以及如何设计和实现不同的数据操作算法和技术。
常见的据结构有线性数据结构(含数组、链表、栈和队列等),非线性数据结构(树、图等)。
注意:不同的数据结构适用于不同的场景和问题,选择合适的数据结构可以提高算法的效率和性能。
(2)常见的数据结构:
1. 数组(Array)
原理:在内存中连续存储的相同类型元素的集合,通过索引(下标)快速访问。
特点:
随机访问:通过索引
O(1)
时间复杂度访问元素。固定大小:初始化后长度固定(动态数组如 Java 的
ArrayList
可自动扩容,但本质是重新分配更大空间并复制元素)。插入 / 删除效率低:中间位置插入 / 删除需移动后续元素,时间复杂度
O(n)
。内存连续:缓存友好,但可能产生内存碎片。
应用:存储同类型数据、实现其他数据结构(如栈、队列)。
2. 链表(Linked List)
原理:由节点组成的线性结构,每个节点包含数据和指向下一节点(或上一节点)的引用(指针),内存不要求内存连续。
分类:
单链表:节点仅指向后继节点。
双向链表:节点同时指向前驱和后继指针。
特点:
动态大小:无需预先指定长度,可灵活增删节点。
插入 / 删除高效:已知前驱节点时,操作时间复杂度
O(1)
(无需移动元素)。访问效率低:需从表头遍历,时间复杂度
O(n)
。内存不连续:每个节点需额外存储指针,内存开销略大。
3. 栈(Stack)
原理:遵循 “后进先出”(LIFO,Last In First Out)的线性结构,仅允许在一端(栈顶)操作。
特点:
查找慢增删快4. 队列(Queue)
原理:遵循 “先进先出”(FIFO,First In First Out)的线性结构,允许在一端(队尾)插入,另一端(队头)删除。
特点:
顺序访问,操作受限。
数组实现的循环队列和链表实现的队列,基本操作时间复杂度均为
O(1)
。5. 树(Tree)
原理:由节点组成的非线性结构,包含一个根节点,其余节点分属不同子树,节点间存在层次关系(父节点与子节点)。
核心概念:
根节点:无父节点的顶层节点。
叶子节点:无子节点的节点。
深度:节点到根的路径长度;高度:节点到最深叶子的路径长度。
常见类型:
二叉树:每个节点最多有 2 个子节点(左、右子树)。
平衡二叉树(如 AVL 树、红黑树):通过自平衡机制避免 BST 退化为链表,保证操作效率稳定。
特点:
非线性结构,适合表示层级关系(如文件系统、组织架构)。
查找、插入、删除效率取决于树的平衡性(平衡树效率接近
O(log n)
)。6. 集合(Set)
原理:存储不重复元素的容器,无固定顺序(部分实现有序),基于哈希表或树实现。
常见实现:
哈希集合(HashSet):基于哈希表,元素无序,查找、插入、删除平均
O(1)
。树集合(如 TreeSet):基于红黑树,元素有序(自然排序或自定义排序),操作时间复杂度
O(log n)
。链表集合(如 LinkedHashSet):基于哈希表 + 链表,保留插入顺序,兼具哈希表的效率。
特点:
元素唯一(通过
equals()
和hashCode()
判断,或比较器)。无索引,不能通过位置访问元素。
应用:去重、判断元素是否存在(如黑名单校验)。
7. 映射(Map)
原理:存储键值对(Key-Value)的容器,键唯一,值可重复,通过键快速查找值。
常见实现:
哈希映射(HashMap):基于哈希表,键无序,操作平均
O(1)
。树映射(TreeMap):基于红黑树,键有序,操作
O(log n)
。链表映射(LinkedHashMap):保留键的插入顺序或访问顺序。
特点:
键唯一(重复插入会覆盖旧值),值可多个。
本质是 “键到值的映射”,可视为 Set 的扩展(Set 可看作键无值的 Map)。
应用:存储关联数据(如用户 ID 与信息、配置参数)、缓存实现。
8. 哈希表(Hash Table)
原理:通过哈希函数将键(Key)映射到数组的索引,实现快速访问。若多个键映射到同一索引(哈希冲突),常用解决方法:
链地址法:冲突的键值对以链表 / 红黑树形式存储在同一索引位置(如 Java HashMap)。
开放地址法:冲突时通过线性探测、二次探测等方式寻找下一个空闲位置。
特点:
理想情况下,查找、插入、删除时间复杂度
O(1)
。性能依赖哈希函数(需均匀分布)和冲突解决策略。
无序存储(除非结合链表维护顺序)。
应用:实现 HashSet、HashMap、数据库索引、缓存系统。