当前位置: 首页 > news >正文

ArrayList详解与实际应用

目录

一、ArrayList 简介

二、ArrayList的基本使用

2.1 构造方法

2.2 常用方法

2.3 遍历方式

三、ArrayList的扩容机制

3.1 扩容流程源码分析

3.2 扩容性能分析

四、ArrayList的实践应用

4.1 杨辉三角

4.2 扑克洗牌


一、ArrayList 简介

ArrayList是Java集合框架中的一个重要类,位于java.util包中。它实现了List接口,底层基于数组实现,可以根据需要动态扩容。

ArrayList的特点:

  1. 以泛型方式实现,类型安全
  2. 实现了RandomAccess接口,支持快速随机访问
  3. 实现了Cloneable接口,支持克隆操作
  4. 实现了Serializable接口,支持序列化
  5. 非线程安全,多线程环境下需要额外同步
  6. 底层使用动态数组,支持自动扩容

二、ArrayList的基本使用

2.1 构造方法

//1. 无参构造,默认初始容量为10
List<Integer> list1 = new ArrayList<>();//2. 指定初始容量
List<Integer> list2 = new ArrayList<>(20);//3. 通过其他集合构造
List<Integer> list3 = new ArrayList<>(list2);

2.2 常用方法

ArrayList提供了丰富的方法来操作元素:

方法描述时间复杂度
boolean add(E e)尾插元素O(1) 平均
void add(int index, E element)在指定位置插入元素O(n)
E remove(int index)删除指定位置元素O(n)
boolean remove(Object o)删除首次出现的指定元素O(n)
E get(int index)获取指定位置元素O(1)
E set(int index, E element)设置指定位置元素O(1)
int size()返回元素个数O(1)
boolean contains(Object obj)判断是否包含指定元素O(n)
int indexOf(Object obj)返回指定元素首次出现的索引O(n)
void clear()清空所有元素O(1)

使用示例:

List<String> list = new ArrayList<>();
list.add("JavaSE");
list.add("JavaWeb");
list.add("JavaEE");// 获取元素
System.out.println(list.get(1)); // 输出: JavaWeb// 修改元素
list.set(1, "JavaWEB");
System.out.println(list.get(1)); // 输出: JavaWEB// 插入元素
list.add(1, "Java数据结构");
System.out.println(list); // 输出: [JavaSE, Java数据结构, JavaWEB, JavaEE]// 删除元素
list.remove("JavaEE");
System.out.println(list); // 输出: [JavaSE, Java数据结构, JavaWEB]// 检查包含
if(list.contains("JavaSE")) {System.out.println("包含JavaSE");
}// 清空列表
list.clear();
System.out.println(list.size()); // 输出: 0

2.3 遍历方式

ArrayList支持三种遍历方式,分别是 for循环foreach循环迭代器 :

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);// 1. for循环+下标
for(int i = 0; i < list.size(); i++) {System.out.print(list.get(i) + " ");
}
System.out.println();// 2. foreach循环
for(Integer num : list) {System.out.print(num + " ");
}
System.out.println();// 3. 迭代器
Iterator<Integer> it = list.iterator();
while(it.hasNext()) {System.out.print(it.next() + " ");
}
System.out.println();

三、ArrayList的扩容机制

ArrayList的扩容机制是其最重要的特性之一。如果当前数组已满,ArrayList会自动创建一个更大的数组,并将原数组中的元素复制到新的数组中。

3.1 扩容流程源码分析

  1. 检查当前数组容量是否足够
  2. 如果容量不足,计算新的容量(通常是原容量的1.5倍)
  3. 创建新数组并复制元素
  4. 更新内部数组引用
// ArrayList扩容核心源码分析
public boolean add(E e) {ensureCapacityInternal(size + 1); // 确保内部容量足够elementData[size] = e;size++;return true;
}private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}private static int calculateCapacity(Object[] elementData, int minCapacity) {if(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;
}private void ensureExplicitCapacity(int minCapacity) {modCount++;if(minCapacity - elementData.length > 0)grow(minCapacity);
}private void grow(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5倍扩容if(newCapacity - minCapacity < 0)newCapacity = minCapacity;if(newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);elementData = Arrays.copyOf(elementData, newCapacity);
}

3.2 扩容性能分析

ArrayList得扩容操作需要创建新数组并复制所有元素,时间复杂度是O(n)。

因此,在已知大致容量的情况下,最好使用带初始容量的构造方法,减少扩容次数。

List<Integer> list = new ArrayList<>(1000);
for (int i = 0; i < 1000; i++) {list.add(i);
}

四、ArrayList的实践应用

4.1 杨辉三角

  1. 我们可以把杨辉三角看成一个下三角形,第一行只有一个元素1,其余行的第一个和最后一个元素都是1
  2. 我们可以用一个二维顺序表(相当于二维数组)来存储,第一行用一个顺序表存入1
  3. 然后利用循环填入剩下的元素
  4. 最后接入二维顺序表即可
public static List<List<Integer>> generatePascalTriangle(int numRows) {List<List<Integer>> list = new ArrayList<>();//第一行List<Integer> list0 = new ArrayList<>();list0.add(1);list.add(list0);for (int i = 0; i < numRows; i++) {//每一行第一个元素List<Integer> curRow = new ArrayList<>();curRow.add(1);//每一行中间的元素List<Integer> preRow = new ArrayList<>();for (int j = 1; j < i; j++) {int v1 = preRow.get(j);int v2 = preRow.get(j-1);curRow.add(v1+v2);}//每一行最后一个元素curRow.add(1);list.add(curRow);}return list;
}

4.2 扑克洗牌

  1. 首先我们把这个问题分成三个步骤:生成扑克牌、洗牌、发牌
  2. 生成扑克牌:我们可以利用循环嵌套来生成52张牌(除去大小王)并存入Poker类中
  3. 洗牌:利用随机数生成将顺序表中下标为i的元素改至下标为index(随机生成下标),如此一来就可以实现扑克牌的打乱
  4. 发牌:把所有人的手牌视作一个二维数组,则每个人的手牌就是一个一维数组,利用循环嵌套就可以将牌存入每个人的手牌中
class Poker {         //除去两张鬼牌剩余的52张手牌private String suit;                            //手牌的花色private int rank;                                //手牌的大小public Poker(String suit, int rank) {this.suit = suit;this.rank = rank;}@Overridepublic String toString() {return "{"+suit+rank+"} ";}
}
class PokerPrepare {public static final String[] suits = {"♠","♥","♣","♦"};     //四种花色//1.扑克牌的生成public List<Poker> pokerCards () {List<Poker> cardList = new ArrayList<>();for (int i = 1; i <= 13; i++) {     //控制牌面for (int j = 0; j < 4; j++) {   //控制花色int rank = i;String suit = suits[j];Poker card = new Poker(suit,rank);  //放入牌cardList.add(card);}}return cardList;}//2.洗牌public void shuffle (List<Poker> cardList) {Random r = new Random();for (int i = cardList.size()-1; i > 0; i--) {int index = r.nextInt(i);swap(cardList,i,index);}}private void swap (List<Poker> cardList,int i, int index) {Poker t = cardList.get(i);cardList.set(i,cardList.get(index));cardList.set(index,t);}//3.摸牌(三人,每人五张牌)public List<List<Poker>> getCards (List<Poker> cardList) {List<Poker> hand0 = new ArrayList<>();List<Poker> hand1 = new ArrayList<>();List<Poker> hand2 = new ArrayList<>();List<List<Poker>> hands = new ArrayList<>();hands.add(hand0);hands.add(hand1);hands.add(hand2);for (int i = 0; i < 5; i++) {for (int j = 0; j < 3; j++) {Poker card = cardList.remove(0);  //相当于将牌堆最顶上的牌拿取hands.get(j).add(card);                  //第j个人手下的卡牌}}return hands;}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class PokerGame {public static void main(String[] args) {PokerPrepare pokerPrepare = new PokerPrepare();//1.生成一副牌(购买一副牌)List<Poker> cardList = pokerPrepare.pokerCards();System.out.println(cardList);//2.洗牌pokerPrepare.shuffle(cardList);System.out.println(cardList);//3.摸牌List<List<Poker>> hands = pokerPrepare.getCards(cardList);for (int i = 0; i < cardList.size(); i++) {System.out.print("第"+ (i+1) +"个人的手牌:"+ hands.get(i));System.out.println();}}
}


文章转载自:

http://cRe1p44m.gbLrn.cn
http://rC4ldXgb.gbLrn.cn
http://8jjGofIx.gbLrn.cn
http://qZcgVVRF.gbLrn.cn
http://ukMDRVTL.gbLrn.cn
http://Qtotvvqm.gbLrn.cn
http://6ljqPvNU.gbLrn.cn
http://10T65tH9.gbLrn.cn
http://8dISoege.gbLrn.cn
http://SyvCOLWN.gbLrn.cn
http://7PQIE33W.gbLrn.cn
http://iqfL5QHw.gbLrn.cn
http://9Nh3M3AZ.gbLrn.cn
http://tVHS5Idr.gbLrn.cn
http://UXl2F6Po.gbLrn.cn
http://x9VWtMJ0.gbLrn.cn
http://uRFWJOuw.gbLrn.cn
http://apVEdRsH.gbLrn.cn
http://uLwPmqMj.gbLrn.cn
http://pVSNfRmd.gbLrn.cn
http://pxFqK5xt.gbLrn.cn
http://wVk0NjSc.gbLrn.cn
http://7rmwORnu.gbLrn.cn
http://aPlu3uVG.gbLrn.cn
http://SD7Syupf.gbLrn.cn
http://yiNSMs1M.gbLrn.cn
http://XEaZtKUq.gbLrn.cn
http://nRDq53ck.gbLrn.cn
http://U4QuIjHo.gbLrn.cn
http://PW72szde.gbLrn.cn
http://www.dtcms.com/a/375486.html

相关文章:

  • 德意志飞机公司与DLR合作完成D328 UpLift演示机地面振动测试
  • MongoDB 备份与恢复终极指南:mongodump 和 mongorestore 深度实战
  • ctfshow - web - 命令执行漏洞总结(二)
  • 基于STM32的GPS北斗定位系统
  • 2025年大陆12寸晶圆厂一览
  • VMware Workstation Pro 安装教程
  • Java Spring @Retention三种保留策略
  • 低代码平台的核心组件与功能解析:红迅低代码平台实战探秘
  • linux sudo权限
  • PM2 管理后端(设置项目自启动)
  • 中国香港服务器中常提到的双向/全程CN2是什么意思?
  • DCS+PLC协同优化:基于MQTT的分布式控制系统能效提升案例
  • Backend
  • 分布式专题——6 Redis缓存设计与性能优化
  • 《智能网联汽车交通仿真软件可信度评估》团标启动会圆满举办
  • 无人机云台电压类型及测量方法
  • 光伏无人机3D设计——高效出方案的快速设计方式!
  • K8s角色权限管理全解析
  • Postgresql 发送数据到Splunk
  • [网络入侵AI检测] CNN-LSTM混合模型
  • 使用列表推导式取代map和filter的最佳实践 (Effective Python 第27条)
  • Promise状态和方法都有哪些,以及实现原理
  • jquery基础知识总结
  • Qwen-VL系列-国产大模型开眼看世界
  • OpenEuler部署gitlab(小白的“升级打怪”成长之路)
  • 内存视角看「类、原型、实例」
  • 「类 vs 实例」对比 ,「类 - 原型 - 实例」的关系
  • sft冷启动时数据集构造需要注意哪些因素?为什么要做数据清洗与均衡采样?
  • OpenCV 模板匹配代码深度解析与应用场景全景分析
  • 2026年ESWA SCI1区TOP,适应性社会流动性重构差分进化算法ASMRDE,深度解析+性能实测