目录
1. ArrayList的简单介绍
2. ArrayList的使用
2.1 ArrayList的构造方法
2.2 AraayList的常见操作
2.3 ArrayList的遍历
2.4 ArrayList的扩容机制
3. ArrayList的使用实例---扑克牌
4. ArrayList的模拟实现
1. ArrayList的简单介绍
在集合框架中,ArrayList是一个普通的类,实现了List接口,具体的框架图如下:
说明:
1. ArrayList实现RandomAccess接口,表明ArrayList支持随机访问
2. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
3. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的
4. 它与Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以使用Vector或者CopyOnWiterArrayList
5. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表
画图进行说明:
2. ArrayList的使用
2.1 ArrayList的构造方法
| 方法 | 解释说明 |
| ArrayList() | 无参数构造 |
| ArrayList(Collectionc) | 利用其他的Collection构建ArrayList |
| ArrayList(int initialCapacity) | 指定顺序表初始容量 |
2.2 AraayList的常见操作
ArrayList的方法比较多,但这里只展示常见的方法:
| 方法 | 解释说明 |
| boolean add(E e) | 尾插e |
| void add(int index,E element) | 将element插入index位置 |
| boolean addAll(Collection extends E>c) | 尾插c中的元素 |
| E remove(int index) | 删除index位置的元素 |
| boolean remove(Object o) | 删除遇到的第一个o |
| E get(int index) | 获取下标为index的元素 |
| E set(int index,E element) | 将下标为index的元素设置为element |
| void clear() | 清空 |
| boolean contains(Object o) | 判断o是否包含其中 |
| int indexOf(Object o) | 返回第一个o所在的下标 |
| int lastIndexOf(Object o) | 返回最后一个o所在的下标 |
| List | 截取部分list |
将上述方法进行代码展示:
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("javaSE");
list.add("javaWeb");
list.add("javaEE");
list.add("JVM");
System.out.println(list);
list.add(1,"java");
System.out.println(list);
list.remove(2);
System.out.println(list);
System.out.println(list.get(0));
list.set(3,"c++");
System.out.println(list.subList(0,2));
System.out.println(list.contains("java"));
System.out.println(list.indexOf("javaSE"));
}
//执行结果:
[javaSE, javaWeb, javaEE, JVM]
[javaSE, java, javaWeb, javaEE, JVM]
[javaSE, java, javaEE, JVM]
javaSE
[javaSE, java]
true
0
2.3 ArrayList的遍历
有三种方式进行遍历:for循环 foreach 迭代器
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
//for循环
for(int i=0;i it = list.listIterator();
while(it.hasNext()){
System.out.print(it.next()+" ");
}
}
2.4 ArrayList的扩容机制
下面的代码有缺陷吗?
public static void main(String[] args) {
List list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(i);
}
}
ArrayList是一个动态类型的顺序表,即:在插入元素的过程中会自动扩容
Object[] elementData; // 存放元素的空间
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默认空间
private static final int DEFAULT_CAPACITY = 10; // 默认容量大小
public void ensureCapacity(int minCapacity) {
// 计算最小的扩容大小
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)? 0 :
DEFAULT_CAPACITY;
// 检测是否需要扩容
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 如果minCapacity比数组的容量大,就调用grow进行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
// 获取旧空间大小
int oldCapacity = elementData.length;
// 预计按照1.5倍方式扩容
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果用户需要扩容大小 超过 原空间1.5倍,按照用户所需大小扩容
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果需要扩容大小超过MAX_ARRAY_SIZE,重新计算容量大小
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 调用copyOf扩容
elementData = Arrays.copyOf(elementData, newCapacity);
}
总结:
1. 检测是否真正需要扩容,如果是调用grow准备扩容
2. 预估需要扩容的大小
初步预估按照1.5倍大小扩容
如果用户所需大小超过预估的1.5倍大小,则按照用户所需大小进行扩容
真正扩容之前检测是否能扩容成功,防止太大导致扩容失败
3. 使用copyOf进行扩容
3. ArrayList的使用实例---扑克牌
public class Card {
public char suit;
public String rank;
public Card(char suit, String rank) {
this.suit = suit;
this.rank = rank;
}
@Override
public String toString() {
return "["+suit+":"+rank+"]";
}
}
public class CardGame {
public List getCards(){
char[] suits = {'♥','♠','♦','♣'};
String[] ranks = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
List cards = new ArrayList<>(52);
for(int i=0;i<4;i++){
for(int j=0;j<13;j++){
cards.add(new Card(suits[i],ranks[j]));
}
}
return cards;
}
public void swap(List cards,int i,int j){
Card temp = cards.get(i);
cards.set(i,cards.get(j));
cards.set(j,temp);
}
public void shuffle(List cards){
Random random = new Random();
for(int i=cards.size()-1;i>0;i--){
int j = random.nextInt(i);
swap(cards,i,j);
}
}
public static void main(String[] args) {
CardGame cg = new CardGame();
List cards = cg.getCards();
System.out.println("一副新牌:");
System.out.println(cards);
System.out.println("一副洗过的牌:");
cg.shuffle(cards);
System.out.println(cards);
List> hands = new ArrayList<>(3);
hands.add(new ArrayList<>(13));
hands.add(new ArrayList<>(13));
hands.add(new ArrayList<>(13));
for(int i=0;i<13;i++){
for(int j=0;j<3;j++){
hands.get(j).add(cards.remove(0));
}
}
System.out.println();
System.out.println("A,B,C三人开始揭牌........");
System.out.println();
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));
ArrayList array = new ArrayList<>();
}
}
执行结果:
一副新牌:
[[♥:A], [♥:2], [♥:3], [♥:4], [♥:5], [♥:6], [♥:7], [♥:8], [♥:9], [♥:10], [♥:J], [♥:Q], [♥:K], [♠:A], [♠:2], [♠:3], [♠:4], [♠:5], [♠:6], [♠:7], [♠:8], [♠:9], [♠:10], [♠:J], [♠:Q], [♠:K], [♦:A], [♦:2], [♦:3], [♦:4], [♦:5], [♦:6], [♦:7], [♦:8], [♦:9], [♦:10], [♦:J], [♦:Q], [♦:K], [♣:A], [♣:2], [♣:3], [♣:4], [♣:5], [♣:6], [♣:7], [♣:8], [♣:9], [♣:10], [♣:J], [♣:Q], [♣:K]]
一副洗过的牌:
[[♥:8], [♦:9], [♠:A], [♦:2], [♣:K], [♣:7], [♦:A], [♥:7], [♠:4], [♠:6], [♥:10], [♠:J], [♥:Q], [♦:8], [♦:K], [♣:Q], [♥:2], [♠:Q], [♠:9], [♠:3], [♥:K], [♠:K], [♥:A], [♠:2], [♣:2], [♣:4], [♣:3], [♥:J], [♣:9], [♣:6], [♦:J], [♦:4], [♦:6], [♦:10], [♠:10], [♣:10], [♥:4], [♣:A], [♥:9], [♦:3], [♥:5], [♠:5], [♣:5], [♣:8], [♥:3], [♦:5], [♠:7], [♣:J], [♥:6], [♠:8], [♦:Q], [♦:7]]A,B,C三人开始揭牌........
A手中的牌:
[[♥:8], [♦:2], [♦:A], [♠:6], [♥:Q], [♣:Q], [♠:9], [♠:K], [♣:2], [♥:J], [♦:J], [♦:10], [♥:4]]
B手中的牌
[[♦:9], [♣:K], [♥:7], [♥:10], [♦:8], [♥:2], [♠:3], [♥:A], [♣:4], [♣:9], [♦:4], [♠:10], [♣:A]]
C手中的牌
[[♠:A], [♣:7], [♠:4], [♠:J], [♦:K], [♠:Q], [♥:K], [♠:2], [♣:3], [♣:6], [♦:6], [♣:10], [♥:9]]



