本文欢迎转载,转载前请联系作者,经允许后方可转载。转载后请注明出处,谢谢! http://blog.csdn.net/colton_null 作者:喝酒不骑马 Colton_Null from CSDN
一.引言
学习数据结构最好的方法个人总结即为两点:1.阅读源码。2.自己动手实现
本文分享一下自主实现简单ArrayList的代码,主要参考了《数据结构与算法分析》。
二.需要实现的内容
- size():返回当前元素个数。
- isEmpty():判断集合是否为空。
- trimToSize():将列表容量裁剪成与元素个数相等。
- length():返回列表容量。
- ensureCapacity(int newCapacity)列表扩容。
- get(int index):根据索引获取元素。
- set(int index, T t):根据索引替换元素。
- add(int index, T t)/add(T t):添加元素到索引位置或添加元素到末位。
- toString():遍历集合返回集合内容。
- iterator():获取迭代器。
- class ArrayListIterator implements Iterator:实现内部迭代器类
- hasNext():判断是否有下一个元素。
- next():获取当前迭代器迭代的元素
- remove():移除元素
- 编写测试类。
三.MyArrayList代码
import java.util.*;
public class MyArrayList<T> implements Iterable<T> {
// 默认容量
private static final int DEFAULT_CAPACITY = 10;
// 列表元素个数
private int theSize;
// 列表元素
private T[] theItems;
public MyArrayList() {
clear();
}
/**
* 清空列表,创建默认长度List
*/
public void clear() {
theSize = 0;
ensureCapacity(DEFAULT_CAPACITY);
}
/**
* 返回当前列表元素个数
*
* @return
*/
public int size() {
return theSize;
}
/**
* 判断列表是否为空
*
* @return
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* 将列表容量裁剪成跟元素个数一致
*/
public void trimToSize() {
ensureCapacity(size());
}
/**
* 列表长度
*
* @return
*/
public int length() {
return theItems.length;
}
/**
* 扩容
*
* @param newCapacity 容量大小
*/
public void ensureCapacity(int newCapacity) {
if (newCapacity < theSize) {
return;
}
T[] old = theItems;
theItems = (T[]) new Object[newCapacity];
for (int i = 0; i < size(); i++) {
theItems[i] = old[i];
}
}
/**
* 根据索引获取列表值
*
* @param index 索引值
* @return 该索引下的元素
*/
public T get(int index) {
if (index < 0 || index >= size()) {
throw new ArrayIndexOutOfBoundsException();
}
return theItems[index];
}
/**
* 替换索引所在位置的元素
*
* @param index 索引值
* @param t 新元素
* @return 旧元素
*/
public T set(int index, T t) {
if (index < 0 || index >= size()) {
throw new ArrayIndexOutOfBoundsException();
}
T old = theItems[index];
theItems[index] = t;
return old;
}
/**
* 添加元素到索引位置
*
* @param index 索引值
* @param t 新元素
*/
public void add(int index, T t) {
if (theItems.length == size()) {
// "+1是用来处理size()为0时的情况
ensureCapacity(size() * 2 + 1);
}
// 索引后的元素依次后移一位
for (int i = size(); i > index; i--) {
theItems[i] = theItems[i - 1];
}
theItems[index] = t;
theSize++;
}
/**
* 添加元素到列表末位
*
* @param t 新元素
*/
public void add(T t) {
add(size(), t);
}
/**
* 移除索引所在位置元素
*
* @param index 索引值
* @return 被移除的元素
*/
public T remove(int index) {
if (index < 0 || index >= size()) {
throw new ArrayIndexOutOfBoundsException();
}
T rmT = theItems[index];
// 索引后的所有元素前移一位
for (int i = index; i < size() - 1; i++) {
theItems[i] = theItems[i + 1];
}
theSize--;
return rmT;
}
@Override
public String toString() {
String str = "";
for (int i = 0; i < size(); i++) {
if (theItems[i] != null) {
str += theItems[i].toString() + "\n";
} else {
str += "null\n";
}
}
return str;
}
/**
* 获得该列表的迭代器
*
* @return
*/
@Override
public Iterator<T> iterator() {
return new ArrayListIterator();
}
/**
* 内部类,迭代器
*/
private class ArrayListIterator implements Iterator<T> {
// 记录当前索引,默认为0
private int current = 0;
/**
* 判断元素是否存在
*
* @return
*/
@Override
public boolean hasNext() {
return current < size();
}
/**
* 获取当前迭代器迭代的元素
*
* @return 当前迭代器迭代的元素
*/
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
// 获取后,current值+1
return theItems[current++];
}
/**
* 移除元素
*/
@Override
public void remove() {
// 移除元素实际上是调用next()方法后,再remove。而next()后,current值被加1,是为了下次迭代做准备。
// 所以如果想删除next()方法返回的元素,需要删除current值-1后的索引所在的元素。
// 又因为移除元素后,后面的元素位置发生了变化,所以current必须的值必须-1。所以使用--。
MyArrayList.this.remove(--current);
}
}
}
四.MyArrayListTest代码
测试方法和思路都写在注释里了。
import java.util.Iterator;
public class MyArrayListTest {
public static void main(String[] args) {
MyArrayList<Integer> list1 = new MyArrayList<>();
// 测试List初始化内容
System.out.println("list1的元素个数为:" + list1.size());
System.out.println("list1为空:" + list1.isEmpty());
System.out.println("list1的长度为:" + list1.length());
// 测试添加元素
list1.add(1);
list1.add(2);
System.out.println("list1的第一个元素为:" + list1.get(0));
// 测试插入元素
list1.add(0, 100);
System.out.println("list1的第一个元素为:" + list1.get(0));
// 测试更新元素
list1.set(1, 200);
System.out.println("list1的第一个元素为:" + list1.get(1));
// 测试移除元素
list1.remove(2);
System.out.println("list1的元素为:");
// 测试list扩容
System.out.println(list1);
for (int i = 3; i < 15; i++) {
list1.add(i);
}
System.out.println("list1的元素为:");
System.out.println(list1);
// 测试list长度裁剪
System.out.println("list1的长度为:" + list1.length());
list1.trimToSize();
System.out.println("trimToSize后,list1的长度为:" + list1.length());
// 测试迭代器
Iterator itr = list1.iterator();
System.out.println("用迭代器遍历输出list1");
while (itr.hasNext()) {
System.out.println(itr.next().toString());
}
// 测试迭代器删除元素
itr = list1.iterator();
while (itr.hasNext()) {
itr.next();
itr.remove();
}
System.out.println("list1为空:" + list1.isEmpty());
}
}
输出结果
list1的元素个数为:0
list1为空:true
list1的长度为:10
list1的第一个元素为:1
list1的第一个元素为:100
list1的第一个元素为:200
list1的元素为:
100
200
list1的元素为:
100
200
3
4
5
6
7
8
9
10
11
12
13
14
list1的长度为:21
trimToSize后,list1的长度为:14
用迭代器遍历输出list1
100
200
3
4
5
6
7
8
9
10
11
12
13
14
list1为空:true
证明MyArrayList的简单实现可用。
站在前人的肩膀上前行,感谢以下博客及文献的支持。
- 《数据结果与算法分析 机械工业出版社》