天天看點

java 定義動态數組_動手編寫—動态數組(Java實作)

數組基礎回顧

1、數組是一種常見的資料結構,用來存儲同一類型值的集合

2、數組就是存儲資料長度固定的容器,保證多個資料的資料類型要一緻

3、數組是一種順序存儲的線性表,所有元素的記憶體位址是連續的

4、例如:new 一個int基本類型的數組array

int[] array = new int[]{11,22,33};

java 定義動态數組_動手編寫—動态數組(Java實作)

5、數組的優勢與劣勢

數組具有很高的随機通路能力,通過數組下标就可以讀取對應的值

數組在插入與删除元素時,會導緻大量的元素移動

數組的長度是固定的,無法動态擴容,在實際開發中,我們更希望數組的容量是可以動态改變的

總結——數組适用于讀操作多,寫操作少的場景

自定義動态數組

動态數組的設計

protected int size;

private E[] elements;

圖示結構:

java 定義動态數組_動手編寫—動态數組(Java實作)

抽象父類接口設計

将動态數組與連結清單共同的屬性與方法抽取出,作為抽象類,提高複用性

抽象父類接口——List

public interface List {

//查無元素的傳回标志

int ELEMENT_NOT_FOUND = -1;

int size();

boolean isEmpty();

E set(int index, E element);

E get(int index);

boolean contains(E element);

int indexOf(E element);

void add(E element);

void add(int index, E element);

E remove(int index);

public E remove(E element);

void clear();

抽象父類設計

抽象父類AbstractList是對接口List的實作

public abstract class AbstractList implements List {

protected int size;

public int size() {

return size;

}

public boolean isEmpty() {

return size == 0;

}

public boolean contains(E element) {

return indexOf(element) != ELEMENT_NOT_FOUND;

}

public void add(E element) {

add(size, element);

}

protected void outOfBounds(int index) {

throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);

}

protected void rangeCheck(int index) {

if (index < 0 || index >= size) {

outOfBounds(index);

}

}

protected void rangeCheckForAdd(int index) {

//index > size,元素可以添加在數組size位置,即數組尾部下一存儲單元

if (index < 0 || index > size) {

outOfBounds(index);

}

}

}

動态數組之DynamicArray

public class DynamicArray extends AbstractList {

private E[] elements;

//數組的預設初始化值

private static final int DEFAULT_CAPACITY = 10;

public DynamicArray(int capacity) {

//如果傳入的capacity>預設初始值,取capacity,否則取預設值

capacity = Math.max(capacity, DEFAULT_CAPACITY);

//通過new Object[],動态數組可以實作多對象化

elements = (E[]) new Object[capacity];

}

public DynamicArray() {

this(DEFAULT_CAPACITY);

}

public E set(int index,E element){

//檢查索引是否合法

rangeCheck(index);

//

E old = elements[index];

elements[index] = element;

return old;

}

public E get(int index){

rangeCheck(index);

return elements[index];

}

public int indexOf(E element){

//如果元素為空,單獨判斷,防止NPE

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 ELEMENT_NOT_FOUND;

}

public void add(int index,E element){

//檢查索引是否合法

rangeCheckForAdd(index);

//檢查數組容量是否足夠

ensureCapacity(size + 1);

for (int i = size;i > index;i--){

elements[i] = elements[i - 1];

}

elements[index] = element;

size++;

}

public E remove(E element){

//調用indexOf擷取索引,通過索引删除指定元素

return remove(indexOf(element));

}

public E remove(int index){

//檢查索引是否合法

rangeCheck(index);

E old = elements[index];

for (int i = index + 1;i < size;i++){

elements[i - 1] = elements[i];

}

//将數組原來尾部最後的元素所在的位置置為null,釋放原來位址引用對應的對象記憶體

elements[--size] = null;

//檢測是否需要縮容

trim();

return old;

}

public void clear() {

for (int i = 0; i < size; i++) {

elements[i] = null;

}

size = 0;

}

private void ensureCapacity(int capacity){

int oldCapacity = elements.length;

//如果數組容量足夠,return

if (oldCapacity >= capacity) return;

//否則的話,數組擴容,數組擴容1.5倍

int newCapacity = oldCapacity + (oldCapacity >> 1);

E[] newElements = (E[]) new Object[newCapacity];

//将原有數組元素複制到新數組中

for (int i = 0;i < size;i++){

newElements[i] = elements[i];

}

//指向新數組

elements = newElements;

System.out.println(oldCapacity + "擴容為" + newCapacity);

}

@Override

public String toString() {

// size=3, [99, 88, 77]

StringBuilder string = new StringBuilder();

string.append("size=").append(size).append(", [");

for (int i = 0; i < size; i++) {

if (i != 0) {

string.append(", ");

}

string.append(elements[i]);

}

string.append("]");

return string.toString();

}

}

補充數組縮容

在每次删除數組元素時及清空數組時,進行縮容檢查

private void trim(){

int oldCapacity = elements.length;

int newCapacity = oldCapacity >> 1;

//如果元素的數量大于縮容後數組長度,或者小于初始量,不進行縮容操作

if (size >= (newCapacity) || size <= DEFAULT_CAPACITY) return;;

// 剩餘空間還很多

E[] newElements = (E[]) new Object[newCapacity];

for (int i = 0; i < size; i++) {

newElements[i] = elements[i];

}

elements = newElements;

System.out.println(oldCapacity + "縮容為" + newCapacity);

}

public void clear() {

// 數組清空,應該根據情況縮容,避免記憶體浪費

if (elements != null && elements.length > DEFAULT_CAPACITY) {

elements = (E[]) new Object[DEFAULT_CAPACITY];

}else {

for (int i = 0; i < size; i++) {

elements[i] = null;

}

}

size = 0;

}

全局的關系圖

java 定義動态數組_動手編寫—動态數組(Java實作)

聲明

個人能力有限,有不正确的地方,還請指正

文章為原創,歡迎轉載,注明出處即可

本文的代碼已上傳github,歡迎star