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来实现扩容.