热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ArrayList底层实现原理

ArrayList的底层实现原理1,属性:privatestaticfinalintDEFAULT_CAPACITY10;privatestaticfinalObj

ArrayList的底层实现原理

1, 属性:
private static final int DEFAULT_CAPACITY = 10;private static final Object [] EMPTY_ELEMENTDATA = {};private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};transient Object [] elementData;private int size; // 动态数组的实际大小2,构造方法:public ArrayList(){this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}调用无参的构造方法,则会将elementData赋上为空的一个数组.public ArrayList(Collectionextends E> c){elementData = c.toArray();if(size = elementData.length != 0){if(elementData.getClass()!=Object[].class)elementData = Arrays.copyOf(elementData,size,Object[].class);}else{elementData = EMPTY_ELEMENTDATA;}
}调用有参的构造方法,参数是一个带范型的集合。生成一个可以不为空的集合。
如果参数使用toArray(),返回类型不是Object[],则使用copyOf() 复制下并赋值给elementData,
public ArrayList(int initialCapacity){if(initialCapacity > 0){this.elementData = new Object[initialCapacity];}else if(initialCapacicty == 0){this.elementData = EMPTY_ELEMENTDATA;}else{throw new IlleagalArgumentException("illagal initialCapacity"+initialCapcity);}
}调用有参的构造函数,初始化储存元素的容量。定义之后,内存会为开辟初始化容量大小的空间。
随着ArrayList 里面元素的增加直到initialCapacity,不需要数组向新数组的拷贝。Tips:
Arraylsit list
= new ArrayList(10);
默认的Object[] elementData 的长度为10;
list.size();的长度还是为0因为size 代表的逻辑长度,内存中实际存在的元素的长度。
3,add;public boolean add(E e){ensureCapacityInternal(size + 1);elementData[size++] = e;return true;
}
private void ensureCapacityInternal(int minCapacity){if(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA){minCapacity = Math.max(DEFAILT_CAPACITY,minCapacity);}ensureExplicitCapacity(minCapacity);
}向ArrayList 里面增添元素的时候,当ArrayList 的为空的时候,add元素时,如果没有设定Arraylist的Object elementData的长度,
会设定默认的Object[] elementData 的长度为10,所以在长度为10 之前能够避免在每添加一个新的元素时候,就要复制原来的元素的数组到新的数组的里面去。
private void ensureExplicitCapacity(int minCapacity){modCount &#43;&#43;;//extends from AbstactArrayListif(minCapacity - elementData.length > 0)grow(minCapacity);//长度不够&#xff0c;每次扩充1.5倍<粗略>

}
private void grow(int minCapacity){int oldCapacity &#61; elementData.length;int newCapacity &#61; oldCapacity &#43; (oldCapacity >> 1);if(newCapacity - minCapacity <0)newCapacity &#61; minCapacity;if(newCapacity - MAX_ARRAY_SIZE > 0)newCapacity &#61; hugeCapacity(minCapacity);//MAX_ARRAY_SIZE 2147483639
elementData &#61; Arrays.copyOf(elementData,newCapacity);//扩充了Obect elementData[]的长度
}private void hugeCapacity(int minCapacity){if(minCapacity <0)//因为minCapacity int 型&#xff0c;超过int 的最大值就会<0,就代表内存溢出throw new OutOfMemoryError();return(minCapacity > Max_ARRAY_SIZE)?Integer.MAX_VALUE:MAX_ARRAY_SIZE;
//最大上限就是Integer的最大值-8&#xff1b;
}4,add
public void add(int index,E element){rangeCheckForAdd(index);ensureCapacityInternal(size &#43; 1); //开辟空间System.arraycopy(elemntData,index,elementData,index &#43; 1,size - index);size &#43;&#43;;
}
private void rangeCheckForAdd(int index){if(index > size || index <0 ){throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}
}add(
int index,E elemenmt)中使用System.arraycopy的思想&#xff0c;是因为elementData的容器长度大于逻辑长度&#xff0c;即它本身的留有一个空位null,可用作填充数据。例&#xff1a;
Object [] elementData
&#61; {"one","two","three","four","five","null","null","null"};
要想在index为3的位置插入
"six",
System.arraycopy(elementData,
3,elementData,4,2);
elementData:源数组
3:源数组的起始位置
elementData:目标数组
4:目标数组的开始位置
2&#xff1a;size - index,size代表的是elementData中不为null的元素的长度所以&#xff0c;就可以将index &#43; 1 后半段的不为null 的元素复制到源数组的本身&#xff0c;同时将index 这个位置空出来,然后插入就可以实现add插入指定位置的功能。
elementData[index]
&#61; "six";
size
&#43;&#43;;Arrays.copyOf(),System.copyof()
system.arraycopy(Object src,
int srcPos,Object dest,destPos,length);native 方法&#xff0c;源码是由C&#43;&#43; 实现
Arrays.copyOf()&#xff0c;内部实现的也是System.arraycopy(),只是ArrayCopy()会创建一个新的数组&#xff0c;将源数组向新数组复制。
5,removepublic E remove(int index){rangeCheck(index);//先check下index有没有有越界modCount&#43;&#43;;//非安全线程
E oldValue &#61; elementData[index];int numMoved &#61; size - index - 1;if(numMoved > 0)System.arraycopy(elementData,index &#43; 1,elementData,numMoved);//如果numMoved &#61;&#61; 0 的情况也就是源数组只有一个元素的情况&#xff0c;就无需复制数组&#xff0c;只需执行elemnetData[--size]即elementData[0] &#61;nullelementData[--size] &#61; null;//将elementData 的空间变成nullreturn oldValue;
}
private void rangeCheck(int index){if(index >&#61; size){throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}
}从一定程度上来说&#xff0c;remove(
int index)的原理是和add(int index, E element)的逻辑是差不多的。6,remove
public boolean remove(Object o){if(o &#61;&#61; null){for(int index &#61; 0;index ){if(elementData[index]&#61;&#61;null){fastRemove(index);return true;}}}else{for(int index &#61; 0;index ){if(o.equals(elementData[index])){fastRemove(index);return true;}}}return false;
}
private void fastRemove(index){modCount&#43;&#43;;//非安全线程int numMoved &#61; size - index - 1;if(numMoved > 0)System.arraycopy(elementData,index &#43; 1,elementData,numMoved);elementData[--size] &#61; null;//将elementData 的空间变成null

}remove(Object o) 删除集合中匹配的元素
<最先匹配的元素>&#xff0c;其思路和remove(index)是一样的
remove(index)是直接告知index,remove(Obejct o)是先找到匹配的index,然后再进行和remove(index) 大致的操作。其中&#xff0c;remove(Obejct o)需考虑元素o 是否为null&#xff0c;关于两元素是否相等的比较方法
&#61;&#61; 和 equals
&#61;&#61; 在值类型中&#xff0c;就是比较值是否相等&#xff0c;但是在引用类型中&#xff0c;实际比较的是在内存中的地址是否相等
equals,是Obejct 中的方法&#xff0c;如下&#xff1a;
public boolean equals(Object o){return (this &#61;&#61; o);
}Object 是所有类的父类&#xff0c;Obejct 中的equals 方法就是
&#61;&#61;&#xff0c;是比较内存中的地址是否相等&#xff0c;
许多类会重写Obejct 中的equals方法&#xff0c;例如String 类&#xff0c;重写之后就是对字符串值进行比较在remove(Obejct o) 中的equals 方法实际比较的就是内存中地址的相等。但是如果对于对Object中equals 方法重写的类&#xff0c;
则实际比较的就是值是否相等。

 



转:https://www.cnblogs.com/pickKnow/p/9151463.html



推荐阅读
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 有没有一种方法可以在不继承UIAlertController的子类或不涉及UIAlertActions的情况下 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 如何用JNI技术调用Java接口以及提高Java性能的详解
    本文介绍了如何使用JNI技术调用Java接口,并详细解析了如何通过JNI技术提高Java的性能。同时还讨论了JNI调用Java的private方法、Java开发中使用JNI技术的情况以及使用Java的JNI技术调用C++时的运行效率问题。文章还介绍了JNIEnv类型的使用方法,包括创建Java对象、调用Java对象的方法、获取Java对象的属性等操作。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
  • C++语言入门:数组的基本知识和应用领域
    本文介绍了C++语言的基本知识和应用领域,包括C++语言与Python语言的区别、C++语言的结构化特点、关键字和控制语句的使用、运算符的种类和表达式的灵活性、各种数据类型的运算以及指针概念的引入。同时,还探讨了C++语言在代码效率方面的优势和与汇编语言的比较。对于想要学习C++语言的初学者来说,本文提供了一个简洁而全面的入门指南。 ... [详细]
  • 本文介绍了Cocos2dx学习笔记中的更新函数scheduleUpdate、进度计时器CCProgressTo和滚动视图CCScrollView的用法。详细介绍了scheduleUpdate函数的作用和使用方法,以及schedule函数的区别。同时,还提供了相关的代码示例。 ... [详细]
  • Mono为何能跨平台
    概念JIT编译(JITcompilation),运行时需要代码时,将Microsoft中间语言(MSIL)转换为机器码的编译。CLR(CommonLa ... [详细]
author-avatar
宁波南诚装饰_886
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有