ArrayList简介

ArrayList是一个动态数组,Array的复杂版本,它提供了动态的增加和减少元素,实现了ICollection和IList接口,灵活的设置数组的大小等好处,ArrayList不是线程安全的。

MyArrayList

在实现MyArrayList前先实现MyList,MyAbstractList,他们的关系如下。

MyArrayList--->(继承于)MyAbstractList--->(实现)MyList接口--->(实现)java.lang.Iterable接口

通过编写新的ArrayList来实现java中ArrayList的部分功能

MyList接口定义如下

public interface MyList<E> extends Iterable<E> {

    public void add(E e);
public void add(int index, E e);
public void clear();
public boolean contains(E e);
public E get(int index);
public int indexOf(E e);
public boolean isEmpty();
public int lastIndexOf(E e);
public boolean remove(E e);
public E remove(int index);
public E set(int index, E e);
public int size();
}

MyAbstractList类定义如下

public abstract class MyAbstractList<E> implements MyList<E> {

    protected int size = 0;

    protected MyAbstractList() {

    }

    protected MyAbstractList(E[] objects) {
for(int i = 0; i < objects.length; i++) {
add(objects[i]);
}
} @Override
public void add(E e) {
add(size, e);
} @Override
public boolean isEmpty() {
return size == 0;
} @Override
public int size() {
return size;
} @Override
public boolean remove(E e) {
if(indexOf(e) >= 0) {
remove(indexOf(e));
return true;
}else {
return false;
}
}
}

MyArrayList定义如下

import java.util.Iterator;

public class MyArrayList<E> extends MyAbstractList<E> {
public static final int INITIAL_CAPACITY = 16;//初始容量
private E[]data = (E[])(new Object[INITIAL_CAPACITY]);; public MyArrayList() {
} public MyArrayList(int length) {
if(length >= 0) {
data = (E[])(new Object[length]);
}
} public MyArrayList(E[] objects) {
for(int i = 0; i < objects.length; i++) {
add(objects[i]);
}
} @Override
public void add(int index, E e) {
// TODO Auto-generated method stub
ensureCapacity(); for(int i = size - 1; i >= index; i--) {//将data[index]和后面的元素往后移动一位
data[i + 1] = data[i];
} data[index] = e;
size++;
} //判断容量满时,新建一个容量为原来两倍+1的数组
private void ensureCapacity() {
if(size >= data.length) {
E[] newData = (E[])(new Object[size * 2 + 1]);//java源码扩容1.5倍+1
System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
} @Override
public void clear() {
// TODO Auto-generated method stub
data = (E[])(new Object[INITIAL_CAPACITY]);
size = 0;
} @Override
public boolean contains(E e) {
// TODO Auto-generated method stub
for(int i = 0; i < size; i++) {
if(e.equals(data[i])) {
return true;
}
}
return false;
} @Override
public E get(int index) {
// TODO Auto-generated method stub
checkIndex(index);//判断下标是否合法
return data[index];
} private void checkIndex(int index) {
if(index < 0 || index >= size) {
throw new IndexOutOfBoundsException("index " + index + " out of bounds");
}
} @Override
public int indexOf(E e) {
// TODO Auto-generated method stub
for(int i = 0; i < size; i++) {
if(e.equals(data[i])) {
return i;
}
}
return -1;
} @Override
public int lastIndexOf(E e) {
// TODO Auto-generated method stub
for(int i = size - 1; i >= 0; i--) {
if(e.equals(data[i])) {
return i;
}
}
return -1;
} @Override
public E remove(int index) {
// TODO Auto-generated method stub
checkIndex(index);//判断下标是否合法
E e = data[index];//获取删除对象的值 for(int i = index; i < size - 1; i++) {//将data[index]后面的元素往前移动一位
data[i] = data[i+1];
} data[size] = null;//删除最后的元素
size--;
return e;
} @Override
public E set(int index, E e) {
// TODO Auto-generated method stub
checkIndex(index);//判断下标是否合法
E old = data[index];
data[index] = e;
return old;
} //重写java.lang.Object.toString方法,打印整个数组
@Override
public String toString() {
StringBuilder result = new StringBuilder("["); for(int i = 0; i < size; i++) {
result.append(data[i]);
if(i < size - 1) {
result.append(",");
}
} return result + "]";
} //新建一个刚好等于size的数组,即将数组容量设为刚好足够存放的大小
public void trimToSize() {
if(size != data.length) {
E[] newData = (E[])(new Object[size]);
System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
} @Override
public Iterator<E> iterator() {
// TODO Auto-generated method stub
return new ArrayListIterator();
} private class ArrayListIterator implements Iterator<E> {
private int current = 0; @Override
public boolean hasNext() {
// TODO Auto-generated method stub
return (current < size);
} @Override
public E next() {
// TODO Auto-generated method stub
return data[current++];
}
}
}

测试代码如下

public class TestMyArrayList {

    public static void main(String[] args) {
// TODO Auto-generated method stub // String[] ss = {"China","America","Germany","Canada","France","Germany"};
MyList<String> list = new MyArrayList<String>();
System.out.println("测试add(E e)方法和add(int index, E e)方法添加数据。");
list.add("America");
list.add(0,"China");
list.add("Canada");
list.add("France");
list.add(2,"Germany");
list.add("Germany");
System.out.println("通过toString()方法打印数组" + list.toString());
System.out.println("通过size()方法获取长度:" + list.size());
System.out.println("测试contains()方法:" + list.contains("France"));
System.out.println("通过get()方法获取指定下标的值:" + list.get(1));
System.out.println("通过indexOf()方法获取指定值的下标:" + list.indexOf("Germany"));
System.out.println("通过lastIndexOf()方法获取最后出现的指定值的下标:" + list.lastIndexOf("Germany"));
System.out.println("通过下标删除指定值:" + list.remove(5));
System.out.println("删除后的数组:" + list.toString());
System.out.println("通过set()方法修改值:" + list.set(2, "Russia"));
System.out.print("通过foreach遍历数组:");
for(String s:list) {
System.out.print(s.toUpperCase() + " ");
}
} }

测试结果

思考:为什么MyArrayList类中的ensureCapacity()扩容倍数是2 * x + 1而不是2 * x?

因为如果我们创建了一个长度为0的数组,如果扩容倍数是2 * x,那么这个数组就无法扩容了。

实现MyArrayList类深入理解ArrayList的更多相关文章

  1. 理解ArrayList与LinkedList的区别

    一.先来看看ArrayList与LinkedList 在JDK中所在的位置 从图中可以看出,ArrayList与LinkedList都是List接口的实现类,因此都实现了List的所有未实现的方法,只 ...

  2. 深入理解ArrayList与LinkedList的区别

    一.先来看看ArrayList与LinkedList 在JDK中所在的位置 从图中可以看出,ArrayList与LinkedList都是List接口的实现类,因此都实现了List的所有未实现的方法,只 ...

  3. [BS-18] 对OC中不可变类的理解

    对OC中不可变类的理解 OC中存在很多不可变的类(如NSString,NSAttributedString,NSArray,NSDictionary,NSSet等),用它们创建的对象存在于堆内存中,但 ...

  4. 编写测试类,了解ArrayList的方法

    这篇文章主要介绍了C#中动态数组用法,实例分析了C#中ArrayList实现动态数组的技巧,非常具有实用价值,需要的朋友可以参考下 本文实例讲述了C#中动态数组用法.分享给大家供大家参考.具体分析如下 ...

  5. 16、Collection接口及其子接口Set和List(常用类LinkedList,ArrayList,Vector和Stack)

    16.Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements).一些Collection允许相同 ...

  6. 对Java中properties类的理解

    转载于:https://www.cnblogs.com/bakari/p/3562244.html 一.Java Properties类 Java中有个比较重要的类Properties(Java.ut ...

  7. AtomicInteger类的理解与使用

    AtomicInteger类的理解与使用 首先看两段代码,一段是Integer的,一段是AtomicInteger的,为以下: public class Sample1 { private stati ...

  8. FileChannel类的理解和使用

    FileChannel类的理解和使用(java.nio.channels.FileChannel) 知识点: 1.FileChannel类及方法理解:2.普通输入输出流复制文件:3.FileChann ...

  9. 从源代码来理解ArrayList和LinkedList差别

    从源代码理解ArrayList和LinkedList差别 ArrayList ArrayList默认容量为10,实质是一个数组用于存放元素,size表示ArrayList所包括的元素个数. Array ...

随机推荐

  1. OJ题:句子逆转

    将一个英文语句以单词为单位逆序排放.例如"I am a boy",逆序排放后为"boy a am I"所有单词之间用一个空格隔开,语句中除了英文字母外,不再包含 ...

  2. 【leetcode】经典算法题-Counting Bits

    题目描述: 给定一个数字n,统计0-n之间的数字二进制的1的个数,并用数组输出 例子: For num = 5 you should return [0,1,1,2,1,2]. 要求: 算法复杂复o( ...

  3. Leetcode_6_ZigZag Conversion

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/41408021 看完这篇文章,你可能会学到到知识如下: (1 ...

  4. Android官方技术文档翻译——Gradle 插件用户指南(7)

    本文译自Android官方技术文档<Gradle Plugin User Guide>,原文地址:http://tools.android.com/tech-docs/new-build- ...

  5. EventBus的其他常用函数

    上一篇EventBus最简易使用方式介绍了EventBus最简易的使用方式,摆脱了叽里呱啦+图片的长篇大论.目的是为了让刚开始接触的人们不晕头转向.那么这篇..我也要开始图片+叽里呱啦了. 转载请注明 ...

  6. Android自定义view进阶-- 神奇的贝塞尔曲线

    上一篇介绍了自定义view需要知道的基本函数.新开一篇献给借给我vpn的深圳_奋斗小哥. 转载请注明出处:http://blog.csdn.net/wingichoy/article/details/ ...

  7. (二十六)静态单元格(Cell)

    制作类似iOS系统设置的页面,如果使用代码来实现,将会比较麻烦,可以通过静态单元格技术方便的实现. 注意:静态单元格只支持TableViewController. 可以通过storyboard直接操作 ...

  8. 【Qt编程】Qt学习之状态栏

    QStatusBar类提供一个水平条来显示状态信息.所谓状态信息,拿个简单的例子来说,当你在word中编辑时,左下角就会出现页面.字数等等信息.状态信息可以分为三类:临时信息,如一般的提示信息:正常信 ...

  9. MT6575 3G切换2G

    因为了节省成本,需要从现在的3G方案切换置2G方案,做的修改,做个笔记. 一: 将MTK给过来的补丁编译出如下文件. 二:在mediatek/custom/common/modem/  路径下增加一个 ...

  10. LeetCode之“链表”:Remove Nth Node From End of List

    题目链接 题目要求: Given a linked list, remove the nth node from the end of list and return its head. For ex ...