ArrayList实现
数组实现
父类:AbstractList
接口:List,RandomAccess,Cloneable,Serializable
字段:
//默认容量
private static final int DEFAULT_CAPACITY = 10;
//空的数组,构造函数参数为0和trim中使用,构造参数给0的人绝对会被打死,每放一个元素,就要重新copy一次
private static final Object[] EMPTY_ELEMENTDATA = {}; //实际保存数组,transient,这个字段不用写入流
transient Object[] elementData
//实际元素数目
private int size;
public ArrayList(int initialCapacity)
{
if (initialCapacity > 0)
{
this.elementData = new Object[initialCapacity];
}
else if (initialCapacity == 0)
{
//注意初始容量为0时给的对象,EMPTY_ELEMENTDATA
this.elementData = EMPTY_ELEMENTDATA;
}
else
{
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
} public ArrayList()
{
//默认构造函数
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
} public ArrayList(Collection<? extends E> c)
{
//转入的集合转换为数组
elementData = c.toArray();
//改变自己的size
if ((size = elementData.length) != 0)
{
//这里有个坑,可能不能正确的返回Object[] Class对象,不能的话复制
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else
{
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
} //截断,在原数组上移动
public void trimToSize()
{
modCount++;
if (size < elementData.length)
{
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
} //比较关心的几个方法,存放,取出,查找
//查找,运行时间上界O(n),从这里也可用看出是允许放null
public int indexOf(Object o)
{
if (o == null)
{
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else
{
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
} //反向查找
public int lastIndexOf(Object o)
{
if (o == null)
{
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else
{
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
//返回index位置的元素
E elementData(int index)
{
return (E) elementData[index];
} //获取对应位置元素,O(1)
public E get(int index)
{
//检查size,并没有判断小于0
rangeCheck(index);
return elementData(index);
} //将元素放在对应位置,index<size,list当成数组使用,注意,这样的代码会报错
//List<String> list = new ArrayList<>(100);
// list.set(10, "123");
//根据构造函数可以知道,已经开辟了100长度的数组,但是就是不让你用
public E set(int index, E element)
{
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
} private void grow(int minCapacity)
{
// overflow-conscious code
int oldCapacity = elementData.length;
//原来的1.5备长度
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
elementData = Arrays.copyOf(elementData, newCapacity);
} private void ensureExplicitCapacity(int minCapacity)
{
modCount++; // overflow-conscious code
//1-0,进入if,进行内存复制,开辟新的数组
if (minCapacity - elementData.length > 0)
grow(minCapacity);
} private void ensureCapacityInternal(int minCapacity)
{
//构造函数给0,这里是false
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
{
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
} //ensureExplicitCapacity(1);
ensureExplicitCapacity(minCapacity);
} //增加一个元素
public boolean add(E e)
{
//为什么构造函数给0会被打死,看下面这个函数,一来就要新数组,新的数组长度也只有1
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
} //元素放到index位置,0<=index<size
public void add(int index, E element)
{
rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
//移除
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;
}
//O(n)的移除,注意在fastRemove方法里面也会出现内存复制
public boolean remove(Object o)
{
if (o == null)
{
for (int index = 0; index < size; index++)
if (elementData[index] == null)
{
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
} //为什么elementData不用置null,方便重用
public void clear()
{
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
} //浅克隆
public Object clone()
{
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
} //返回副本
public Object[] toArray()
{
return Arrays.copyOf(elementData, size);
} 结尾附上一个内存分布的代码,有指针真好
int main(int argc, char* argv[])
{
//int ba[4];
int a[] = { 1, 2, 3, 4 };
int c = 5;
int d = 6;
int dd = 7;
cout << a << endl;
cout << a[-1] << endl;
cout << a-1 << endl;
cout<<&dd<<endl;
cout << &d << endl;
cout << &c << endl;
//memcpy(ba, a, sizeof(int) * 4);
//cout << ba[0] << endl;
//cout << ba[1] << endl;
return 0;
}
ArrayList实现的更多相关文章
- 计算机程序的思维逻辑 (38) - 剖析ArrayList
从本节开始,我们探讨Java中的容器类,所谓容器,顾名思义就是容纳其他数据的,计算机课程中有一门课叫数据结构,可以粗略对应于Java中的容器类,我们不会介绍所有数据结构的内容,但会介绍Java中的主要 ...
- 分享个 之前写好的 android 文件流缓存类,专门处理 ArrayList、bean。
转载麻烦声明出处:http://www.cnblogs.com/linguanh/ 目录: 1,前序 2,作用 3,特点 4,代码 1,前序 在开发过程中,client 和 server 数据交流一 ...
- 深入理解java中的ArrayList和LinkedList
杂谈最基本数据结构--"线性表": 表结构是一种最基本的数据结构,最常见的实现是数组,几乎在每个程序每一种开发语言中都提供了数组这个顺序存储的线性表结构实现. 什么是线性表? 由0 ...
- 【干货】用大白话聊聊JavaSE — ArrayList 深入剖析和Java基础知识详解(二)
在上一节中,我们简单阐述了Java的一些基础知识,比如多态,接口的实现等. 然后,演示了ArrayList的几个基本方法. ArrayList是一个集合框架,它的底层其实就是一个数组,这一点,官方文档 ...
- WebAPI接口返回ArrayList包含Dictionary对象正确解析
一.问题提出 为了减少流量,将key-value(键值对)直接输出到Dictionary<string, string>,接口返回结果如下: 其中{}里面内容如下: 上图显示600是键,4 ...
- ArrayList LinkedList源码解析
在java中,集合这一数据结构应用广泛,应用最多的莫过于List接口下面的ArrayList和LinkedList; 我们先说List, public interface List<E> ...
- ArrayList、Vector、LinkedList的区别联系?
1.ArrayList.Vector.LinkedList类都是java.util包中,均为可伸缩数组. 2.ArrayList和Vector底层都是数组实现的,所以,索引数据快,删除.插入数据慢. ...
- ArrayList、Vector、HashMap、HashSet的默认初始容量、加载因子、扩容增量
当底层实现涉及到扩容时,容器或重新分配一段更大的连续内存(如果是离散分配则不需要重新分配,离散分配都是插入新元素时动态分配内存),要将容器原来的数据全部复制到新的内存上,这无疑使效率大大降低. 加载因 ...
- Java中Vector和ArrayList的区别
首先看这两类都实现List接口,而List接口一共有三个实现类,分别是ArrayList.Vector和LinkedList.List用于存放多个元素,能够维护元素的次序,并且允许元素的重复.3个具体 ...
- C#语言基础——集合(ArrayList集合)
集合及特殊集合 集合的基本信息: System.Collections 命名空间包含接口和类,这些接口和类定义各种对象(如列表.队列.位数组.哈希表和字典)的集合.System.Collections ...
随机推荐
- 查找一个Class到底在那一个jar文件里
整理自己的一些笔记,发觉这个命令 ,看起来是用来找一个Class到底在那一个jar文件里的. 虽然没有再测一下,估计是好使的. 先在博客园里记下来,防止自己忘掉. findstr /S /M org. ...
- Android------视频播放器(包含全屏播放,快退,快进,腾讯新闻的列表播放等)
前段时间做了一个新闻APP,涉及到了列表视频播放,和腾讯新闻APP差不多,总结了一下代码,写了一个Demo来分享给大家. 用了 TabLayout+RecylerView+自定义视频控件 完成的 ...
- python爬虫脚本下载YouTube视频
python爬虫脚本下载YouTube视频 爬虫 python YouTube视频 工作环境: python 2.7.13 pip lxml, 安装 pip install lxml,主要用xpath ...
- 【hive】数据仓库层次设计
转载 https://www.jianshu.com/p/849db358ec61
- android中string.xml中%一$s、%1$d等的用法
%n$ms:代表输出的是字符串,n代表是第几个参数,设置m的值可以在输出之前放置空格 %n$md:代表输出的是整数,n代表是第几个参数,设置m的值可以在输出之前放置空格,也可以设为0m,在输出之前放置 ...
- 基于 React + NodeJS + Express + MongoDB 开发的一个社区系统
还可以, 功能挺全的, 可以作为react开发入门项目 链接 线上站点: 源码地址:
- python将字符转换为字典
参考文章Python 如何将字符串转为字典 注意: 使用json的时候一定要注意是loads而不是load 即:user_dict = json.loads(user_info) 注意: 用eval( ...
- 未能加载文件或程序集“NPOI”或它的某一个依赖项
自己遇到过得一个很麻瓜很耽误时间的bug,也请教了一些大神嫩是没找到解决方法 下面分享下问题和解决方法 做的是一个下载功能,本地是没问题IIS站点导出EXCEL的时候出错 我这边看不到错误信息,只能一 ...
- c# 添加注册表
- 【idea】如何安装jetty容器,并使用。
参考:https://www.jetbrains.com/idea/help/run-debug-configuration-jetty-server.html背景:web开发当中,我觉得服务层的代码 ...