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

重要说明:
1.ArrayList是以泛型方式实现的,使用时必须要先实例化。
2.ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
3.ArrayList实现了Serializable接口,表明ArrayList是支持序列化的
4. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList
2.ArrayList的使用
2.1ArrayList的构造方法
方法: 解释:
ArrayList() 无参构造
ArrayList(Collection<? extends E> c) 利用其他Collection构建ArrayList
ArrayList(int initialCapacity) 指定顺序表初始容量
示例:
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也实现了CollectionArrayList<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的遍历
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>类型的数据,可以想象成二维数组。
public class Card {public int rank; // 牌面值public String suit; // 花色@Overridepublic 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));}}