自己实现ArrayList
思路:
一 载体
ArrayList是一个集合容器,必然要有一个保存数据的载体。
public class MyArraylist {
private final static int INIT_COUNT = 10;
Object[] arrays;
public MyArraylist() {
this(INIT_COUNT);
}
public MyArraylist(int count) {
arrays = new Object[count];
}
}
二属性
长度
得到集合会初始化一个数组长度,集合的元素个数不能是数组长度。
public class MyArraylist2 {
private int size;
public int size(){
return size;
}
}
三方法
增删改查
增加
按默认索引加入元素,按索引加入元素,加入单个元素,加入批量元素。这里只举按单个加入元素的例子。
首先需要判断索引是否非法
public void checkIndexRange(int index) {
if (index > size) {
throw new IndexOutOfBoundsException("数组越界");
}
}
public void checkIndexRangeForAdd(int index) {
if (index > size || index < 0) {
throw new IndexOutOfBoundsException("数组越界");
}
}
判断当前数组是否需要扩容。如果索引大于当前数组长度,按当前长度的50%增加。并将当前数组复制到新的数组。
public void checkIndex(int index) {
if (index > arrays.length) {
int oldLength = size;
int newLength = oldLength + (index >> 1);
arrays = Arrays.copyOf(arrays, newLength);
}
}
增加单个元素
public void add(Object obj, int index) {
checkIndexRangeForAdd(index);//判断索引是否非法
checkIndex(size + 1);//判断数组是否需要扩容
System.arraycopy(arrays, index, arrays, index + 1, size - index);
arrays[index] = obj;
size++;
}
public boolean add(Object obj) {
checkIndex(size + 1);//判断数组是否需要扩容
arrays[size++] = obj;
return true;
}
获取元素
public T get(int index) {
checkIndexRangeForAdd(index);
return (T) arrays[index];
}
更新元素
public T set(Object obj, int index) {
checkIndexRange(index);
T t = (T) arrays[index];
arrays[index] = obj;
return t;
}
删除元素
public T remove(int index) {
checkIndexRange(index);
T t = (T) arrays[index];
int moveLength = size - index - 1;
if (moveLength > 0) {
System.arraycopy(arrays, index + 1, arrays, index, moveLength);
}
arrays[--size] = null;
return t;
}
四迭代
使用增强型for循环迭代输出,以及Java 8引进的lambda表达式实现foreach。
首先生成一个迭代器。
private class MyArrayListIterator implements Iterator<T> {
private int count;
public boolean hasNext() {
return count != size;
}
public T next() {
checkModcount();
return (T) arrays[count++];
}
}
然后继承Iterable接口。
public class MyArraylist2<T> implements Iterable<T>{
@Override
public Iterator<T> iterator() {
return new MyArrayListIterator();
}
}
五线程安全问题
ArrayList没有实现线程安全,但是在迭代的时候,不允许修改。
ArrayList使用一个成员变量modCount在迭代开始的时候记录ArrayList正在做修改(增加,修改,删除)的数量,然后在每迭代一行的时候,去比较modCount是否发生变化。如果发生变化,证明此刻有其它的线程或者就是本线程就对它进行修改,然后抛出异常。
定义modcount变量。
private transient int modcount;
在增加,修改,删除的时候,均需将此值加1。
public boolean add(Object obj) {
checkIndex(size + 1);
modcount++;//加1
arrays[size++] = obj;
return true;
}
public void checkIndex(int index) {
if (index > arrays.length) {
modcount++;//加1
int oldLength = size;
int newLength = oldLength + (index >> 1);
arrays = Arrays.copyOf(arrays, newLength);
}
}
public T set(Object obj, int index) {
checkIndexRange(index);
modcount++;//加1
T t = (T) arrays[index];
arrays[index] = obj;
return t;
}
public T remove(int index) {
checkIndexRange(index);
modcount++;//加1
@SuppressWarnings("unchecked")
T t = (T) arrays[index];
int moveLength = size - index - 1;
if (moveLength > 0) {
System.arraycopy(arrays, index + 1, arrays, index, moveLength);
}
arrays[--size] = null;
return t;
}
在迭代的时候,将此值赋给另一个变量exceptCount。然后再每迭代一行的时候,将exceptCount与modcount比较。
private class MyArrayListIterator implements Iterator<T> {
private int exceptCount = modcount;
public void checkModcount() {
if (exceptCount != modcount) {
throw new ConcurrentModificationException();
}
}
}
最后实现的全部代码
package com.skycomm.sdf; import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Iterator; public class MyArraylist<T> implements Iterable<T> { private final static int INIT_COUNT = 10; private int size = 0; private transient int modcount; Object[] arrays; public MyArraylist() {
this(INIT_COUNT);
} public MyArraylist(int count) {
arrays = new Object[count];
} public void add(Object obj, int index) {
checkIndexRangeForAdd(index);
checkIndex(size + 1);
System.arraycopy(arrays, index, arrays, index + 1, size - index);
arrays[index] = obj;
size++;
} public boolean add(Object obj) {
checkIndex(size + 1);
modcount++;//加1
arrays[size++] = obj;
return true;
} public void checkIndex(int index) {
if (index > arrays.length) {
modcount++;//加1
int oldLength = size;
int newLength = oldLength + (index >> 1);
arrays = Arrays.copyOf(arrays, newLength);
}
} public T get(int index) {
checkIndexRangeForAdd(index);
return (T) arrays[index];
} public T remove(int index) {
checkIndexRange(index);
modcount++;//加1 @SuppressWarnings("unchecked")
T t = (T) arrays[index];
int moveLength = size - index - 1;
if (moveLength > 0) {
System.arraycopy(arrays, index + 1, arrays, index, moveLength);
}
arrays[--size] = null;
return t;
} public T set(Object obj, int index) {
checkIndexRange(index);
modcount++;//加1
T t = (T) arrays[index];
arrays[index] = obj;
return t;
} public void checkIndexRange(int index) {
if (index > size) {
throw new IndexOutOfBoundsException("数组越界");
}
} public void checkIndexRangeForAdd(int index) {
if (index > size || index < 0) {
throw new IndexOutOfBoundsException("数组越界");
}
} public int size() {
return size;
} public boolean isEmpty() {
return size == 0;
} public String toString() {
Iterator<T> it = iterator();
if (!it.hasNext())
return "[]"; StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
T e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (!it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
} public Iterator<T> iterator() {
return new MyArrayListIterator();
} private class MyArrayListIterator implements Iterator<T> { private int count; private int exceptCount = modcount; public boolean hasNext() {
return count != size;
} public T next() {
checkModcount();
return (T) arrays[count++];
} public void checkModcount() {
if (exceptCount != modcount) {
throw new ConcurrentModificationException();
}
} } }
自己实现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 ...
随机推荐
- iOS业务模块化利用CocoaPod入门实践
iOS业务模块化即是通过不同的工程管理不同的业务,通常应用在中大型项目中,这样做的好处主要有:1.多人开发时,防止工程文件冲突 2.能够为下个不同的项目抽取代码,话不多说,直接看步骤:括号内容为本例 ...
- Optaplanner规划引擎的工作原理及简单示例(2)
开篇 在前面一篇关于规划引擎Optapalnner的文章里(Optaplanner规划引擎的工作原理及简单示例(1)),老农介绍了应用Optaplanner过程中需要掌握的一些基本概念,这些概念有且于 ...
- spring jpa方法关键字转成sql
The following table describes the keywords supported for JPA and what a method containing that keywo ...
- go语言学习--内核态和用户态(协程)
go中的一个特点就是引入了相比于线程更加轻量级的协程(用户态的线程),那么什么是用户态和内核态呢? 一.什么是用户态和内核态 当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核 ...
- Pandas之Dataframe叠加,排序,统计,重新设置索引
Pandas之Dataframe索引,排序,统计,重新设置索引 一:叠加 import pandas as pd a_list = [df1,df2,df3] add_data = pd.concat ...
- REST API TO MiniProgram 上线WordPress官方插件库
全新开发的用于 wordpress微信小程序的插件 REST API TO MiniProgram今天上线WordPress官方插件库.这个插件的上一个版本叫:wp-rest-api-for-app, ...
- POJ3094 Quicksum
POJ3094 Quicksum Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 18517 Accepted: 1271 ...
- kubernetes学习笔记之十四:helm入门
1.Helm的简介 Helm是Kubernetes的一个包管理工具,用来简化Kubernetes应用的部署和管理.可以把Helm比作CentOS的yum工具. Helm有如下几个基本概念: Chart ...
- 删除链表的倒数第N个节点
题目描述: 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例: 给定一个链表: 1->2->3->4->5, 和 n = 2. 当删除了倒数第二个节点后 ...
- Python的迭代器和生成器
列表生成式 列表生成式可以快速创建list. >>> [x * x for x in range(1, 11) if x % 2 == 0] [4, 16, 36, 64, 100] ...