================================================================================
[](()2.1 介绍
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。其继承了 AbstractList,并实现了 List 接口。LinkedList 不仅实现了 List 接口,还实现了 Queue 和 Deque 接口,可以作为队列去使用。
ArrayList 类位于 java.util 包中,使用前需要引入它。
[](()2.2 ArrayList 的构造方法
| 方法 | 描述 |
| — | — |
| ArrayList() | 无参构造 |
| ArrayList(Collection extends E> c) | 利用其他 Collection 构建 ArrayList |
| ArrayList(int initialCapacity) | 指定顺序表初始容量 |
示例一:
ArrayList list1 = new ArrayList<>();
示例二:
ArrayList list2 = new ArrayList<>(10);
// 该构造方法就是在构建时就将底层数组大小设置为了10
示例三:
List list = new ArrayList<>();
list.add(1);
list.add(2);
ArrayList list3 = new ArrayList<>(list);
Collection extends E> c 只要是具体类型都和 list3 是一样的集合都可以放入转化成 ArrayList
[](()2.3 ArrayList 底层数组的大小
当我们使用 add 方法给 ArrayList 的对象进行尾插时,突然想到了一个问题:既然 ArrayList 的底层是一个数组,那么这个数组有多大呢?
为了解决这个问题,我进行了如下探索
- 跳转到 ArrayList 的定义,我们看到了 elementData 和 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
- 跳转到 elementData 的定义,我们可以了解 ArrayList 底层是数组的原因
- 跳转到 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的定义,初步分析得到这个数组其实是空的
为什么这个数组是空的但存储元素的时候没有报异常呢?我们再去了解下 add 是怎样存储的
- 通过转到 ArrayList 的 add 方法的定义
- 通过定义,不难发现,数组容量和 ensureCapacityInternal 这个东西有关,那我们就看看它的定义
- 我们看里面的 calculateCapacity ,他有两个参数,此时数组为空,那么 minCapacity 就为 1。我们再转到 calculateCapacity 看看它的定义
- 此时我们就好像可以与之前串起来了,当数组为 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 时,就返回 DeFauLt_CAPACITY 和 minCapacity(此时为1) 的最大值。DeFauLt_CAPACITY 其实是默认容量的意思,我们可以转到它的定义看看有多大
- DeFauLt_CAPACITY 的值是10,故 calculateCapacity 函数此时的返回值为10,最后我们再确定一下 ensureExplicitCapacity 是干啥的
- 此时 minCapacity 的值是10,而数组为空时数组长度为0,所以进入 if 语句,执行 grow 方法,我们继续转到 grow 的定义
此时我们就可以了解,当我们创建一个 ArrayList 时,其底层数组大小其实是0。当我们第一次 add 的时候,经过 grow ,数组的大小就被扩容为了10。并且这大小为10的容量放满以后,就会按1.5倍的大小继续扩容。至于这个数组最大能存放多少,大家可以再转到 MAX_ARRAY_SIZE 的定义去查看。
[](()3. LinkedList
=================================================================================
[](()3.1 介绍
LinkedList 类是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
Java 的 LinkedList 底层是一个双向链表,位于 java.util 包中,使用前需要引入它
[](()3.2 LinkedList 的构造方法
| 方法 | 描述 |
| — | — |
| LinkedList() | 无参构造 |
| LinkedList(Collection extends E> c) | 利用其他 Collection 构建 LinkedList |
示例一:
LinkedList list1 = new LinkedList<>();
示例二:
List list = new LinkedList<>();
list.add(1);
list.add(2);
LinkedList list2 = new LinkedList<>(list);
Collection extends E> c 只要是具体类型都和 list2 是一样的集合都可以放入转化成 LinkedList
[](()4. 练习题
==========================================================================
- 习题一
题目描述:
霍格沃茨学院有若干学生(学生对象放在一个 List 中),每个学生有一个姓名(String)、班级(String)和考试成绩(double)。某次考试结束后,每个学生都获得了一个考试成绩。遍历 list 集合,并把每个学生对象的属性都打印出来
本题代码:
class Student{
private String name;
private String classes;
private double score;
// 重写构造方法
public Student(String name, String classes, double score) {
this.name = name;
this.classes = classes;
this.score = score;
}
// 构造 get 和 set 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClasses() {
return classes;
}
public void setClasses(String classes) {
this.classes = classes;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
// 重写 toString 方法
@Override
public String toString() {
return “Student{” +
“name='” + name + ‘’’ +
“, classes='” + classes + ‘’’ +
“, score=” + score +
‘}’;
}
}
public class TestDemo {
public static void main(String[] args) {
ArrayList students = new ArrayList<>();
students.add(new Student(“哈利波特”,“大二班”,95.5));
students.add(new Student(“赫敏格兰杰”,“小三班”,93));
students.add(new Student(“罗恩韦斯莱”,“小二班”,91));
for(Student s: students){
System.out.println(s);
}
}
}
// 结果为:
// Student{name=‘哈利波特’, classes=‘大二班’, score=95.5}
// Student{name=‘赫敏格兰杰’, classes=‘小三班’, score=93.0}
// Student{name=‘罗恩韦斯莱’, classes=‘小二班’, score=91.0}
- 习题二
题目描述:
有一个 List 当中存放的是整形的数据,要求使用 Collections.sort 对 List 进行排序
该题代码:
public class TestDemo {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add(3);
list.add(7);
list.add(1);
list.add(6);
list.add(2);
Collections.sort(list);
System.out.println(list);
}
}
// 结果为:[1, 2, 3, 6, 7]
补充:
Collections 是一个工具类,sort 是其中的静态方法,它是用来对 List 类型进行排序的
注意:
如果具体的类是类似于习题一那样的 Student 类,该类中含有多个属性,那就不能直接使用这个方法。要对 comparator 或者 comparable 接口进行重写,确定比较的是哪个属性才行
- 习题三
题目描述:
输出删除了第一个字符串当中出现的第二个字符串中的字符的字符串,例如
String str1 = “welcome to harrypotter”;
String str2 = “come”;
// 结果为:wl t harrypttr
希望本题可以使用集合来解决
该题代码:
public static void removeS(String str1, String str2){
if(str1null || str2null){
return;
}
List list = new ArrayList<>();
int lenStr1=str1.length();
for(int i=0; i
char c = str1.charAt(i);
if(!str2.contains(c+“”)){
list.add©;
}
}
for(char ch: list){
System.out.print(ch);
}
}
[](()5. 扑克牌小游戏
=============================================================================
我们可以通过上述所学,运用 List 的知识,去写一个关于扑克牌的逻辑代码(如:获取一副牌、洗牌、发牌等等)
class Card{
private String suit; // 花色
private int rank; // 牌面值
public Card(String suit, int rank){
this.suit=suit;
this.rank=rank;
}
@Override
public String toStrin 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 g() {
return "[ “+suit+” “+rank+” ] ";
}
}
public class TestDemo {
public static String[] suits = {“♣”, “♦”, “♥”, “♠”};
// 获取一副牌
public static List getNewCards(){
// 存放 52 张牌
List card = new ArrayList<>();
for(int i=0; i<4; i++){
for(int j=1; j<=13; j++) {
card.add(new Card(suits[i], j));
}
}
return card;
}
public static void swap(List card, int i, int j){
Card tmp = card.get(i);
card.set(i, card.get(j));
card.set(j, tmp);
}
// 洗牌
public static void shuffle(List card){
int size = card.size();
for(int i=size-1; i>0; i–){
Random random = new Random();
int randNum = random.nextInt(i);
swap(card, i, randNum);
}
}
public static void main(String[] args) {
// 得到一副新的牌



