用数组实现ArrayList
一、数组介绍
-
数组是一种顺序存储的线性表,可以存储多个值,每个元素可以通过索引进行访问,所有元素的内存地址是连续的。
-
优点:
- 空间利用率高。
- 查询速度高效,通过下标来直接存取。
- 缺点:
-
插入和删除比较慢,比如:插入或者删除一个元素时,整个表需要遍历移动元素来重新排一次顺序。
-
不可以增长长度,有空间限制,当需要存取的元素个数可能多于顺序表的元素个数时,会出现"溢出"问题.当元素个数远少于预先分配的空间时,空间浪费巨大
二、Java中使用数组
- 第一种:声明数组的时候初始化,有N个元素:
数组类型 [] 数组名 = {em1,em2,em3,…,emN};
int[] array = {1,2,3,4,6,5};
- 2、用new关键字声明数组的同时指定数组长度:
数组类型[] 数组名 = new 数组类型[N];
String[] str = new String[6];
- 3、用new关键字声明数组的同时初始化数组:
数组类型[] 数组名 = new 数组类型[] {em1,em2,em3,…,emN};
int[] array = new int[] {2,4,7,6,8,9};
- 数组一旦声明,数组长度就已经确定。每个数组都有一个length属性,不可改变。可以改变数组元素
三、实现ArrayList
public class MyArray<E> {
private int size = 0;//保存当前元素个数
//定义默认初始化容量
private static final int CAPACITY = 10;
//查找失败返回值
private static final int NOT_FOUND = -1;
//用于保存数组元素
private E[] elements = (E[]) new Object[CAPACITY];
public MyArray() {
this(CAPACITY);
}
/**
* 带参初始化
*
* @param capacity 初始化容量
*/
public MyArray(int capacity) {
if (capacity < 10) {
elements = (E[]) new Object[CAPACITY];
} else {
elements = (E[]) new Object[capacity];
}
}
}
判断当前数组是否为空
/**
* 空:true
* 非空:false
*
* @return 返回true | false
*/
public boolean isEmpty() {
return size == 0;
}
是否包含某个元素
/**
* @param element
* @return 返回true | false
*/
public boolean contains(E element) {
return indexOf(element)!=ELEMENT_NOT_FOUND;
}
查找元素
/**
* @param element 需要查找的元素
* @return 返回该元素索引 | -1
*/
public int indexOf(E element) {
if(element==null){
for (int i = 0; i <size; i++) {
if(elements[i]==null){
return i;
}
}
}else{
for (int i = 0; i <size; i++) {
if(element.equals(elements[i])){
return i;
}
}
}
return NOT_FOUND;
}
返回对应索引的值
/**
* @param index 元素的索引
* @return 对应值 | -1
*/
public E get(int index) {
checkIndex(index);
return elements[index];
}
设置index位置元素的值
/**
* @param index 需要设置的位置索引
* @param element 设置的值
* @return 返回原先的值
*/
public E set(int index, E element) {
checkIndex(index);
E old=elements[index];
elements[index]=element;
return old;
}
清空所有元素
public void clear() {
//遍历将每个元素复制为null即可清空
for (int i = 0; i <size; i++) {
elements[i]=null;
}
size=0;
}
返回当前元素的数量
/**
* @return 当前元素的个数
*/
public int size() {
return size;
}
添加元素到尾部
/**
* @param element 待添加的元素
*/
public void add(E element) {
if(size>elements.length-1){
ensureCapacity(size+1);
}
elements[size]=element;
size++;
}
向index位置添加元素
/**
* @param index 插入位置的索引
* @param element 插入的元素
*/
public void add(int index, E element) {
if(index<0||index>size){
throw new IndexOutOfBoundsException("索引越界");
}
for (int i =size; i>index; i--) {
elements[i]=elements[i-1];//元素右移
}
elements[index]=element;
size++;
}
移除index位置元素
/**
* @param index 被移除元素的索引
* @return 返回原先值
*/
public E remove(int index) {
checkIndex(index);
E old=elements[index];
for (int i = index; i <size; i++) {
elements[i]=elements[i+1];
}
size--;
elements[size]=null;//清空最后一个元素
if(size==elements.length>>1){
ensureCapacity(elements.length>>1);
}
return old;
}
返回元素集合
/**
* @return
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("size:" + size + " => [");
for (int i = 0; i < size; i++) {
if (i != 0) {
sb.append(" ,");
}
sb.append(elements[i]);
}
sb.append("]");
return sb.toString();
}
判断是否越界
//判断是否越界
public void checkIndex(int index){
if(index<0||index>=size){
throw new IndexOutOfBoundsException("索引越界");
}
}
确保数组容量
public void ensureCapacity(int capacity){
if(elements.length>=capacity){
return;
}
//扩容1.5倍
E[] newElments=(E[])new Object[elements.length+(elements.length>>1)];
//将原有数组元素复制到新数组中
for (int i = 0; i <size; i++) {
newElments[i]=elements[i];
}
elements=newElments;
}