ArrayList以数组的形式实现,顺序插入、查找快,插入、删除较慢(==寻址容易,插入删除困难==)
ArrayList的基本元素:
元素 | 作用 |
---|---|
private transient Object[] elementData; | ArrayList是基于数组的一个实现,elementData就是底层的数组 |
private int size; | ArrayList里面元素的个数,这里要注意一下,size是按照调用add、remove方法的次数进行自增或者自减的,所以add了一个null进入ArrayList,size也会加1 |
四个关注点在ArrayList上的答案
关注点 | 结论 |
---|---|
ArrayList是否允许空 | 允许 |
ArrayList是否允许重复数据 | 允许 |
ArrayList是否有序 | 有序 |
ArrayList是否线程安全 | 非线程安全 |
ArrayList的优点:
- ArrayList底层以数组实现,是一种随机访问模式,再加上它实现了RandomAccess接口,因此查找也就是get的时候非常快
- ArrayList在顺序添加一个元素的时候非常方便,只是往数组里面添加了一个元素而已
ArrayList的缺点: - 删除元素的时候,涉及到一次元素复制,如果要复制的元素很多,那么就会比较耗费性能
- 插入元素的时候,涉及到一次元素复制,如果要复制的元素很多,那么就会比较耗费性能
因此,==ArrayList比较适合顺序添加、随机访问的场景==。
注意两个问题:
- ArrayList和Vector的区别
- 为什么ArrayList的elementData是用transient修饰的?
1、 容器默认大小为10,位置不够了自动扩增,每次增加当前长度的一半;(扩增时用Arrays.copyOf进行扩增)
2、 数组容量扩增到Integer.MAX_VALUE-8的时候,就会开始限制数组扩充,超过Integer.MAX_VALUE的时候,抛内存溢出异常;
3、 clone是浅拷贝,List中的引用指向的还是相同数据;
4、 线程不安全的;
5、 迭代器中的expectedModCount和modCount:迭代器初始化时,会用modCount去初始化expectedModCount,在迭代器的操作中都要检查这两个值的等值性,不想等抛出ConcurrentModificationException异常表示当前List正在被修改,为什么呢?如下:
List本身的add和remove操作时都会修改modCount的值,如果在迭代器循环迭代过程中调用了List本身的add和remove方法就会导致两个值不想等而抛出异常,而迭代器本身的remove则不会有这个问题,它会在remove完成后重新更新一遍expectedModCount保持两个值的等值性。
6、 ListIterator和普通迭代器类似,只是多了双向迭代的功能;
7、 ArrayList本身的sort其实是调用Arrays.sort传入比较器实现的
ArrayList自定义源码如下:
package com.hao.laker.study.javabase.source;
import java.util.Arrays;
/**
* 自定义数组
* Created by haojiahong on 17/3/1.
*/
public class MyArrayList<E> {
private int capacity = 10;
private int size = 0;
private Object[] tables;
public MyArrayList() {
tables = new Object[capacity];
}
public MyArrayList(int capacity) {
this.capacity = capacity;
tables = new Object[capacity];
}
public void add(E e) {
if (size >= capacity) {
enlargeCapacity();
}
tables[size] = e;
size++;
}
public void remove(int index) {
if (index >= size) {
throw new RuntimeException("the " + index + " is out of bond");
}
for (int i = index; i < size - 1; i++) {
tables[i] = tables[i + 1];
}
tables[size - 1] = null;//垃圾回收
size--;
}
@SuppressWarnings("unchecked")
public E get(int index) {
if (index >= size) {
throw new RuntimeException("the " + index + " is out of bond");
}
return (E) tables[index];
}
/**
* 数组扩容方法
*/
private void enlargeCapacity() {
capacity = capacity * 3 / 2 + 1;
// Object[] newTables = new Object[capacity];
// System.arraycopy(tables, 0, newTables, 0, tables.length);
Object[] newTables = Arrays.copyOf(tables, capacity);
tables = newTables;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < size; i++) {
sb.append(tables[i]).append(",");
}
if (size > 0) {
sb.deleteCharAt(sb.length() - 1);
}
sb.append("]");
return sb.toString();
}
public static void main(String[] args) {
MyArrayList<Integer> myArrayList = new MyArrayList<>();
//添加操作
myArrayList.add(1);
myArrayList.add(2);
myArrayList.add(3);
myArrayList.add(1);
myArrayList.add(2);
myArrayList.add(3);
myArrayList.add(1);
myArrayList.add(2);
myArrayList.add(3);
myArrayList.add(1);
myArrayList.add(2);
myArrayList.add(3);
System.out.println(myArrayList.toString());
//删除操作
myArrayList.remove(2);
System.out.println(myArrayList.toString());
//get操作
System.out.println(myArrayList.get(0));
}
}
网友评论