it-auto; text-size-adjust: auto;font-size:16px;">List聚集源码剖析
it-auto; text-size-adjust: auto;font-size:16px;">1.数据结构特色
it-auto; text-size-adjust: auto;font-size:16px;">ArrayList底层数据构造是一个数组,查问元素速度快,增删速度稍慢
it-auto; text-size-adjust: auto;font-size:16px;">2.几个概念:
it-auto; text-size-adjust: auto;font-size:16px;">(1)DEFAULT_CAPACITY: 表现数组的初始大小,默认10
it-auto; text-size-adjust: auto;font-size:16px;">(2)size: 表示当前数组的大小
it-auto; text-size-adjust: auto;font-size:16px;">(3)modCount: 统计当前数组元素被修改的次数,只要修正,就+1
it-auto; text-size-adjust: auto;font-size:16px;">3.空参结构方式初始化
it-auto; text-size-adjust: auto;font-size:16px;">public ArrayList() {
it-auto; text-size-adjust: auto;font-size:16px;">//实际大小为{},长度为0的数组
it-auto; text-size-adjust: auto;font-size:16px;">this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">阐明: ArrayList无参构造方法初始化时,默认大小是空数组,并不是大家常说的10,
it-auto; text-size-adjust: auto;font-size:16px;">10是在第一次add的时候扩容的数组容量值
it-auto; text-size-adjust: auto;font-size:16px;">4,JSON格式化是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率.第一次添加元素扩容原理
it-auto; text-size-adjust: auto;font-size:16px;">java
it-auto; text-size-adjust: auto;font-size:16px;">public boolean add(E e) {
it-auto; text-size-adjust: auto;font-size:16px;">//确保数组大小是否足够,不够履行扩容,size为当前数组的大小
it-auto; text-size-adjust: auto;font-size:16px;">ensureCapacityInternal(size + 1); // Increments modCount!!
it-auto; text-size-adjust: auto;font-size:16px;">//直接把元素e保存到数组中
it-auto; text-size-adjust: auto;font-size:16px;">elementData[size++] = e;
it-auto; text-size-adjust: auto;font-size:16px;">return true;
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">java
it-auto; text-size-adjust: auto;font-size:16px;">private void ensureCapacityInternal(int minCapacity) {
it-auto; text-size-adjust: auto;font-size:16px;">ensureExplicitCapacity(calculateCapacity(elementData,不可逆JS加密随着互联网的快速发展,网站客户端(浏览器)IE(ff)运行的javaSCRIPT代码常常被别人轻易的拷贝, 为了保护程序员自己的劳动成果,因此程序员不得不对想办法保护自己源代码-------javascript加密, minCapacity));
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">private static int calculateCapacity(Object[] elementData, int minCapacity) {
it-auto; text-size-adjust: auto;font-size:16px;">//如果是空数组{}
it-auto; text-size-adjust: auto;font-size:16px;">if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
it-auto; text-size-adjust: auto;font-size:16px;">//在最小容量minCapacity和DEFAULT_CAPACITY(10)抉择一个较大的值
it-auto; text-size-adjust: auto;font-size:16px;">return Math.max(DEFAULT_CAPACITY, minCapacity);
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">return minCapacity;
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">private void ensureExplicitCapacity(int minCapacity) {
it-auto; text-size-adjust: auto;font-size:16px;">//记载修改次数
it-auto; text-size-adjust: auto;font-size:16px;">modCount++;
it-auto; text-size-adjust: auto;font-size:16px;">//如果咱们冀望的最小容量>数组目前的长度就扩容
it-auto; text-size-adjust: auto;font-size:16px;">if (minCapacity - elementData.length > 0)
it-auto; text-size-adjust: auto;font-size:16px;">grow(minCapacity);
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">private void grow(int minCapacity) {
it-auto; text-size-adjust: auto;font-size:16px;">// overflow-conscious code
it-auto; text-size-adjust: auto;font-size:16px;">int oldCapacity = elementData.length;
it-auto; text-size-adjust: auto;font-size:16px;">//oldCapacity >> 1: 是把oldCapacity/2的意思
it-auto; text-size-adjust: auto;font-size:16px;">int newCapacity = oldCapacity + (oldCapacity >> 1);
it-auto; text-size-adjust: auto;font-size:16px;">//如果扩容后的值<我们盼望的值,扩容后的值即是我们期冀的值
it-auto; text-size-adjust: auto;font-size:16px;">if (newCapacity - minCapacity < 0)
it-auto; text-size-adjust: auto;font-size:16px;">newCapacity = minCapacity;
it-auto; text-size-adjust: auto;font-size:16px;">//如果扩容后的值>jvm所能分配的数组的最大值,那么就用Integer的最大值
it-auto; text-size-adjust: auto;font-size:16px;">if (newCapacity - MAX_ARRAY_SIZE > 0)
it-auto; text-size-adjust: auto;font-size:16px;">newCapacity = hugeCapacity(minCapacity);
it-auto; text-size-adjust: auto;font-size:16px;">//通过复制数组扩容
it-auto; text-size-adjust: auto;font-size:16px;">elementData = Arrays.copyOf(elementData, newCapacity);
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">留神:
it-auto; text-size-adjust: auto;font-size:16px;">1.扩容的规矩并不是翻倍,是本来容量大小的1.5倍
it-auto; text-size-adjust: auto;font-size:16px;">2.ArrayList中数组的最大长度是Integer.MAX_VALUE,超过这个值,JVM就不会给数组调配内存空间了
it-auto; text-size-adjust: auto;font-size:16px;">3.新增元素时,并没有对值进行严厉的校验,所以ArrayList是容许null值的
it-auto; text-size-adjust: auto;font-size:16px;">LinkeList集合
it-auto; text-size-adjust: auto;font-size:16px;">1.数据结构特点:
it-auto; text-size-adjust: auto;font-size:16px;">LinkedList底层数据结构是一个双向链表,链表中的每个节点都可以查找前一个节点或者向后查找后一个节点
it-auto; text-size-adjust: auto;font-size:16px;">2.多少个概念:
it-auto; text-size-adjust: auto;font-size:16px;">(1)链表每个节点叫做Node,Node有prev属性,代表前一个节点的地址,next属性代表后一个节点的地址
it-auto; text-size-adjust: auto;font-size:16px;">(2)first是双向链表的头节点,它的前一个节点是null
it-auto; text-size-adjust: auto;font-size:16px;">(3)last是双向链表的尾节点,它的后一个节点是null
it-auto; text-size-adjust: auto;font-size:16px;">(4)链表中如果没有数据,first和last都null
it-auto; text-size-adjust: auto;font-size:16px;">(5)由于是双向链表,只有内存空间足够大,链表的大小是不限度的
it-auto; text-size-adjust: auto;font-size:16px;">3.链表中的元素(节点)叫做Node,是LinkedList集合的私有静态内部类,代码如下:
it-auto; text-size-adjust: auto;font-size:16px;">java
it-auto; text-size-adjust: auto;font-size:16px;">private static class Node<E> {
it-auto; text-size-adjust: auto;font-size:16px;">E item;//节点数据
it-auto; text-size-adjust: auto;font-size:16px;">Node<E> next;//下一个节点的地址
it-auto; text-size-adjust: auto;font-size:16px;">Node<E> prev;//前一个节点的地址
it-auto; text-size-adjust: auto;font-size:16px;">//初始化参数次序是: 前一个节点地址,节点自身的数据,后一个节点地址
it-auto; text-size-adjust: auto;font-size:16px;">Node(Node<E> prev, E element, Node<E> next) {
it-auto; text-size-adjust: auto;font-size:16px;">this.item = element;
it-auto; text-size-adjust: auto;font-size:16px;">this.next = next;
it-auto; text-size-adjust: auto;font-size:16px;">this.prev = prev;
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">4.add添加节点(从链表尾部添加)
it-auto; text-size-adjust: auto;font-size:16px;">java
it-auto; text-size-adjust: auto;font-size:16px;">public boolean add(E e) {
it-auto; text-size-adjust: auto;font-size:16px;">linkLast(e);
it-auto; text-size-adjust: auto;font-size:16px;">return true;//链表节点数据能够反复,所以add办法始终返回true
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">java
it-auto; text-size-adjust: auto;font-size:16px;">//从尾部添加节点
it-auto; text-size-adjust: auto;font-size:16px;">void linkLast(E e) {
it-auto; text-size-adjust: auto;font-size:16px;">//把尾节点地址存储在l中
it-auto; text-size-adjust: auto;font-size:16px;">final Node<E> l = last;
it-auto; text-size-adjust: auto;font-size:16px;">//创立新的节点,参数含意如下
it-auto; text-size-adjust: auto;font-size:16px;">//l是新节点的前一个节点的地址,当前值是尾节点地址值
it-auto; text-size-adjust: auto;font-size:16px;">//e是当前新增节点中保留的数据,当前新增节点的下一个节点是null,因为是在末尾添加
it-auto; text-size-adjust: auto;font-size:16px;">final Node<E> newNode = new Node<>(l, e, null);
it-auto; text-size-adjust: auto;font-size:16px;">//last指向新增节点(新增节点作为尾节点)
it-auto; text-size-adjust: auto;font-size:16px;">last = newNode;
it-auto; text-size-adjust: auto;font-size:16px;">//如果链表为空(第一次添加节点)(l是尾节点,尾节点为空,链表即空),头部跟尾部都是指向统一个节点,都是新建的节点
it-auto; text-size-adjust: auto;font-size:16px;">if (l == null)
it-auto; text-size-adjust: auto;font-size:16px;">first = newNode;
it-auto; text-size-adjust: auto;font-size:16px;">else
it-auto; text-size-adjust: auto;font-size:16px;">//链表不是空(非第一次增加节点),把增添新节点之前的尾节点的下一个节点指向新添加的节点
it-auto; text-size-adjust: auto;font-size:16px;">l.next = newNode,Base64编码/解码是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范;
it-auto; text-size-adjust: auto;font-size:16px;">//节点数+1
it-auto; text-size-adjust: auto;font-size:16px;">size++;
it-auto; text-size-adjust: auto;font-size:16px;">//链表的实际修改次数+1
it-auto; text-size-adjust: auto;font-size:16px;">modCount++;
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">5.get(int index)查询节点
it-auto; text-size-adjust: auto;font-size:16px;">java
it-auto; text-size-adjust: auto;font-size:16px;">public E get(int index) {
it-auto; text-size-adjust: auto;font-size:16px;">checkElementIndex(index);//检讨索引值是否越界
it-auto; text-size-adjust: auto;font-size:16px;">return node(index).item;
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">private void checkElementIndex(int index) {
it-auto; text-size-adjust: auto;font-size:16px;">if (!isElementIndex(index))
it-auto; text-size-adjust: auto;font-size:16px;">throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">private boolean isElementIndex(int index) {
it-auto; text-size-adjust: auto;font-size:16px;">return index >= 0 && index < size;
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">中心根据索引获取节点数据的方法
it-auto; text-size-adjust: auto;font-size:16px;">链表查询某个节点是比拟慢的,须要挨个查找才可以
it-auto; text-size-adjust: auto;font-size:16px;">java
it-auto; text-size-adjust: auto;font-size:16px;">依据链表索引地位查询元素
it-auto; text-size-adjust: auto;font-size:16px;">Node<E> node(int index) {
it-auto; text-size-adjust: auto;font-size:16px;">//如果index处于链表的前半部分,从头开始查,size>>1 是 size/2的意思
it-auto; text-size-adjust: auto;font-size:16px;">if (index < (size >> 1)) {
it-auto; text-size-adjust: auto;font-size:16px;">Node<E> x = first;
it-auto; text-size-adjust: auto;font-size:16px;">//晓得for轮回到index的前一个node结束
it-auto; text-size-adjust: auto;font-size:16px;">for (int i = 0; i < index; i++)
it-auto; text-size-adjust: auto;font-size:16px;">x = x.next;
it-auto; text-size-adjust: auto;font-size:16px;">return x;
it-auto; text-size-adjust: auto;font-size:16px;">} else {
it-auto; text-size-adjust: auto;font-size:16px;">//如果index处于链表的后半部门,从尾开始查
it-auto; text-size-adjust: auto;font-size:16px;">Node<E> x = last;
it-auto; text-size-adjust: auto;font-size:16px;">//知道for循环到index的后一个node停滞
it-auto; text-size-adjust: auto;font-size:16px;">for (int i = size - 1; i > index; i--)
it-auto; text-size-adjust: auto;font-size:16px;">x = x.prev;
it-auto; text-size-adjust: auto;font-size:16px;">return x;
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">}
it-auto; text-size-adjust: auto;font-size:16px;">从源码中发明,LinkedList并没有采取从头循环到尾的做法,而是采用了简略二分查找法,
it-auto; text-size-adjust: auto;font-size:16px;">首先看index是在链表的左半部分仍是右半部分.如果是在左半部分,就从左侧开始找,
it-auto; text-size-adjust: auto;font-size:16px;">假如切实链表的有伴局部,就从右侧开端找.这种方法,循环的次数至少下降了一半,进步查询机能.