自己通过写一个简单的SimpleArrayList来加深对JDK源码中的ArrayList的理解。
- 构造器
如果没有对集合设定长度,这里我们默认采取长度为10作为内置数组的初始化长度。
public SimpleArrayList() {
this(DEFAULT_SIZE);
}
public SimpleArrayList(int size) {
target = new Object[size];
}
- 向集合中添加元素add(E)
这里用到了Arrays类的copyof。如果长度超过我们设置的长度。数组中的元素复制到新数组。新数组长度为原数组的2倍。(当然这里可以自定义设置扩容比例)
由于数组长度设定不能大于int的长度即java.lang.Integer.MAX_VALUE = 2^31-1 = 2147483647(实际上虚拟机内存不一定支持理论上的最大值),这里没有加上这个校验,真实的程序是有这个校验的。
public void add(E e){
if(this.size < DEFAULT_SIZE){
//小于默认尺寸10
target[size++] = e;
}else{
//大于10的时候需要扩容,
//copyOf复制指定的数组到新数组,第一个参数为原数组,第二个参数为新数组长度
target = Arrays.copyOf(target, size*2);
target[size++] = e;
}
}
- 根据下标获取元素get(index)
public E get(int index){
return (E)target[index];
}
- 返回集合长度size()方法
public int size(){
return this.size;
}
- 判断元素是否在集合 indexOf(Object)
public int indexOf(Object obj){
if(obj==null){
for(int i=0;i<target.length;i++){
if(target[i]==null){
return i;
}
}
}else{
for(int i=0;i<target.length;i++){
if(obj.equals(target[i])){
return i;
}
}
}
return -1;
}
- 根据下标移除集合中的元素remove(index)
System.arraycopy(被复制的数组,被复制位置,目标数组,目标数组位置,被复制数组的结束到开始的长度)
target将index+1到最后的所有数据,复制到target的排除e元素即index位置到最后的位置。
这样的数组长度还是没有变化的,所以,–size,让集合长度减一,而溢出的这个元素,等待GC回收
public E remove(int index){
E e =get(index);
System.arraycopy(target, index+1, target, index, size-index-1);
target[--size] = null;
return e;
}
- 根据元素移除集合中和该元素相同的元素remove(Object)
public boolean remove(Object o){
if(o==null){
for(int i=0;i<target.length;i++){
if(target[i]==null){
remove(i);
return true;
}
}
}else{
for(int i=0;i<target.length;i++){
if(o.equals(target[i])){
remove(i);
return true;
}
}
}
return false;
}
- 清空集合(clear)
public void clear(){
for(int i=0;i<target.length;i++){
target[i] =null;
}
size = 0;
}
最后附上全部的源码,有什么不对的地方,请指出。
/**
* 模拟ArrayList
* 1,实现方法,get(int),add(E),add(int,E),size(),remove(int),remove(Object),indexOf(Object)
* 2,ArrayList本质上是动态数组
* 3,巧用System.arraycopy和Arrays.copyof来实现元素的添加和删除
*
*/
public class SimpleArrayList<E> {
private final static int DEFAULT_SIZE = 10;
private int size;
private Object[] target;
public SimpleArrayList() {
this(DEFAULT_SIZE);
}
public SimpleArrayList(int size) {
target = new Object[size];
}
/**
* 向集合中添加元素
* @param e 元素
*/
public void add(E e){
if(this.size < DEFAULT_SIZE){
//小于默认尺寸10
target[size++] = e;
}else{
//大于10的时候需要扩容,
//copyOf复制指定的数组到新数组,第一个参数为原数组,第二个参数为新数组长度
target = Arrays.copyOf(target, size*2);
target[size++] = e;
}
}
/**
* 根据下标获取集合中的元素
* @param index 下标
* @return
*/
public E get(int index){
return (E)target[index];
}
/**
* 返回集合长度
* @return
*/
public int size(){
return this.size;
}
/**
* 判断元素是否存在集合中
* 存在返回下标
* 不存在返回-1
* @param obj
* @return
*/
public int indexOf(Object obj){
if(obj==null){
for(int i=0;i<target.length;i++){
if(target[i]==null){
return i;
}
}
}else{
for(int i=0;i<target.length;i++){
if(obj.equals(target[i])){
return i;
}
}
}
return -1;
}
/**
* 根据下标移出集合中的元素
* @param index 下标
* @return
*/
public E remove(int index){
E e =get(index);
/**
* System.arraycopy(被复制的数组,被复制位置,目标数组,目标数组位置,被复制数组的结束到开始的长度)
*
* target将index+1到最后的所有数据,复制到target的排除e元素即index位置到最后的位置。
*
* 这样的数组长度还是没有变化的,所以,--size,让集合长度减一,而溢出的这个元素,等待GC回收
*/
System.arraycopy(target, index+1, target, index, size-index-1);
target[--size] = null;
return e;
}
/**
* 根据移除集合中的元素
* 移除成功返回true,反之false
* @param o 元素
* @return
*/
public boolean remove(Object o){
if(o==null){
for(int i=0;i<target.length;i++){
if(target[i]==null){
remove(i);
return true;
}
}
}else{
for(int i=0;i<target.length;i++){
if(o.equals(target[i])){
remove(i);
return true;
}
}
}
return false;
}
/**
* 清空集合
*/
public void clear(){
for(int i=0;i<target.length;i++){
target[i] =null;
}
size = 0;
}
}