Java ArrayList的模拟实现
package test; import java.util.Arrays;
import java.util.Collection; public class MyArrayList<E> { //存储数据
private Object[] values; //已经使用的容量
private int size; //修改次数
private int modCount; /**
* 根据给定容量初始化
* @param initialCapacity
*/
public MyArrayList(int initialCapacity){
if(initialCapacity > ){//按照给定的容量大小初始化数组
values = new Object[initialCapacity];
}else if(initialCapacity == ){
values = new Object[]{};
}else{
throw new IllegalArgumentException("非法初始化容量: "+
initialCapacity);
} } /**
* 默认初始化方法
*/
public MyArrayList(){
this();
} /**
* 用集合初始化一个ArrayList
* @param c
*/
public MyArrayList(Collection c){
values = c.toArray();
if (values.length != ) {
size = values.length;
if (values.getClass() != Object[].class)
values = Arrays.copyOf(values, size, Object[].class);
}else{
values = new Object[]{};
}
}
/**
* 检查是否数组越界了
* @param index
*/
private void rangeCheck(int index) {
if (index >= size || index < )
throw new IndexOutOfBoundsException("数组越界了");
} /**
* 替换原数组中的值,并且将原值返回
* @param index
* @param element
* @return
*/
public E set(int index,E element){
//检查是否越界
rangeCheck(index); E oldValue = (E)values[index];
values[index] = element; return oldValue;
} /**
* 在数组的末尾增加一个元素
* @param element
*/
public void add(E element){
//扩容
ensureCapacity(size+);
values[size++] = element; } /**
* @param index
* @param element
*/
public void add(int index,E element){
//先检查数组的下标是否越界了
rangeCheck(index);
//扩容
ensureCapacity(size+); Object[] oldValues = values;
values[index] = element; //将原数组index后的值拷贝带新数组中
System.arraycopy(oldValues, index, values, index+, size-index); size++; } /**
* 将一个collection中的元素添加到数组末尾
* @param c
*/
public void addAll(Collection c){
Object[] cArray = c.toArray(); //扩容
ensureCapacity(size+cArray.length); //将传入数据拷贝到数组末尾
System.arraycopy(cArray, , values, size, cArray.length); size += cArray.length;
} /**
* 将一个collection中的元素添加到数组的指定位置
* @param index
* @param c
*/
public void addAll(int index,Collection c){
//先检查数组的下标是否越界了
rangeCheck(index);
//扩容
Object[] cArray = c.toArray();
int cLength = cArray.length; ensureCapacity(size+cLength); Object[] oldValues = values;
//将传入数据拷贝到数组指定位置
System.arraycopy(cArray, , values, index, cLength); //将原数组中index以后的数据拷贝过来
System.arraycopy(oldValues, index, values, values.length-, size-index); size += cLength; } /**
* 根据下标获取元素
* @param index
* @return
*/
public E get(int index){
//先检查数组的下标是否越界了
rangeCheck(index); E e = (E) values[index]; return e; } /**
* 根据下标删除元素
* @param index
* @return
*/
public E remove(int index){
//先检查数组的下标是否越界了
rangeCheck(index); E removeValue = (E) values[index]; System.arraycopy(values, index+, values, index, size-index-); //置为空,gc回收
values[size--] = null; return removeValue; } /**
* 根据对象删除
* @param o
*/
public void remove(Object o){
//考虑元素为null的情况
if(null == o){
for (int i = ; i < size; i++) {
if(values[i] == null){
remove(i);
}
} }else{
for (int i = ; i < size; i++) {
if(values[i].equals(o)){
remove(i);
}
} }
} /**
* 扩容方法,保证数组的长度足够
* @param minCapacity
*/
public void ensureCapacity(int minCapacity){
modCount++; int oldCapacity = values.length;
if (minCapacity > oldCapacity) {
//先默认扩容50%+1,如果还是不能满足,则直接用传入的所需容量
int newCapacity = (oldCapacity*)/+;
if(newCapacity < minCapacity){
newCapacity = minCapacity;
} values = Arrays.copyOf(values, newCapacity); }
} public int size(){
return size;
} }
最后再介绍一下ensureCapacity这个方法的想法(从网上看到的):
我们知道ArrayList的内部是采用数组来存储元素的,由于java数组都是定长的,所以这个数组的大小一定是固定的,这个大小就是capacity。我们可以肯定capacity一定是大于或等于ArrayList的size,那么当size不断增加到了要超过capacity的时候,ArrayList就不得不重新创建新的capacity来容纳更多的元素,这时需要首先建立一个更长的数组,将原来的数组中的元素复制到新数组中,再删除原来的数组。可见当ArrayList越来越大时,这种操作的消耗也是越来越大的。
为了减少这种不必要的重建capacity的操作,当我们能肯定ArrayList大致有多大(或者至少会有多大)时,我们可以先让ArrayList把capacity设为我们期望的大小,以避免多余的数组重建。
假设ArrayList自动把capacity设为10,每次重建时将长度递增原来的三分之二,那么当我们需要大约存储50个元素到ArrayList中时,就会大约需要重建数组4次,分别是在增加第11、第17、第26、第39个元素的时候进行的。如果我们一开始就让ArrayList的capacity为50,那么不需要任何数组重建就能完成所有插入操作了。
java允许我们在构造ArrayList的同时指定capacity,如new ArrayList(50),也允许在以后将它设得更大,而增大capacity就是使用ensureCapacity()方法。注意:capacity只能比原来的更大,而不能比原来的更小,否则java会忽略该操作。ArrayList的初始默认capacity为10,所以给capacity指定小于10的整数是毫无意义的。
最后说说ArrayList的size,前面说过,size一定小于等于capactiy,而且更重要的是,访问超过size的位置将抛出异常,尽管这个位置可能没有超过capacity。ensureCapacity()只可能增加capacity,而不会对size有任何影响。要增加size,只能用add()方法。
Java ArrayList的模拟实现的更多相关文章
- Mockito:一个强大的用于Java开发的模拟测试框架
https://blog.csdn.net/zhoudaxia/article/details/33056093 介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用 ...
- java.net.URL 模拟用户登录网页并维持session
java.net.URL 模拟用户登录网页并维持session 半成品,并非完全有用 import java.io.BufferedReader; import java.io.InputStream ...
- Java ArrayList、Vector和LinkedList等的差别与用法(转)
Java ArrayList.Vector和LinkedList等的差别与用法(转) ArrayList 和Vector是采取数组体式格式存储数据,此数组元素数大于实际存储的数据以便增长和插入元素,都 ...
- 浅析 java ArrayList
浅析 java ArrayList 简介 容器是java提供的一些列的数据结构,也可以叫语法糖.容器就是用来装在其他类型数据的数据结构. ArrayList是数组列表所以他继承了数组的优缺点.同时他也 ...
- java.net.URL 模拟用户登录网页并维持session【转】
java.net.URL 模拟用户登录网页并维持session 半成品,并非完全有用 import java.io.BufferedReader; import java.io.InputStream ...
- Java ArrayList中对象的排序 (Comparable VS Comparator)
我们通常使用Collections.sort()方法来对一个简单的数据列表排序.但是当ArrayList是由自定义对象组成的,就需要使用comparable或者comparator接口了.在使用这两者 ...
- Java ArrayList源码剖析
转自: Java ArrayList源码剖析 总体介绍 ArrayList实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现.除该类未实现同步外 ...
- Java ArrayList 源代码分析
Java ArrayList 之前曾经参考 数据结构与算法这本书写过ArrayList的demo,本来以为实现起来都差不多,今天抽空看了下jdk中的ArrayList的实现,差距还是很大啊 首先看一下 ...
- Java ArrayList trimToSize()
前几天看了Java ArrayList,没有明白trimToSize()这个方法是什么意思,所以看了一下源码并且debug一下自己的一个例子,明白了其中的含义.贴在这里. ArrayList al = ...
随机推荐
- python的一致性(1)sorted和len
每个语言,都有自己的特性,而一致性,是python语言特性重要的一个环节. 比如排序,我们不是aaa.sort(),而是 sorted(aaa),比如len,不是aaa.length(),而是len( ...
- python multiprocessing多进程模块
原文:https://blog.csdn.net/CityzenOldwang/article/details/78584175 多进程 Multiprocessing 模块 multiprocess ...
- 阿里云linux下修改mysql默认密码(xampp环境)- 原创
1.修改MySQL的登录设置: # vi /etc/my.cnf 在[mysqld]的段中加上一句:skip-grant-tables 例如: [mysqld] datadir=/var/lib/my ...
- Laravel使用Carbon人性化显示时间
1.下载Carbon composer require nesbot/carbon Laravel自带Carbon包,可以直接使用 use Carbon\Carbon; 2.如果数据库存的是日期格式, ...
- php判断检测一个数组里有没有重复的值
php判断检测一个数组里有没有重复的值 php里有一个处理数组重复值得函数array_unique,我们的思路就是用这个函数来实现的. if (count($array) != count(array ...
- Macaca 自动化录制工具uirecorder使用入门
Q&A PC端执行用例前,一定要运行selenium-standalone start,否则会出现这个问题:https://github.com/alibaba/uirecorder/issu ...
- POJ 3264 Balanced Lineup 【线段树/区间最值差】
Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 62103 Accepted: 29005 Cas ...
- XSS && CRLF && property&attribute
XSS cross-site scripting 跨站点脚本,为了避免与css冲突,命名为XSS.它是将恶意代码作为一个网页内容,这些恶意代码会注入到用户的浏览器中并执行,从而使用户受到攻击,常见的有 ...
- RPD Volume 168 Issue 4 March 2016 评论2
Influence of the phantom shape (slab, cylinder or Alderson) on the performance of an Hp(3) eye dosem ...
- python url拼接
import datetime,requests import json,time,urllib import hashlib self.url_domain = “www.baidu,com/” u ...