集合:List
概述
有序的 [collection](也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
Collection将集合划分为两大类:
- List集合
- Set集合
List接口的特点
-
有序【存储有序】
-
可重复
-
可以存储 null值
-
部分子集合线程安全,部分不安全 例如 ArrayList 和 Vector
-
有索引,针对每个元素能够方便地查询和修改
-
判断元素是否重复依赖于equals方法
-
a. 如果元素是系统类,不需要重写equals方法
-
b. 如果是自定义类,就需要我们按需求重写 equals方法
ArrayList(掌握)
概述
List
接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括null
在内的所有元素。除了实现
List
接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于Vector
类,除了此类是不同步的。)
特点
- 底层数据结构是数组
- 增加和删除的效率低,查询和修改的效率高
- 能够存储 null 值
- 线程不安全,效率高 可以通过 Collections.synchronizedList();变安全
- 有索引,能够方便检索
- 元素可重复,我们自己可以通过 选择排序去重复
- 不可以排序,但是可以通过 Collections.sort();方法排序
底层设计
ArrayList底层是一个数组,通过一段连续的存储空间存储数据,各元素按照插入的顺序进行存储,允许出现重复的元素。依次向ArrayList中添加1~10,则底层就是存储在如下图类似的数组中
ArrayList使用了泛型的设计思想,他可以存储任何类型的数据,包括自定义类型、基本数据类型对应的包装类等。
对于Java中的集合,都提供了泛型的设计思想,泛型还可以约束集合中的存储数据的类型,如果不指定一个数据类型,则集合中可以存储任意类型的数据,这样就不能保证集合中元素的类型一致性,可能会发生大量的异常,比如:字符串类型和数据类型比较大小、字符串类型进行运算等。
默认容量大小是10,默认容量不足是扩容至原来的1.5倍
常用方法
添加元素
方法签名 | 方法说明 |
---|---|
boolean add(E e) | 在集合尾部添加元素e,返回值为是否添加成功 |
void add(int index, E element) | 在index位置插入元素element |
boolean addAll(Collection<? extends E> c) | 将c中的元素尾插到集合中 |
boolean addAll(int index, Collection<? extends E> c) | 从index位置插入c中的元素 |
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(2);//尾插2
System.out.println(list.toString());// [2]
list.add(0,1);//0下标插入1
System.out.println(list.toString());// [1, 2]
//Collection接口的子类
List<Integer> list2 = new LinkedList<>();
list2.add(3);
list2.add(4);
list.addAll(list2);//将list2集合中的元素尾插到list中
System.out.println(list.toString());// [1, 2, 3, 4]
list.addAll(1,list2);//将list2集合中的元素从1下标插入list中
System.out.println(list.toString());// [1, 3, 4, 2, 3, 4]
}
删除元素
方法签名 | 方法说明 |
---|---|
E remove(int index) | 删除index位置的元素并返回该元素 |
boolean remove(Object o) | 删除出现的第一个o元素,参数必须为Object或其子类,返回是否删除成功void clear()清空元素 |
void clear() | 清空元素 |
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(2);
list.add(1);
//删除下标为0的元素,并返回该元素
int n = list.remove(0);
System.out.println(n);// 1
System.out.println(list.toString());// [2, 3, 2, 1]
//删除第一个2
//通过显示装箱,将2数字包装成对应的包装类
boolean result = list.remove(new Integer(2));
System.out.println(result);// true
System.out.println(list.toString());// [3, 2, 1]
//清空元素
list.clear();
System.out.println(list.toString());// []
}
其他方法
方法签名 | 方法说明 |
---|---|
E get(int index) | 获取indext下标的元素并返回 |
E set(int index, E element) | 将index下标的元素修改为element并返回修改前元素的值 |
boolean contains(Object o) | 集合中是否存在o元素 |
int lastIndexOf(Object o) | 返回最后一个o元素的位置 |
List< E > subList(int fromIndex, int toIndex) | List< E > subList(int fromIndex, int toIndex) |
public static void main(String[] args) {
ArrayList<Integer> = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(1);
list.add(2);
//获取1下标的元素
System.out.println(list.get(1));//2
//设置0下标的元素为2
System.out.println(list.set(0, 2));//1
//判断集合中是否存在元素5
System.out.println(list.contains(5));//false
//返回第一个2出现的位置
System.out.println(list.indexOf(2));//0
//返回最后一次出现2的位置
System.out.println(list.lastIndexOf(2));//4
//截取0~3位置的元素
List<Integer> sub = list.subList(0,3);
System.out.println(sub.toString());// [2, 2, 3]
System.out.println(list.toString());// [2, 2, 3, 1, 2]
}
LinkedList(掌握)
概念:
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
链表的分类
链表可分为单向链表和双向链表
一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。
一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接
ArrayList 与 LinkedList
LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低。
ArrayList用于
-
频繁访问列表中的某一个元素。
-
只需要在列表末尾进行添加和删除元素操作
LinkedList常用于
- 你需要通过循环迭代来访问列表中的某些元素。
- 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
结构
LinkedList(链表)是Java集合框架提供的一个实现了List接口的类。它是基于双向链表结构实现的,可以用于存储和操作元素的有序集合。
继承体系结构如下:
构造方法
LinkedList类提供了以下几种构造方法:
1.LinkedList():创建一个空的LinkedList对象。
LinkedList<String> list = new LinkedList<>();
2.LinkedList(Collection<? extends E> c):创建一个包含指定集合中的元素的LinkedList对象。集合中的元素将按照迭代器返回的顺序添加到LinkedList中。
List<String> collection = new ArrayList<>();
collection.add("Element 1");
collection.add("Element 2");
LinkedList<String> list = new LinkedList<>(collection);
3.LinkedList(LinkedList<? extends E> c):创建一个包含指定LinkedList中的元素的LinkedList对象。指定LinkedList中的元素将按照迭代器返回的顺序添加到新的LinkedList中。
LinkedList<String> originalList = new LinkedList<>();
originalList.add("Element 1");
originalList.add("Element 2");
LinkedList<String> newList = new LinkedList<>(originalList);
常见操作
LinkedList类提供了许多用于操作链表的方法。以下是一些常见的操作方法:
添加元素:
- add(E element):在链表末尾添加一个元素。
- addFirst(E element):在链表开头添加一个元素。
- addLast(E element):在链表末尾添加一个元素。
LinkedList<String> list = new LinkedList<>();
list.add("Element 1");
list.addFirst("Element 0");
list.addLast("Element 2");
获取元素:
get(int index)
:获取指定位置的元素。getFirst()
:获取链表的第一个元素。getLast()
:获取链表的最后一个元素。
LinkedList<String> list = new LinkedList<>();
list.add("Element 1");
list.add("Element 2");
String element = list.get(0);
String firstElement = list.getFirst();
String lastElement = list.getLast();
删除元素:
remove(int index)
:删除指定位置的元素。removeFirst()
:删除链表的第一个元素。removeLast()
:删除链表的最后一个元素
LinkedList<String> list = new LinkedList<>();
list.add("Element 1");
list.add("Element 2");
list.remove(0);
list.removeFirst();
list.removeLast();
判断元素是否存在:
contains(Object element)
:检查链表是否包含指定元素。
LinkedList<String> list = new LinkedList<>();
list.add("Element 1");
list.add("Element 2");
boolean containsElement = list.contains("Element 1");
获取链表大小和清空链表:
size()
:获取链表中元素的个数。isEmpty()
:检查链表是否为空。clear()
:清空链表中的所有元素。
LinkedList<String> list = new LinkedList<>();
list.add("Element 1");
list.add("Element 2");
int size = list.size();
boolean isEmpty = list.isEmpty();
list.clear();
Vector(过时)
概述
java.util.Vector 也实现了 List 接口,其描述的也是可变长度的对象数组。
Vector 类以类似数组的方式顺序地存储数据,但是具有比数组更强大的功能;它是允许不同类型元素共存的变长数组。
特点
1 , Vector 类允许不同类型元素共存;
2 , Vector 对象中元素的个数是可变的,它就像一个动态数组。
Vector 类适合于下列情况使用:
1, 序列中的元素都是对象
2, 需要处理的对象数目不定
3, 需要将不同的类的对象组合成一个数据序列
4, 需要频繁的对序列中的元素进行插入和删除
5, 需要经常定位序列中的对象或进行查找工作
6, 在不同类之间传递大量的数据
Stack(过时)
-
Stack是先进后出(LIFO)的对象堆栈,实际上继承自Vector。
-
他是Vector的增强类,堆栈顶部都对应向量尾部。
-
在首次创建栈的时候,不包含项。
-
特点是只能在栈顶进行插入和删除操作,即先进后出。
-
不建议直接使用Stack类:在Java中,Stack类是通过继承自Vector类来实现的,而Vector类是一个线程安全的动态数组。由于Stack类继承了Vector类的所有方法,包括一些不安全的方法,因此在实际使用中,建议使用更为常见的LinkedList类来实现栈,或者使用Deque接口的实现类,如ArrayDeque。
-
在使用栈时,需要注意空栈检查,避免栈溢出,不支持随机访问,以及选择合适的实现方式等。
-
栈有一个固定的容量,当栈中的元素数量超过容量时,会导致栈溢出(StackOverflowError)。因此,在使用栈时,应该注意控制入栈的数量,避免溢出。
-
不支持随机访问:栈是一种顺序访问的数据结构,只能从栈顶进行入栈和出栈操作。它不支持随机访问,即不能直接访问栈中的任意位置的元素。
-
适用场景:栈适用于需要先进后出的场景,比如函数调用、表达式求值、括号匹配等。在这些场景下,栈可以提供便捷的操作和管理。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)