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 ...
随机推荐
- 【测试设计】使用jenkins 插件Allure生成漂亮的自动化测试报告
前言 以前做自动化测试的时候一直用的HTMLTestRunner来生成测试报告,后来也尝试过用Python的PyH模块自己构建测试报告,在后来看到了RobotFramework的测试报告,感觉之前用的 ...
- 【源码学习之spark streaming 1.6.1 】
说明:个人原创,转载请说明出处 http://www.cnblogs.com/piaolingzxh/p/5634577.html 未完待续
- IDEAL葵花宝典:java代码开发规范插件 GenerateAllSetter、ECtranslation、translation、插件
前言: GenerateAllSetter: 我们在程序开发过程中,往往要编写这样的类:类的部分或者全部属性不希望让外部世界直接访问,而不用public字段修饰.这样,方法调用成了访问这些属性的唯一 ...
- Eclipse 常用快捷键和使用技巧
1.查看快捷键定义的地方 Window->Preferences->General->Keys. 2.更改启动页 在AndroidManifest.xml第一个activity标签项 ...
- Appium 自动化测试(6) -- 使用Appium操作YY语音例子
#!/usr/bin/env python # -*- coding: utf-8 -*- import os import unittest from appium import webdriver ...
- JS object(对象)的学习汇总
Object(对象)是在所有的编程语言中都十分重要的一个概念,对于事物我们可以把他们看作是一个对象,而每一个事物都有自己的表示的属性和对于某一信息作出的相应的操作.而这些东西就变成了事物的属性和方法. ...
- js enter键激发事件
document.onkeydown = function (e) { if (!e) e = window.event; if ((e.keyCode | ...
- 本地代码同步到github
1 设置 ssh 公钥信息 首先你要确保 github 账号设置了ssh 公钥信息.如果没有的话可以按照下面的方式设置: 前往 github 网站的 account settings, 依次点击 Se ...
- tf.device()指定tensorflow运行的GPU或CPU设备
在tensorflow中,我们可以使用 tf.device() 指定模型运行的具体设备,可以指定运行在GPU还是CUP上,以及哪块GPU上. 设置使用GPU 使用 tf.device('/gpu:1' ...
- Buildroot MariaDB替代MySQL
/********************************************************************************* * Buildroot Maria ...