1 前言
數組是一種順序存儲的線性表,所有元素的內存地址是連續的,在很多編程語言中,數組都有個致命的缺點,無法動態修改容量實際開發中,我們更希望數組的容量是可以動態改變的。在此,我們實現一個動態數組。
2 動態數組接口設計
/**
* @Description: 線性表接口
* @Auther: zhurongsheng
* @Date: 2020/4/22 23:26
*/
public interface ZrsList<E> {
/**
* 元素數量
*/
int size();
/**
* 是否爲空
*/
boolean isEmpty();
/**
* 是否包含
*/
boolean contains(E element);
/**
* 添加元素
*/
void add(E element);
/**
* 返回index位置對應的元素
*/
E get(int index);
/**
* 設置index位置的元素,返回原來的元素
*/
E set(int index, E element);
/**
* 在index位置添加元素
*/
void add(int index, E element);
/**
* 刪除index對應的元素
*/
E remove(int index);
/**
* 查看元素的位置
*/
int indexOf(E element);
/**
* 清除所有元素
*/
void clear();
}
3 ZrsArrayList
/**
* @Description: 動態數組
* @Auther: zhurongsheng
* @Date: 2020/4/22 23:25
*/
public class ZrsArrayList<E> implements ZrsList<E> {
private int size;
private Object[] elements;
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ZrsArrayList(int capaticy) {
if (capaticy == 0) {
this.elements = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
} else if (capaticy > 0) {
this.elements = new Object[capaticy];
} else {
throw new IllegalArgumentException("Illegal Capacity: " +
capaticy);
}
}
public ZrsArrayList() {
this(DEFAULT_CAPACITY);
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public boolean contains(E element) {
for (Object o : elements) {
if (o.equals(element)) return true;
}
return false;
}
@Override
public void add(E element) {
ensureCapacityInternal(size + 1);
elements[size++] = element;
}
private void ensureCapacityInternal(int minCapacity) {
//如果最小值大於數組長度則需要擴容
if (minCapacity - elements.length > 0) {
if (elements == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = DEFAULT_CAPACITY;
}
int oldCapacity = elements.length;
//擴容oldCapacity容量的1/2
int newCapacity = minCapacity + (oldCapacity >> 1);
//防止溢出
if (newCapacity - oldCapacity < 0) {
newCapacity = minCapacity;
}
//擴容
elements = Arrays.copyOf(elements, newCapacity);
}
}
@Override
public E get(int index) {
rangeCheck(index);
return (E) elements[index];
}
@Override
public E set(int index, E element) {
rangeCheck(index);
Object oldValue = elements[index];
elements[index] = element;
return (E) oldValue;
}
@Override
public void add(int index, E element) {
rangeCheck(index);
ensureCapacityInternal(size + 1);
System.arraycopy(elements, index, elements, index + 1,
size - index);
elements[index] = element;
size++;
}
@Override
public E remove(int index) {
rangeCheck(index);
Object oldValue = elements[index];
int moved = size - index - 1;
if (moved > 0) {
System.arraycopy(elements, index + 1, elements, index,
moved);
}
elements[--size] = null;
return (E) oldValue;
}
@Override
public int indexOf(E element) {
for (int i = 0; i < elements.length; i++) {
if (element.equals(elements[i])) return i;
}
return -1;
}
@Override
public void clear() {
for (int i = 0; i < elements.length; i++) {
elements[i] = null;
}
size = 0;
}
private void rangeCheck(int index) {
if (index < 1 || index >= size) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
private String outOfBoundsMsg(int index) {
return "Index: " + index + ", Size: " + size;
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < size; i++) {
if (i == 0) {
sb.append(elements[i]);
} else {
sb.append(",").append(elements[i]);
}
}
sb.append("]");
return sb.toString();
}
}
4 測試類
/**
* @Description: 測試類
* @Auther: zhurongsheng
* @Date: 2020/4/22 23:56
*/
public class ArrayListTest {
public static void main(String[] args) {
ZrsList<Integer> lists = new ZrsArrayList<>();
for (int i = 0; i < 10; i++) {
lists.add(i);
}
lists.remove(2);
System.out.println(lists.toString());
lists.add(2, 2);
System.out.println(lists.toString());
System.out.println("size:" + lists.size());
}
}