package com.java;
import java.util.Arrays;
public class MyArrayList {
private final static int DEFAULT_SIZE = 10;
private Object[] arr;
// 首先是构造方法
// 查询api发现arraylist有三个构造方法
// 第一个构造初始容量为10的空列表
int size;
public MyArrayList() {
this(DEFAULT_SIZE);
}
// 第二个指定元素类型的 ,使用泛型的暂时不做了
// 第三个构造具有指定容量的空列表
public MyArrayList(int arrlenght) {
if (arrlenght < 0) {
throw new NoRangeException("输入的范围不对");
} else {
arr = new Object[arrlenght];
}
}
// 第一个方法 将指定元素追加到此列表末尾
public boolean add(Object o) {
// 首先判断要不要判断会不会超出范围
judgeRange(size + 1);
arr[size++] = o;
return true;
}
public void judgeRange(int size) {
if (size + 1 > arr.length) {
// 当size表示这次要添加的位置,判断size+1是不是大于数组的长度了 大于就要扩充数组
expand(size);
}
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
public void expand(int size) {
int oldsize = arr.length;
int newsize = oldsize + (oldsize >> 1);// 位运算 向右移动一位,相当于原来的1/2
// 将数组扩大到原来的1.5倍
if (newsize < size) {
newsize = size; // 如果1.5倍长度不够就申请需要的长度,如果增加一个的话是用不到这个方法的,
// 主要用于addAll的时候一次增加元素导致一次1.5倍不够.
}
if (newsize > MAX_ARRAY_SIZE)
newsize = (size > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
// 当list长到大于上面定义的最大的长度,就把长度扩展到int的最大值,否则使用上面定义的那个
arr = Arrays.copyOf(arr, newsize);
}
// 第二个方法 在此列表中的指定位置插入指定元素
public void add(int index, Object o) {
// 首先判断要插入的位置在不在有效的范围
judgeAddRange(index);
// 然后判断需不需要扩容
judgeRange(size + 1);
// 将index及以后的元素向后移动一位
System.arraycopy(arr, index, arr, index + 1, size - index);
arr[index] = o; // index下标的内容改为o
size++;
}
// 判断范围
public void judgeAddRange(int index) {
if (index < 0 && index > size) {
throw new IndexOutOfBoundsException("index越界");
}
}
// 从列表中删除所有元素
public void clear() {
for (int i = 0; i < size; i++) {
arr[i] = null;
}
size = 0;
}
// 返回此列表实例的浅拷贝 也不知道对不对,不会死很懂这个clone,也不会验证
public Object clone() {
MyArrayList v = null;
try {
v = (MyArrayList) super.clone();
v.arr = Arrays.copyOf(arr, size);
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return v;
}
// 如果此列表包含指定的元素,则返回true
public boolean contains(Object o) {
return indexOf(o) > -1;
}
// 返回此列表中指定元素的第一次出现的索引,如果此类表不包含元素,则返回-1
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (arr[i] == null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(arr[i]))
return i;
}
return -1;
}
// 返回此类表中指定位置的元素
public Object get(int index) {
// 判断范围
rangeForRemove(index);
return arr[index];
}
// 如果此列表不包含元素,则返回true
public boolean isEmpty() {
return size() == 0;
}
// 返回列表中的元素
public int size() {
return size;
}
// 删除该列表中指定位置的元素
public Object remove(int index) {
// 先判断范围
rangeForRemove(index);
Object oldo = arr[index];
int moveSize = size - index - 1;
if (moveSize > 0) // 判断删除的是不是最后一个元素,覆盖
System.arraycopy(arr, index + 1, arr, index, size - index - 1);
arr[--size] = null; // 后面的赋值为null
return oldo;
}
// 从列表中删除指定元素的第一个出现(如果存在)
public boolean remove(Object o) {
// 首先看有没有这个元素
if (contains(o)) {
remove(indexOf(o));
return true;
}
return false;
}
// 从这个列表中删除所有索引在intfromIndex(含)和toIndex之间的元素
protected void removeRange(int intFromIndex, int toIndex) {
System.arraycopy(arr, toIndex, arr, intFromIndex, size - toIndex);
int newsize = size - toIndex + intFromIndex;
for (int i = newsize; i < size; i++) {
arr[i] = null;
}
size = newsize;
}
private void rangeForRemove(int index) {
if (index >= size || index < 0)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
@Override
public String toString() {
return "MyArrayList [arr=" + Arrays.toString(arr) + ", size=" + size + "]";
}
}
收获
arraylist默认的大小是10.
arraylist扩充容量会是原来的1.5倍,如果1.5被不够那么就扩招到需要的容量,当然最大的范围是Integer的最大值.但是为什么会默认保留8位呢,或许保存着一些东西,或许是为了跨平台???防止在有些机器上出问题,为什么要默认-8,又能个扩展到最大啊
判断元素的时候先判断是不是为null 也就是说这个集合支持存null的
底层是数组的话,是不是意味着他在增加和删除方面比较慢,在查询方面比较快.但是好像和其他的对象也有点关系.
用System.arraycopy来是实现元素的覆盖.增删.
用Arrays.copyOf来实现扩容.
转载于:https://blog.51cto.com/10760006/2160660