目录
List
常用方法:
方法 | 说明 |
---|---|
public void add(int index,E element) | 在指定的索引位置上添加数据 |
public E get(int index) | 获取指定索引位置上的数据 |
public int indexOf(Object o) | 查找指定对象的索引位置 |
public ListIterator listIterator() | 获取ListIterator接口实例 |
public static List of(E …element) | 通过指定的内容创建List集合 |
public E set(int index,E element) | 修改指定索引位置上的数据 |
default void sort(Comparator<? super E> c) | 实现List集合排序 |
List<String> list = List.of(); //使用of创建的List数组可以读,不可以改。(JDK1.9新增)
List<String> listA = new ArrayList<>(); //使用子类向上转型可以修改数据
List<String> listB = new LinkedList<>();//使用子类向上转型可以修改数据
List<String> listC = new Vector<>(); //使用子类向上转型可以修改数据
ArrayList
ArrayList使用数组的形式实现的,可以根据索引下标查询数据。
ArrayList无参构造源码:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //默认初始容量为0
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = new Object[0];
ArrayList有参构造源码:
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];//大于0开辟一个传入数据大小的Object的数组
} else {
if (initialCapacity != 0) {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
this.elementData = EMPTY_ELEMENTDATA; //输入0,和无参构造一样
}
}
private static final Object[] EMPTY_ELEMENTDATA = new Object[0];
在使用add()、addAll()增加数据时在进行扩充操作。
在10或10以内用无参构造比较好,大于10用有参构造不然会产生垃圾空间。
add源码扩充的方法:
public boolean add(E e) {
++this.modCount; //线程保护
this.add(e, this.elementData, this.size);
return true;
}
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length) { //判断数据的容量是否满了
elementData = this.grow(); //容量扩充
}
elementData[s] = e;
this.size = s + 1;
}
private Object[] grow() {
return this.grow(this.size + 1);
}
private Object[] grow(int minCapacity) {
return this.elementData = Arrays.copyOf(this.elementData, this.newCapacity(minCapacity)); //copyOf改变ArrayList的容量赋给新的ArrayList数组
}
//数组容量扩充
private int newCapacity(int minCapacity) {
int oldCapacity = this.elementData.length; //获取前数组的长度
int newCapacity = oldCapacity + (oldCapacity >> 1); //旧数据+新数据(旧数据右移1,相当于除2)
if (newCapacity - minCapacity <= 0) {
if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(10, minCapacity); //第一次增加数据时ArrayList的容量变为10
} else if (minCapacity < 0) {
throw new OutOfMemoryError();
} else {
return minCapacity;
}
} else {
return newCapacity - 2147483639 <= 0 ? newCapacity : hugeCapacity(minCapacity);
}
}
ArrayList扩容步骤:
1、ArrayList在未指定容量时,默认为0,而可以说容量为10。
2、在第一次增加数据时,判断ArrayList的长度 == size,进行扩容操作。
3、使用Arrays.copyOf()保留原数组内容的同时进行数组扩容,改变容量长度。
4、在newCapacity()内,进行操作。
1)获取数组长度。
2)获取新的长度 newCapacity = (oldCapacity + (Capacity >>1)); 右移1 就是除2。
5、判定新的长度 - (传入的size + 1)<=0。
1)判断数组是否容量为0,为0返回Math.max(10,传入的size + 1的值); 返回两个数的最大的那一个,第一次返回10。
2)小于0,报错。
3)大于0,返回传入的size + 1的值。
6、判定 (新的长度 - (传入的size + 1)> 0) newCapacity - 2147483639(最大array的长度)<= 0 ? newCapacity : hugeCapacity(传入的size + 1的值);
LinkedList
LinkedList使用链表的形式实现数据的存储,但查询的性能不高。
Vector
Vector的实现和ArrayList类似,但使用率极低。
Vector默认容量为10:
public Vector() {
this(10);
}
区别
ArrayList: 在JDK1.2提出加入集合类,基于数组实现的动态数据存储,根据索引查询的时间复杂度为O(1),内部未使用线程同步,属于非线程安全。
LinkedList: 在JDK1.2提出加入集合类,基于链表实现数据存储,根据索引查询的时间复杂度为O(n)。
Vector: 在JDK1.0提出的一个类,在JDK1.2加入集合类,基于数组实现的动态数据存储,内部方法使用了synchronized同步,属于线程安全。