特点:
在内存中分配连续的空间,只存储数据,不存储地址信息。位置就隐含着地址。
1
优点:
1.节省存储空间,因为分配给数据的存储单元全用存放结点的数据(不考虑c/c++语言中数组需指定大小的情况), 结点之间的逻辑关系没有占用额外的存储空间。
2. 索引查找效率高,即每一个结点对应一个序号,由该序号可以直接计算出来结点的存储地址。 假设线性表的每个数据元素需占用K个存储单元,并以元素所占的第一个存储单元的地址作为数据元素的存储地址。 则线性表中序号为i的数据元素的存储地址LOC(a i )与序号为i+1 的数据元素的存储地址LOC(a i+1 )之间的关系为
LOC(a i+1 ) = LOC(a i ) + K
通常来说,线性表的i号元素a i 的存储地址为
LOC(a i ) = LOC(a 0 ) + i×K
其中LOC(a 0 )为 0 号元素a 0 的存储地址,通常称为线性表的起始地址。
缺点:
1.插入和删除操作需要移动元素,效率较低。
2.必须提前分配固定数量的空间,如果存储元素少,可能导致空闲浪费。
3.按照内容查询效率低,因为需要逐个比较判断
无参构造(一开始如果用户没设置集合大小,初始值就为10)
public ArrayList(){ this(10); //数组大小初始为10 }
有参构造(给用户设置大小)
public ArrayList(int len){ elementData = new Object[len]; }
集合容量不足时,每次扩容增加50%
void grow(){ //创建新的数组 Object []newArr = new Object[elementData.length + (elementData.length >> 1)];//扩容1.5倍 for(int i = 0; i < size; i++){ //将原来数组的内容存到新数组里 newArr[i] = elementData[i]; } elementData = newArr; }
定义List接口
public interface List <T>{ // ------- 添加 ------- void add(Object object); // ------- 根据坐标删除 ------- void remove(int index); // ------- 根据内容删除 ------- void removeobj(Object object); // ------- 取出数据 ------- Object get(int index); // ------- 求集合的长度 ------- int size(); // ------- 判断集合是否为空 ------- boolean isEmpty(); // ------- 根据内容找到元素坐标 ------- int IndexOf(Object object); // ------- 判断元素是否存在 ------- boolean contions(Object object); // ------- 根据坐标位置插入元素 ------- void add(int index, Object object); // ------- 修改元素 ------- void replase(int index, Object object); // ------- toString ------- String toString(); // ------- arraylist迭代器 ------- ArrayList.Ite iterator(); }
定义Iterator接口
public interface Iterator <T>{ boolean hasNext(); T next(); }
ArrayList实现类
public class ArrayList <T>implements List { public Object []elementData; //数组的引用 private int size; //集合的大小,并非elementData.length //如果用户没设置大小就初始为10 public ArrayList(){ this(10); //数组大小初始为10 } //集合的大小等于用户设置的大小 public ArrayList(int len){ elementData = new Object[len]; } // 数组的扩容 void grow(){ //创建新的数组 Object []newArr = new Object[elementData.length + (elementData.length >> 1)];//扩容1.5倍 for(int i = 0; i < size; i++){ //将原来数组的内容存到新数组里 newArr[i] = elementData[i]; } elementData = newArr; } //在集合的尾部添加元素 public void add(Object object) { //如果数组长度不够就调用扩容 if(elementData.length <= size){ grow(); } elementData[size] = object; //大小增加一位 size++; } //根据坐标删除元素 public void remove(int index) { //判断用户是否输入错误 if(index<0|| index >size-1){ throw new IndexOutOfBoundsException("索引越界"+index); } Object element=elementData[index]; // 向前移动元素 for (int i = index; i <size-1 ; i++) { elementData[i]=elementData[i+1]; } // 最后一个元素置为空 elementData[size-1]=null; size--; } //根据元素删除 public void removeobj(Object object) { int index = IndexOf(object); //判断用户是否输入错误! if(index<0){ throw new NullPointerException(); } remove(index); } //根据坐标得到元素 public Object get(int index) { return elementData[index]; } //求集合的长度 public int size() { return size; } //判断是否为空 public boolean isEmpty() { return size == 0; } //根据元素找到坐标 public int IndexOf(Object object) { int i = 0; while(i < size){ if(elementData[i].equals(object)){ break; } i++; } return i; } //判断元素是否存在 public boolean contions(Object object) { boolean flag = false; for(int i = 0; i < size; i++){ if(elementData[i].equals(object)){ flag = true; break; } } return flag; } //根据坐标位置添加元素 public void add(int index, Object object) { if(size >= elementData.length){ grow(); } for(int i = size; i > index; i--){ elementData[i] = elementData[i - 1]; } elementData[index] = object; size++; } //修改元素 public void replase(int index, Object object) { elementData[index] = object; } //重写toString public String toString(){ StringBuilder str = new StringBuilder("["); for(int i = 0; i < size; i++){ //判断是否到了最后一位,如果到了就不添加, if(i == size - 1){ str.append(elementData[i]); break; }else{ str.append(elementData[i] + ","); } } str.append("]"); return str.toString(); } // ------- 迭代器 ------- public Ite iterator(){ return new Ite(); } public class Ite<T>implements Iterator<T> { int cursor = 0; //指向当前元素,默认是0 public ArrayList arr = new ArrayList(); public boolean hasNext() { return cursor != size; } public T next() { int i = cursor; //保留当前值 cursor++;//自增 // 进行判断,防止越界 if (i > size) { throw new RuntimeException("没有元素"); } return (T) elementData[i]; } } }
自定义异常(不自定义也没关系,java自带也有)
public class IndexOutOfBoundsException extends RuntimeException{
public IndexOutOfBoundsException() { }
public IndexOutOfBoundsException(String message) {
super(message);
}
}
Java数据结构与算法之ArrayList