ArrayList的的底层是一个顺序表。
顺序表是用一段地址连续的单元来依次存储数据元素的线性结构,他一般采用数组进行存储。可以在顺序表上进行增删改查。
1.ArrayList简介
ArrayList是一个普通的类,它底层是一个动态顺序表,实现了List接口。
(不是全部关系)

重要说明:
1.ArrayList是以泛型方式实现的,使用时必须要先实例化。
2.ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
3.ArrayList实现了Serializable接口,表明ArrayList是支持序列化的
- 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList
- ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表
6.ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
2.ArrayList的使用
2.1ArrayList的构造方法
方法: 解释:
ArrayList() 无参构造
ArrayList(Collection<? extends E> c) 利用其他Collection构建ArrayList
ArrayList(int initialCapacity) 指定顺序表初始容量
示例:
java
import java.util.ArrayList;
public class Test1 {
public static void main(String[] args) {
//这样创建没什么特别的....
//因为ArrayList实现了List接口,所以用List来接收也行
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(1);//添加
list1.add(2);
list1.add(3);
//ArrayList也实现了Collection
ArrayList<Integer> list2 = new ArrayList<>(list1);
System.out.println(list2); //list2没add(),却打印[1,2,3]
//这也没什么特别的
ArrayList<Integer> list3 = new ArrayList<>(10);//顺序表初始空间为10
}
}
2.2ArrayList常见操作
ArrayList提供的方法很多,但常见的方法如下。

ArrayList可以进行增删查改,改、查的时间复杂度为O(1)(底层是一个数组),但增、删的时间复杂度可达O(n) 。
2.2.1ArrayList底层
ArrayList中会有int usedSize记录有效元素个数
当我们使用add()进行插入时,会出现以下请况;添加元素---》usedSize++

同理,当我们进行remove(删除)时,后面的值会依次向前补,usedSize--;虽然原来数组末尾的值还存在,但是ArrayList中遍历有效数组是依靠usedSize。
2.2.2ArrayList的遍历
java
List<String> list = new ArrayList<>();
list.add("1");
list.add("12");
list.add("123");
//法一:for循环遍历
for (int i=0;i< list.size();i++){
System.out.println(list.get(i));
}
//法二:for-each循环遍历
//ArrayList的底层是数组,所以可以这样操作
for(String str:list){
System.out.println(str);
}
//法三:借助迭代器
Iterator it = list.iterator();//因为AL实现了Iterable,所以它可以所以迭代器遍历
while(it.hasNext()){
System.out.print(it.next() + " ");
}
2.3ArrayList的扩容机制
有人或许会在2.2.1发出疑惑:
- 如果没给ArrayList指定数组大小,那数组初始大小为多少?
- 如果数组满了,再添加元素会报错吗?
解答:
当我们未给ArrayList指定数组大小时,它底层的数组大小就是0;只不过在add()内会判断有效元素个数是否与数组大小相同,相同则扩容

因此ArrayList的底层才会叫做动态顺序表!数组会自动扩容。
3.ArrayList实操
实现简单的洗牌算法:
提醒
- List<Card> list = new ArrayList<>();// 的意思是list的底层数组只能放Card类型的数据
- List<List<Card>> list = new ArrayList<>(); // 的意思是只能放List<Card>类型的数据,可以想象成二维数组。
java
public class Card {
public int rank; // 牌面值
public String suit; // 花色
@Override
public String toString() {
return "Card{" + rank + suit +
'}';
}
}
//总结就是 买牌,打乱牌(shuffle和swap方法都是用来打乱牌的),发牌
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
public class CardDemo {
public static final String[] SUITS = {"♠", "♥", "♣", "♦"};
// 买一副牌
private static List<Card> buyDeck() {
List<Card> deck = new ArrayList<>(52);
for (int i = 0; i < 4; i++) {
for (int j = 1; j <= 13; j++) {
String suit = SUITS[i];
int rank = j;
Card card = new Card();
card.rank = rank;
card.suit = suit;
deck.add(card);
}
}
return deck;
}
private static void swap(List<Card> deck, int i, int j) {
Card t = deck.get(i);
deck.set(i, deck.get(j));
deck.set(j, t);
}
private static void shuffle(List<Card> deck) {
Random random = new Random();
for (int i = deck.size() - 1; i > 0; i--) {
int r = random.nextInt(i);
swap(deck, i, r);
}
}
public static void main(String[] args) {
List<Card> deck = buyDeck();
System.out.println("刚买回来的牌:");
System.out.println(deck);
shuffle(deck);
System.out.println("洗过的牌:");
System.out.println(deck);
// 三个人,每个人轮流抓 5 张牌
List<List<Card>> hands = new ArrayList<>();
hands.add(new ArrayList<>());
hands.add(new ArrayList<>());
hands.add(new ArrayList<>());
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 3; j++) {
hands.get(j).add(deck.remove(0));
}
}
System.out.println("剩余的牌:");
System.out.println(deck);
System.out.println("A 手中的牌:");
System.out.println(hands.get(0));
System.out.println("B 手中的牌:");
System.out.println(hands.get(1));
System.out.println("C 手中的牌:");
System.out.println(hands.get(2));
}
}