前言:工作将近4年,自认为基础还算可以,实际工作中用到的技术比较广泛,常用框架也有所了解,数据库原理、优化也花时间啃过,分布式hadoop、zookeeper有些了解,mongodb也玩过,但是总感觉无论做什么都没有办法做深做透。而工作了4年,5年的时候应该对自己的将来有个定位,是走业务专家路线还是走架构师路线,经过长期的思考抉择,最终定位在技术上。再分析自己做技术也没有什么优势,年龄倒是一年一年增长,在技术上没有什么特长,这一点是很要命的,没有一技之长很快就会被淘汰。于是,夯实基础成为了上半年计划的重中之重,紧接着数据结构、算法就提上了日程。
现在手头上有本大学教材《数据结构——c语言描述》,而我又打算把c/c++再看一遍,即使有6,7年没有接触过c语言了,我想它也不会成为拦路之虎。而实际用的还是java语言,所以看看jdk是如何实现数据结构的成了顺理成章的事。
进入正题,先从最简单易懂的线性表顺序存储开始。首先来看一下顺序表的存储结构,有图有真相。
c语言描述如下:
#define MAXSIZE=50
typedef struct
{
ElemType elem[MAXSIZE];
int last;
} SeqList;
结构比较简单。下面,再来看看jdk是如何实现的。
属性的定义:
private transient Object[] elementData;
private int size;
和c语言是如此相似,呵呵,不过细心的童鞋可能看到了,为何elementData要用transient来修饰了呢,它表示不需要序列化啊?法无定法,随心即法,对此不了解又想了解的可以看看我的另一篇文章——ArrayList源码分析——如何实现Serializable,地址:http://java-road-126-com.iteye.com/admin/blogs/1463313。
回归正题,接着聊方法。
1.初始化,
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
//默认是elementData的长度是10,注意此时size是0
public ArrayList() {
this(10);
}
2.查找,分为按序号查找和按内容查找。
//按序号查找
public E get(int index) {
RangeCheck(index);
return (E) elementData[index];
}
//越界会抛出runtime exception
private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
}
//按内容查找
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public int indexOf(Object o) {
// o为null也会判断是否elementData有为null的值,
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;
}
3.插入,分为在末尾插入和在中间插入
//末尾插入 ,也可以用调用add重载方法实现,你想到了吧!当然,这个性能是要快的,什么?你想知道为什么,自己想去。
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
/**
*数组在越界时,增加长度,每次增加原来的1/2 + 1, 为什么加1的原因,我想是因为oldCapacity=1时,(oldCapacity * 3)/2 =1 的原因
**/
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
//该方法是public,所以有这样的判断,可能用户希望更大的数组,不是吗?
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
//中间插入
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
ensureCapacity(size+1); // Increments modCount!!
//System.arraycopy 是native方法,传说比for循环数组要快,我想不仅仅是传说吧,可以验证的!:-D
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
4.删除,分为按序号删除和按内容删除,按范围删除
//按序号删除
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
//按内容删除
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;
}
//fastRemove比remove少了个RangeCheck校验,是要稍快写的
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
由于替换等操作比较简单,就不做介绍了,从各个方法的实现方式可以看到,ArrayList擅长于随机访问,对于在中间插入元素,则代价是比较高的,等分析完LinkedList后,会做一个性能比较。
各位看官,注意到了没有,对elementData改变的方法都用到了modCount++,你觉得是用来搞么事的呢?
不急,等我写结合JDK学习设计模式时再分析,什么?你说很急,现在就想知道,ok,提醒你一句,在iterator里会用到的,据说next()的时候,并发又有对ArrayList的更改操作,于是乎就读脏数据了,所以抛出了运行时异常。
你也不知道并发是搞么事,哎,事情有多了。好,等我写结合JDK学习并发时再分析。这回你不自己学TIJ真得等了,我连提醒都不提醒你了,因为,大周末的,我要搞别的事了。
- 大小: 15.7 KB
分享到:
相关推荐
这份"Java JDK 6学习笔记——ppt简体版"提供了关于这个关键版本的详细教程,适合初学者和有一定经验的开发者来深入理解Java编程。 首先,我们要了解Java JDK是什么。Java Development Kit,简称JDK,是Oracle公司...
总的来说,“Java JDK 6学习笔记——ppt简体版”全面介绍了Java编程语言的基础知识和JDK 6的关键特性,结合配套的代码示例,是系统学习和掌握Java开发的宝贵资料。无论你是Java初学者还是寻求提升的老手,都能从中...
Java JDK 6学习笔记——ppt简体版 第20章.ppt
Java JDK 6学习笔记——ppt简体版 第19章.ppt
Java JDK 6学习笔记——ppt简体版 第18章.ppt
Java JDK 6学习笔记——PPT简体版是针对初学者和有经验的开发者们的一份宝贵资源,它深入浅出地介绍了Java编程语言的核心概念和技术。这份笔记以PPT的形式呈现,使得学习过程更加直观易懂,适合课堂教学或自我学习。...
Java数据结构 线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构
Java JDK 6学习笔记——PPT简体版是针对初学者和有经验的开发者们的一份宝贵资源,它深入浅出地介绍了Java编程语言的核心概念和技术。这份资料以PPT的形式呈现,使得学习过程更加直观易懂,同时包含了课程中的源代码...
**JDK 6学习笔记——PPT简体版** Java Development Kit(JDK)是Java编程语言的核心组件,它提供了开发和运行Java应用程序所需的工具和环境。JDK 6是Oracle公司发布的一个重要版本,为开发者带来了许多改进和新特性...
Linux安装JDK指南 ...* JDK的安装目录结构 * JDK的环境变量配置 八、结语 本文指导了读者如何在Linux系统上安装JDK,从解压缩JDK安装包到检测JDK安装的每一步骤。本文适合初学者和经验丰富的开发者和系统管理员。
11. **并发编程改进**:引入了java.util.concurrent包,提供了线程安全的数据结构和并发工具类,如ExecutorService、Semaphore等,使得多线程编程更加高效和易用。 12. **NIO(非阻塞I/O)**:Java 5.0引入了NIO...
Stream是JDK8为了更好地支持函数式编程引入的一个数据处理管道,它允许你以声明方式处理数据集,并可以进行并行处理。 Stream的创建可以基于集合(如List、Set等)、数组和特定的IO资源(如Files)。 例如,在内容...