1、ArrayList
数据结构(动态数组、自动扩容)
1)添加元素时容量不够
2)新建一个数组,长度为原数组长度 * 扩充因子(1.5)。
3)新元素放入新数组,并将数组赋值给集合,原数组丢弃。
两个常量空数组:节省集合创建时占用的内存
1)EMPTY_ELEMENTDATA:构造器指定了初始容器,容量不够时按1.5倍扩容
2)DEFAULTCAPACITY_EMPTY_ELEMENTDATA:无参构造器,初次添加元素时容量默认初始化10,容量不够时按1.5倍扩容。
EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA两个都是ArrayList的成员变量,并且都被声明为static final;更为核心的是,这两个都是空数组,那么问题来了,为什么要这样去规范呢?
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
发现 ArrayList有三个构造函数:无参构造、给定初始容量构造、集合类中进行构造
1)无参构造:
无参构造时,Obeject数组elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
2)给定初始容量构造:
源码具体逻辑如下:
当 传入的初始容量initialCapacity > 0为真时,创建一个大小为initialCapacity的空数组,并将引用赋给elementData;
当 传入的初始容量initialCapacity = 0为真时,将空数组EMPTY_ELEMENTDATA赋给elementData;
当 传入的初始容量initialCapacity < 0为真时,直接抛出IllegalArgumentException异常。
3)集合类中进行构造:
如果长度为0那么 elementData = EMPTY_ELEMENTDATA,否则进行拷贝
即:
当无参构造时,Obeject数组elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
当有参构造时,如果给定初始容量为0,或者传入集合为空集合(不是null),那么,将空数组EMPTY_ELEMENTDATA赋给elementData;
迭代器:fail-fast(快速失败机制)
iterator()获取迭代器时,保存modCount(操作次数)快照,游标初始化为0.
hasNext判断条件:cursor != size,如果有其他县城更改了集合的长度,会导致size变话,modCount和快照就会有误差。
next()取元素时,为防止下标越界,先判断modCount和快照是否相同,不同意味着size已变话。
如下图所示:
拷贝:拷贝栈中的内容
拷贝前后是否相互独立:(三种情况)
基本类型:独立 在栈中分配,拷贝一份栈中的内容,因此拷贝前后的变量完全独立。
以用类型: 不独立 栈中只记录了引用地址,拷贝一份栈中的内容,拷贝前后都是指向堆中的同一块内存。
String: 独立 栈中记录内存地址,但是指向的内容在常量池中,如果修改该常量,不会直接修改,而是生成一个新的常量并赋值给变量,因此拷贝前后的变量指向不同的内存地址。
.jpg
ArraysasList:
接收的是可变参数,基本类型不支持泛型化,会把整个数组当成一个元素放进新的数组。
用法
优点:
1、支持自动改变大小
2、可以灵活的插入元素
3、可以灵活的删除元素
局限:
比一般的数组的速度慢一些;
一、初始化:
1、不初始化容量
ArrayList arr1 = new ArrayList(); //不初始化刚开始的数组容量,当数组容量满时数组会自动一当前数组容量的2倍扩容
2、初始化容量
ArrayList arr2 = new ArrayList(3);//初始容量为3
3、用一个集合或数组初始化
ArrayList arr3 = new ArrayList(a); //a为集合或数组
二、添加元素
1)add(object value;) 将指定元素object value追加到集合的末尾
ArrayList arr = new ArrayList(); //初始化数组,下面各种方法省略初始化
arr.add("a"); //往数组里添加元素
2)a dd(int index, Object obj);
功能:在集合中指定index位置,添加新元素obj
三、删除元素
方法:remove();
功能:从集合中删除指定位置处的元素,返回该元素
arr.remove("a"); //在数组里删除元素(根据对象删除)
arr.remove(0); //根据下标删除ArrayList的元素
四、替换元素
方法:set() ;
功能:用指定元素obj替代集合中指定index位置的元素
arr.set(1, "10"); // 设置第2个元素为10
五、clear清空
六、查找元素
方法:get(int index); //index -- 该元素返回的索引值
功能:返回集合中指定位置上的元素
import java.util.ArrayList;
public class ArrayListDemo01 {
public static void main(String[] args) {
// 创建ArrayList集合
ArrayList<String> list = new ArrayList<String>();
// 向集合中添加元素
list.add("stu1");
list.add("stu2");
list.add("stu3");
list.add("stu4");
// 获取集合中元素的个数
System.out.println("集合的长度:" + list.size());
// 取出并打印指定位置的元素
System.out.println("第1个元素是:" + list.get(0));
System.out.println("第2个元素是:" + list.get(1));
System.out.println("第3个元素是:" + list.get(2));
System.out.println("第4个元素是:" + list.get(3));
}
}
网友评论