集合类源码简单阅读(一)(ArrayList)
来源:互联网 发布:网贷安卓源码 编辑:程序博客网 时间:2024/06/12 03:37
在休憩不知道该啃哪根骨头的情况下,选择了一根比较比较好啃的骨头,就是从Java基础知识开始,当然是源码,而集合就自然成为了要研究和记录了第一个源码(记录单纯是为了可以给自己看到一个学习轨迹,不足的地方有待大家提意见)
由于接下来会陆陆续续研究集合的源码,因此还是很传统的把这张图给贴出来了
六个接口:
Iterator,接口
Collection<E>,接口, Collection<E> extends Iterable<E>
Map ,接口 Map<K,V>
ListIterator<E>,接口, ListIterator<E> extends Iterator<E>
List, 接口, List<E> extends Collection<E>
Set,接口,Set<E> extends Collection<E>
SortedMap<K, V> ,接口,SortedMap<K,V> extends Map<K,V>
Collection的继承结构:
Collection<--List<--Vector
Collection<--List<--ArrayList
Collection<--List<--LinkedList
Collection<--Set<--HashSet
Collection<--Set<--HashSet<--LinkedHashSet
Collection<--Set<--SortedSet<--TreeSet
一、ArrayList(线性列表)
一、ArrayList(线性列表)
说明:底层的数据结构就是数组,数组元素类型为Object类型,即可以存放所有类型数据。我们对ArrayList类的实例的所有的操作底层都是基于数组的
1、Vector、ArrayList 都是以类似数组的形式存储在内存中,LinkedList 则以链表的形式进行存储。
2、Vector 线程同步,ArrayList、LinkedList 线程不同步;后两者一般用在线程安全的地方,也可以通过 Collections.synchronizedList(……);实现线程同步。
3、LinkedList 适合指定位置插入、删除操作,不适合查找;ArrayList、Vector适合查找,不适合指定位置的插入、删除操作。
4、ArrayList 在元素填满容器 时会自动扩充容器大小的 50%,而 Vector 则是100%,因此 ArrayList 更节省空间。
5、LinkedList 还实现了 Queue 接口,该接口比 List 提供了更多的方法,包括offer(),peek(),poll()等,多与一些线程池一起使用.
补充:以上都实现了序列化接口,这点在对象远程传输时很重要;而Vector,ArrayList 实现了 AccessRandom 接口,这是一个标记接口,此接口的主要目的是允许 一般的算法更改其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能
2.1 类的继承
class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess(可随机访问), Cloneable(可拷贝), java.io.Serializable(序列化)
2.2 类的属性
//序列化编号 private static final long serialVersionUID = 8683452581122892189L; //初始容量 private static final int DEFAULT_CAPACITY = 10; //用于空实例的共享空数组实例。 private static final Object[] EMPTY_ELEMENTDATA = {}; //共享空数组实例,用于默认大小的空实例。 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //存储ArrayList元素的数组缓冲区。 transient Object[] elementData; protected transient int modCount = 0; //数组实际大小 private int size; //要分配的数组的最大大小。 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
2.3 核心方法
1) add()方法
public boolean add(E e) { //增加元素 ensureCapacityInternal(size + 1); // 调用ensureCapacityInternal方法 elementData[size++] = e; return true; }
这只是第一步,接下来是ensureCapacityInternal(int minCapacity)方法
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //在初期时默认赋值minCapacity = 10 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); //调用ensureExplicitCapacity方法 }
然后是ensureExplicitCapacity(int minCapacity)方法
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) //是否为容器增容,初始为数组创建默认长度为10的空间 grow(minCapacity); }
最后是grow(int minCapacity)
private void grow(int minCapacity) { int oldCapacity = elementData.length; //旧容量 int newCapacity = oldCapacity + (oldCapacity >> 1); //新容量为旧容量的1.5倍(右位移) if (newCapacity - minCapacity < 0) //新容量小于指定参数容量 newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) //新容量大于最大容量 newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); //拷贝扩容新容量超过最大最大容量的时候
private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }2) set(int index,E elemnet)方法
由于ArrayList的本质是Object[],因此在设定ArrayList指定位置的值只需要将旧值覆盖即可
public E set(int index, E element) { //index 设置值的下标 element 要设定的值 rangeCheck(index); //checkindex E oldValue = elementData(index); //获取久值 elementData[index] = element; // 将element赋值给数组指定的下标 return oldValue; //返回旧值 }从上面看来set方法结构很简单,checkindex,然后覆盖值
private void rangeCheck(int index) { if (index >= size) //比较index与size的大小 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }获取指定位置的值方法
@SuppressWarnings("unchecked") //字符串{ @ code“unchecked”}被用来抑制未经检查的警告。 E elementData(int index) { return (E) elementData[index]; }3) add(int index, E element) 方法
在指定位置加值,调用ensureCapacityInternal(int minCapacity)确定数组大小,如果长度不够就扩容,然后新建一个新数组将旧数组
index之前的值以及index后的值复制到新数组,最后把参数element赋值给新数组的指定下标
public void add(int index, E element) { rangeCheckForAdd(index); //checkindex,与set里面一致 ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }
阅读全文
1 0
- 集合类源码简单阅读(一)(ArrayList)
- JAVA 集合类(java.util)源码阅读笔记------ArrayList
- 浅析Java集合类源码(一)--- Vector, ArrayList, LinkedList
- JAVA源码阅读-集合框架(一)
- JDK 1.7源码阅读笔记(二)集合类之ArrayList
- Java集合源码解析(一)ArrayList源码解析
- Java集合源码分析系列-(一)ArrayList源码剖析
- ArrayList集合(一)--源码
- ArrayList源码(一)
- jdk源码阅读一:ArrayList
- C# 集合类(一):ArrayList
- C# 集合类(一):ArrayList
- C# 集合类(一):ArrayList
- C# 集合类(一):ArrayList
- Java集合(一)---ArrayList
- Java集合--ArrayList(一)
- 源码阅读(一)
- 源码阅读(一)
- 1. Two Sum
- KMP算法的一些细节
- JAVA序列化和反序列化的常见格式
- 《.NET 设计规范》第 9 章:常用的设计模式
- 【LeetCode】404. Sum of Left Leaves
- 集合类源码简单阅读(一)(ArrayList)
- MYSQL数据库间同步数据
- 坐标系变换数学基础
- 服务器客户端
- web访问的原理
- centos7下redis莫名的链接不上
- 工厂模式
- GitHub管理代码操作方式
- 迷茫的5年