Java 集合框架之List 的使用(附小游戏练习)
作者:吞吞吐吐大魔王 发布时间:2023-11-24 10:33:40
目录
1. List
1.1 List 的常见方法
1.2 代码示例
2. ArrayList
2.1 介绍
2.2 ArrayList 的构造方法
2.3 ArrayList 底层数组的大小
3. LinkedList
3.1 介绍
3.2 LinkedList 的构造方法
4. 练习题
5. 扑克牌小游戏
1. List
1.1 List 的常见方法
1.2 代码示例
注意: 下面的示例都是一份代码分开拿出来的,上下其实是有逻辑关系的
示例一: 用 List 构造一个元素为整形的顺序表
List<Integer> list = new ArrayList<>();
示例二: 尾插 e
list.add(1);
list.add(2);
System.out.println(list);
// 结果为:[1, 2]
示例三: 将 e 插入到 index 位置
list.add(0,10);
System.out.println(list);
// 结果为:[10, 1, 2]
示例四: 尾插 c 中的元素
List<Integer> list1=new LinkedList<>();
list1.add(99);
list1.add(100);
list.addAll(list1);
System.out.println(list);
// 结果为:[10, 1, 2, 99, 100]
只要是继承于 Collection
的集合类的元素都可以 * 入进去,但要注意传过来的具体的类型要么是和 list 的具体类型是一样的,要么是 list
具体类型的子类
示例五: 删除 index 位置的元素
System.out.println(list.remove(0));
System.out.println(list);
// 结果为:10 和 [1, 2, 99, 100]
示例六: 删除遇到的第一个 o
System.out.println(list.remove((Integer) 100));
System.out.println(list);
// 结果为:true 和 [1, 2, 99]
示例七: 获取下标 index 位置的元素
System.out.println(list.get(0));
// 结果为:1
示例八: 将下标 index 位置元素设置为 element
System.out.println(list.set(2,3));
System.out.println(list);
// 结果为:99 和 [1, 2, 3]
示例九: 判断 o 是否在线性表中
System.out.println(list.contains(1));
// 结果为:true
示例十: 返回第一个 o 所在下标
System.out.println(list.indexOf(1));
// 结果为:0
示例十一: 返回最后一个 o 的下标
list.add(1);
System.out.println(list.lastIndexOf(1));
// 结果为:3
示例十二: 截取部分 list
List<Integer> list2=list.subList(1,3);
System.out.println(list2);
// 结果为:[2, 3]
注意:当我们将 list2 通过 set 更改元素,其实对 list 也会有影响
list2.set(0,5);
System.out.println(list2);
System.out.println(list);
// 结果为:[5, 3] 和 [1, 5, 3, 1]
通过 subList
方法进行的截取,得到的集合的数值指向的地址和原集合中数值的地址是一样的
2. ArrayList
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<Integer> list1 = new ArrayList<>();
示例二:
ArrayList<Integer> list2 = new ArrayList<>(10);
// 该构造方法就是在构建时就将底层数组大小设置为了10
示例三:
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
ArrayList<Integer> 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 是怎样存储的
(1)通过转到
ArrayList
的add
方法的定义(2)通过定义,不难发现,数组容量和
ensureCapacityInternal
这个东西有关,那我们就看看它的定义(3)我们看里面的
calculateCapacity
,他有两个参数,此时数组为空,那么minCapacity
就为 1。我们再转到calculateCapacity
看看它的定义(4)此时我们就好像可以与之前串起来了,当数组为
DEFAULTCAPACITY_EMPTY_ELEMENTDATA
时,就返回DeFauLt_CAPACITY
和minCapacity
(此时为1) 的最大值。DeFauLt_CAPACITY
其实是默认容量的意思,我们可以转到它的定义看看有多大
(5)
DeFauLt_CAPACITY
的值是10,故calculateCapacity
函数此时的返回值为10,最后我们再确定一下ensureExplicitCapacity
是干啥的
(6)此时
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<Integer> list1 = new LinkedList<>();
示例二:
List<Integer> list = new LinkedList<>();
list.add(1);
list.add(2);
LinkedList<Integer> 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<Student> 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<Integer> 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(str1==null || str2==null){
return;
}
List<Character> list = new ArrayList<>();
int lenStr1=str1.length();
for(int i=0; i<lenStr1; i++){
char c = str1.charAt(i);
if(!str2.contains(c+"")){
list.add(c);
}
}
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 toString() {
return "[ "+suit+" "+rank+" ] ";
}
}
public class TestDemo {
public static String[] suits = {"♣", "♦", "♥", "♠"};
// 获取一副牌
public static List<Card> getNewCards(){
// 存放 52 张牌
List<Card> 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> 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> 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) {
// 得到一副新的牌
List<Card> cardList = getNewCards();
System.out.println("已获取新的扑克牌");
System.out.println("洗牌:");
shuffle(cardList);
System.out.println(cardList);
System.out.println("抓牌:(3个人,每人轮流抓牌总共抓5张)");
List<Card> hand1 = new ArrayList<>();
List<Card> hand2 = new ArrayList<>();
List<Card> hand3 = new ArrayList<>();
List<List<Card>> hands = new ArrayList<>();
hands.add(hand1);
hands.add(hand2);
hands.add(hand3);
for(int i=0; i<5; i++){
for(int j=0; j<3; j++){
Card card = cardList.remove(0);
hands.get(j).add(card);
}
}
System.out.println("第一个人的牌:"+hand1);
System.out.println("第二个人的牌:"+hand2);
System.out.println("第三个人的牌:"+hand3);
}
}
/**
结果为:
已获取新的扑克牌
洗牌:
[[ ♥ 9 ] , [ ♦ 6 ] , [ ♣ 8 ] , [ ♦ 2 ] , [ ♣ 6 ] , [ ♦ 4 ] , [ ♣ 11 ] , [ ♣ 9 ] , [ ♠ 8 ] , [ ♣ 5 ] , [ ♦ 8 ] , [ ♦ 10 ] , [ ♦ 1 ] , [ ♦ 12 ] , [ ♥ 10 ] , [ ♥ 7 ] , [ ♠ 12 ] , [ ♥ 12 ] , [ ♦ 7 ] , [ ♣ 13 ] , [ ♠ 6 ] , [ ♠ 5 ] , [ ♥ 3 ] , [ ♦ 5 ] , [ ♦ 11 ] , [ ♣ 12 ] , [ ♠ 7 ] , [ ♦ 3 ] , [ ♥ 5 ] , [ ♦ 13 ] , [ ♣ 1 ] , [ ♥ 8 ] , [ ♠ 10 ] , [ ♠ 4 ] , [ ♣ 4 ] , [ ♣ 7 ] , [ ♥ 1 ] , [ ♠ 1 ] , [ ♣ 3 ] , [ ♥ 11 ] , [ ♥ 13 ] , [ ♦ 9 ] , [ ♠ 13 ] , [ ♣ 10 ] , [ ♥ 6 ] , [ ♠ 11 ] , [ ♠ 3 ] , [ ♣ 2 ] , [ ♠ 2 ] , [ ♥ 2 ] , [ ♥ 4 ] , [ ♠ 9 ] ]
抓牌:(3个人,每人轮流抓牌总共抓5张)
第一个人的牌:[[ ♥ 9 ] , [ ♦ 2 ] , [ ♣ 11 ] , [ ♣ 5 ] , [ ♦ 1 ] ]
第二个人的牌:[[ ♦ 6 ] , [ ♣ 6 ] , [ ♣ 9 ] , [ ♦ 8 ] , [ ♦ 12 ] ]
第三个人的牌:[[ ♣ 8 ] , [ ♦ 4 ] , [ ♠ 8 ] , [ ♦ 10 ] , [ ♥ 10 ] ]
*/
上述代码中有一处代码是这样写的 List<List<Card>>
,其实不难理解,这个类型其实就是 List
中存放的每个元素都是一个 List 类型的,并且每一个 List
元素中的元素都是 Card
类型,类似于二维数组。
来源:https://blog.csdn.net/weixin_51367845/article/details/120838319


猜你喜欢
- ViewFlipper实现文字轮播(仿淘宝头条垂直滚动广告),供大家参考,具体内容如下广告条目可以单独写成布局文件,然后在布局文件或者代码中
- 在分布式系统中,我们会需要 ID 生成器的组件,这个组件可以实现帮助我们生成顺序的或者带业务含义的 ID。目前有很多经典的 ID 生成方式,
- 末日这天写篇博客吧,既然没来,那就纪念一下。这次谈谈自制控件,也就是自定义控件,先上图,再说1.扩展OpenFileDialog,在Open
- file: BluetoothEventLoop.java GB/GB2/GB3: 1. import android.os.PowerMa
- 在数字科技日新月异的今天,软件和硬件的完美结合,造就了智能移动设备
- 前天在做批量数据导入新增时,要对数据进行有效性判断,其中还要去除重复,如果没出现linq的话可能会新声明一个临时对象集合,然后遍历原始数据判
- C#自己没有Inputbox这个类,但是Inputbox也蛮好用的,所以有两种方法可以使用一:间接调用vb中的Inputbox功能 
- Android API Demos中有很多非常Nice的例子,这些例子的代码都写的很出色,如果大家把API Demos中的每个例子研究透了,
- 前言前面文章我们介绍了Broker是如何将消息全量存储到CommitLog文件中,并异步生成dispatchRequest任务更新Consu
- 在Monkeyrunner做自动化测试时,可以使用模拟器,当然也可以选择用真机。不过,要想通过电脑来安装软件,操作手机,则必须先安装手机驱动
- 本文实例讲述了Android开发之SeekBar基本使用及各种美观样式。分享给大家供大家参考,具体如下:改变控件透明度只需通过 .setAl
- 前言碎语今天博主分享一个Kubernetes集全管理软件,也就是Kubernetes web ui。是360团队开源的一款产品,Wayne
- 前言去年在公司参与了一个某某机场建设智能机场的一个项目,人脸登机是其中的一个功能模块,当时只是写了后台的接口,调用人脸识别设备的api,给闸
- 今天有同事用swagger2开发时,有一方法返回Map<String,List<Object>>出现无法解析错误。P
- 先看看效果图:源码下载:Android Navigation TabBar控件实现多彩标签栏代码:MainActivity.javapack
- MyBatis-Plus是通过version机制实现乐观锁的。大致思路:取出记录,携带记录的当前version;更新记录的时候,比较记录当前
- 对于maven的部署和安装插件不熟的同学可以看一下上两篇文章maven的部署和安装:此笔记已经集成了maven的插件。一、构建Maven项目
- jcasbin简介:jcasbin 是一个用 Java 语言打造的轻量级开源访问控制框架https://github.com/casbin/
- 本文为大家分享了C#基于Socket套接字的网络通信封装代码,供大家参考,具体内容如下摘要之所以要进行Socket套接字通信库封装,主要是直
- 效果和代码都非常直观:实例1:TimePicker<RelativeLayout xmlns:android="http:/