### ArrayList
* ArrayList类支持能够按需增长的动态数组,增长策略oldCapacity + \(oldCapacity >> 1\)即原来的长度+原长度的一半
```
int newCapacity = oldCapacity + (oldCapacity >> 1);
```
* 默认容量大小是10
```
private static final int DEFAULT_CAPACITY = 10;
```
### 主要API
* **add\(E e\)**
add主要的执行逻辑如下:
1)确保数组已使用长度(size)加1之后足够存下下一个数据
2)修改次数modCount 标识自增1,如果当前数组已使用长度(size)加1后的大于当前的数组长度,则调用grow方法,增长数组,grow方法会将当前数组的长度变为原来容量的1.5倍。
```
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
```
3)确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上。
4)返回添加成功布尔值;
```
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
```
* **add\(int index, E element\)**
![](../assets/20180411104349001.png)
这个方法其实和上面的add类似,该方法可以按照元素的位置,指定位置插入元素,具体的执行逻辑如下:
1)确保数插入的位置小于等于当前数组长度,并且不小于0,否则抛出异常
2)确保数组已使用长度(size)加1之后足够存下下一个数据
3)修改次数modCount标识自增1,如果当前数组已使用长度(size)加1后的大于当前的数组长度,则调用grow方法,增长数组
4)grow方法会将当前数组的长度变为原来容量的1.5倍。
5)确保有足够的容量之后,使用System.arraycopy 将需要插入的位置(index)后面的元素统统往后移动一位。
6)将新的数据内容存放到数组的指定位置(index)上
* grow\(\)扩容
```
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
```
* **get\(int index\)**
```
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
```
* **remove\(int index\)**
根据索引remove
1)判断索引有没有越界
2)自增修改次数
3)将指定位置(index)上的元素保存到oldValue
4)将指定位置(index)后的元素都往前移动一位
5)将最后面的一个元素置空,好让垃圾回收器回收
6)将原来的值oldValue返回
```
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
```
_**注意:调用remove方法不会缩减数组的长度,只是将最后一个数组元素置空而已**_
* trimToSize\(\)缩小集合容量
* toArray\(\)将集合转换为数组
* Arrays初始化
```
List list = Arrays.asList("a", "b");
List list = new ArrayList(){};
```
### 知识点
* ArrayList自己实现了序列化和反序列化的方法,因为它自己实现了 private void writeObject\(java.io.ObjectOutputStream s\)和 private void readObject\(java.io.ObjectInputStream s\) 方法
* ArrayList基于数组方式实现,无容量的限制(会扩容)
* 添加元素时可能要扩容(所以最好预判一下),删除元素时不会减少容量(若希望减少容量,trimToSize\(\)),删除元素时,将删除掉的位置元素置为null,下次gc就会回收这些元素所占的内存空间。添加删除某个索引的数据时,需要整体移动数组所以效率比较低
* 线程不安全
* add\(int index, E element\):添加元素到数组中指定位置的时候,需要将该位置及其后边所有的元素都整块向后复制一位
* get\(int index\):获取指定位置上的元素时,可以通过索引直接获取(O\(1\))
* remove\(Object o\)需要遍历数组
* remove\(int index\)不需要遍历数组,只需判断index是否符合条件即可,效率比remove\(Object o\)高
* contains\(E\)需要遍历数组
* 使用iterator遍历可能会引发多线程异常
* 中文排序
```
Collator collator = Collator.getInstance(Locale.CHINA);
List list = Arrays.asList("罗友宝", "黄慧", "阿伟", "车晓");
Collections.sort(list, collator);
list.stream().forEach(System.err::println);
```
- java演变
- JDK各个版本的新特性
- JDK1.5新特性
- JDK1.6新特性
- JDK1.7新特性
- JDK1.8新特性
- JAVA基础
- 面向对象特性
- 多态
- 方法重载
- 方法重写
- class
- 常量
- 访问修饰符
- 类加载路径
- java-equals
- 局部类
- java-hashCode
- Java类初始化顺序
- java-clone方法
- JAVA对象实例化的方法
- 基础部分
- JAVA基础特性
- JAVA关键字
- javabean
- static
- 日期相关
- final
- interface
- 函数式接口
- JAVA异常
- 异常屏蔽
- try-with-resource资源泄露
- JAVA引用
- WeakReference
- SoftReference
- PhantomReference
- 位运算符
- try-with-resource语法糖
- JDK冷知识
- JAVA包装类
- JAVA基本类型与包装类
- java.lang.Boolean
- java.lang.Integer
- java.lang.Byte
- java.lang.Short
- java.lang.Long
- java.lang.Float
- java.lang.Double
- java.lang.Character
- 日期相关
- TemporalAdjusters
- String
- 字符串常量池
- String拼接
- String编译期优化
- StringBuilder&StringBuffer
- intern
- 注解
- java标准注解
- 内置注解
- 元注解
- 自定义注解
- 注解处理器
- JVM注解
- Java8 Annotation新特性
- 反射-Reflective
- Reflection
- Class
- Constructor
- Method
- javabean-property
- MethodHandles
- 泛型
- 类型擦除
- bridge-method
- Accessor&Mutator方法
- enum
- JAVA数组
- finalize方法
- JAR文件
- JAVA高级编程
- CORBA
- JMX
- SPI
- Java SPI使用约定
- ServiceLoader
- 实际应用
- IO
- 工具类
- JDK常用工具类
- Objects
- System
- Optional
- Throwable
- Collections
- Array
- Arrays
- System
- Unsafe
- Number
- ClassLoader
- Runtime
- Object
- Comparator
- VarHandle
- 数据结构
- 栈-Stack
- 队列(Queue)
- Deque
- PriorityQueue
- BlockingQueue
- SynchronousQueue
- ArrayBlockingQueue
- LinkedBlockingQueue
- PriorityBlockingQueue
- ConcurrentLinkedQueue
- 列表
- 迭代器
- KV键值对数据类型
- HashMap
- TreeMap
- Hash冲突
- ConcurrentHashMap
- JDK1.7 ConcurrentHashMap结构
- jdk7&jdk8区别
- 集合
- Vector
- Stack
- HashSet
- TreeSet
- ArrayList
- LinkedList
- ArrayList && LinkedList相互转换
- 线程安全的集合类
- 集合类遍历性能
- 并发容器
- CopyOnWriteArrayList
- ConcurrentHashMap
- 同步容器
- BitMap
- BloomFilter
- SkipList
- 设计模式
- 设计模式六大原则
- 单例模式
- 代理模式
- 静态代理
- 动态代理
- JDK动态代理
- cglib动态代理
- spring aop
- 策略模式
- SpringAOP策略模式的运用
- 生产者消费者模式
- 迭代器模式
- 函数式编程
- 方法引用
- 性能问题
- Lambda
- Lambda类型检查
- Stream
- findFirst和findAny
- reduce
- 原始类型流特化
- 无限流
- 收集器
- 并行流
- AOP
- 静态织入
- aspect
- aspect的定义
- AspectJ与SpringAOP
- 动态织入
- 静态代理
- 动态代理
- JDK动态代理
- CGLib动态代理
- Spring AOP
- SpringAOP五种通知类型
- @Before
- @AfterReturning
- @AfterThrowing
- @After
- @Around
- Aspect优先级
- SpringAOP切点表达式
- within
- execution
- 嵌套调用
- 系统优化与重构
- 重叠构造器模式
- 工具类构造器优化
- 常见面试题
- new Object()到底占用几个字节
- 访问修饰符
- cloneable接口实现原理
- 异常分类以及处理机制
- wait和sleep的区别
- 数组在内存中如何分配
- 类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式
- 类的实例化顺序
- 附录
- JAVA术语
- FAQ
- 墨菲定律
- 康威定律
- 软件设计原则
- 阿姆达尔定律
- 字节码工具
- OSGI