这篇文章,我们来一起研究一下Java集合中的ArrayList。
一、回顾List。
1、特点
(1)有序:List中每个元素都有索引标记,可以根据元素的索引标记来精确控制元素。
(2)可重复:List中允许放入重复(e1.equals(e2)即此处的重复)的元素。
二、ArrayList优缺点
1、优点
我们知道,ArrayList底层数据结构为数组,数组开辟的空间是连续的,so,遍历元素和随机访问元素的效率较高。
2、缺点
添加和删除元素需要大量的移动元素,故插入和删除效率较低。
三、简单实现ArrayList
public class MyArrayList<E> {
//存放数据的数组
private Object[] elementData;
//数组中默认存放的元素个数
private static final int DEFAULT_CATACITY = 10;
//存放的元素的个数
private int size;
public MyArrayList(){
elementData = new Object[DEFAULT_CATACITY];
}
public MyArrayList(int catacity){
if(catacity < 0){
throw new RuntimeException("数组的长度不能为负数");
}else if(catacity == 0){
elementData = new Object[DEFAULT_CATACITY];
}else{
elementData = new Object[catacity];
}
}
/**
* 判断集合是否为空
* @return
*/
public boolean isEmpty(){
return size==0?true:false;
}
/**
* 获取集合中元素的个数
* @return
*/
public int size(){
return size;
}
/**
* 添加元素
* @param element
*/
public void add(E element){
//当默认长度的数组存放满了以后,就要涉及到数组的扩容问题
//数组的扩容其实还是数组的拷贝
if(size==elementData.length){
//此处注意运算的优先级问题 + 优先级高于移位运算 >>
Object[] newArray = new Object[elementData.length+(elementData.length>>1)];
System.arraycopy(elementData,0,newArray,0,elementData.length);
elementData = newArray;
}
elementData[size++] = element;
}
/**
* 设置元素
* @param index
* @param element
*/
public void set(int index,E element){
checkRange(index);
elementData[index] = element;
}
/**
* 获取指定索引出的元素
* @param index
* @return
*/
public E get(int index){
checkRange(index);
return (E)elementData[index];
}
/**
* 根据索引删除元素
* [a,b,c,d,e]
* [a,b,d,e]
* @param index
*/
public void remove(int index){
checkRange(index);
int numMove = elementData.length-index-1;
if(numMove>0){
//移除数组底层其实是数组的拷贝
System.arraycopy(elementData,index+1,elementData,index,numMove);
}
elementData[--size] = null;
}
/**
* 删除指定元素
* @param element
*/
public void remove(E element){
for(int i = 0; i < size; i ++){
if(element.equals(get(i))){
remove(i);
}
}
}
private void checkRange(int index){
if(index<0 || index>size-1){
throw new RuntimeException("数组下标越界");
}
}
//为了方便观察,重写toString()方法
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i = 0;i <size; i ++){
sb.append(elementData[i]+",");
}
sb.setCharAt(sb.length()-1,']');//设置该索引处的字符为 ']'
return sb.toString();
}
public static void main(String[] args){
MyArrayList<String> myArrayList = new MyArrayList<>(5);
/*myArrayList.add("a");
myArrayList.add("b");
myArrayList.add("c");
myArrayList.add("d");*/
for(int i = 0; i < 20; i ++){
myArrayList.add("caojia"+i);
}
System.out.println(myArrayList);
System.out.println(myArrayList.get(10));
myArrayList.set(10,"张三");
System.out.println(myArrayList);
//myArrayList.remove(10);
myArrayList.remove("张三");
System.out.println(myArrayList);
}
}
整体来说,代码相对简单,需要注意的就是:
1、数组的扩容
2、数组的拷贝
具体的操作代码中写的很详细。