關於Java的小知識集合之 ArrayList可變長陣列

ckxllf發表於2020-03-18

  特徵:

  陣列形式的操作方式,查詢效率高,但是刪除增加效率低

  底層是一個陣列形式,陣列:

  Object型別陣列

  方法:

  ArrayList中使用的方法基本上都是從List介面中遵從實現的方法.

  特徵:

  ensureCapacity(int minCapacity);

  判斷當前容量是否足夠

  trimToSize();

  截斷整個陣列容量 ==> size有效元素個數,有的位置可能沒儲存元素但還是佔用了空間,

  所以階段之後每個位置都有元素,不會有白白佔用空間的問題出現;

  時間換空間,空間換時間

  Constructor構造方法:

  add(E e);

  add(int index, E e);

  addAll(自定義ArrayList e);

  addAll(int index, 自定義ArrayList e);

  remove(Object obj);

  remove(int index);

  set(int index, E);

  E get(int index);

  int indexOf();

  int lastIndexOf();

  boolean contains(Object obj);

  boolean containsAll(自定義ArrayList型別 list);

  boolean isEmpty();

  int size();

  自定義ArrayList subList(int fromIndex, int endIndex);

  Object[] toArray();

  方法實現:

  package com.wcc.d_arraylist;

  import java.util.Arrays;

  /**

  * @Author kk

  * @Date 2020/3/16 18:42

  */

  public class MyArrayList {

  /**

  * 準備一個底層陣列,用於儲存資料內容

  */

  private Object[] elements;

  /**

  * 初始化預設容量

  */

  private static final int DEFAULT_CAPACITY = 10;

  /**

  * 最大陣列容量 , -8是為了騰出一定的空間,儲存陣列的必要內容

  */

  private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

  /**

  * 當前底層陣列中儲存的有效元素的個數

  */

  private int size = 0;

  /**

  * 無參構造方法,但是需要提供給陣列一個初始化容量來儲存必要的資料

  */

  public MyArrayList(){

  elements = new Object[DEFAULT_CAPACITY];

  }

  /**

  * 使用者指定儲存元素容量的初始化過程,要求使用者指定的容量範圍是有效的

  * @param initCapacity 使用者指定的初始化容量,但是不餓能小於0不能大於MAX_ARRAY_SIZE

  */

  public MyArrayList(int initCapacity){

  if(initCapacity <0 || initCapacity > MAX_ARRAY_SIZE){

  throw new IllegalArgumentException("IllegalArgumentException:" + initCapacity);

  }

  elements = new Object[initCapacity];

  }

  /**

  * 增加方法

  */

  /**

  * 新增元素到當前集合的末尾

  * @param e 要求是符合泛型約束的指定資料型別

  * @return 新增成功返回true

  */

  public boolean add(E e){

  //直接呼叫在指定下標位置新增元素的方法,只不過這裡指定下標位置就是尾插法下標位置

  return add(size, e);

  }

  /**

  * 在底層陣列的指定下標位置儲存對應元素

  * @param index 指定下標位置,不能超出有效範圍,0《=index《=size

  * @param e 符合泛型約束的資料類新

  * @return 新增成功返回true

  */

  public boolean add(int index, E e){

  //下標合法性判定

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

  throw new ArrayIndexOutOfBoundsException(index);

  }

  ensureCapacity(size + 1);

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

  elements[i + 1] = elements[i];

  }

  elements[index] = e;

  size += 1;

  return true;

  }

  /*

  * addAll方法

  * 1.需要得到新增集合中的元素內容,有效元素個數

  * 2.確認容量問題

  * 3.size = oldSize + newSize

  */

  /**

  * 新增另一個集合到當前集合的末尾

  * @param list MyArrayList型別,自定義ArrayList,要求儲存元素和當前集合一致,或者是其子類

  * @return 新增成功返回true新增失敗返滬false

  */

  public boolean addAll(MyArrayList list){

  Object[] array = list.toArray();

  int newSize = array.length;

  //size是原陣列容量,newSize是要新增的陣列的容量

  ensureCapacity(size + newSize);

  //elements.length是擴容後的陣列容量

  for(int i = 0; i

  //array尾插法到原陣列之後

  elements[i + size] = array[i];

  }

  return true;

  }

  public boolean addAll(int index, MyArrayList list){

  //這個方法沒寫完

  return true;

  }

  /**

  * 刪除指定元素

  * @param obj 要刪除的元素

  * @return 刪除成功返回true

  */

  public boolean remove(Object obj){

  //獲取要刪除的元素的下標

  int index = indexOf(obj);

  //呼叫下面的remove方法,刪除該下標的元素

  //如果刪除成功,下面的remove方法返回對應元素,然後null != 元素該方法返回值為true

  //如果刪除失敗返回null,然後null != null 該方法返回值為false

  return null != remove(index);

  }

  /**

  * 刪除指定下標元素

  * @param index

  * @return 刪除成功返回對應元素,刪除失敗返回null

  */

  public E remove(int index){

  if( -1 == index){

  return null;

  }

  E e = get(index);

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

  elements[i] = elements[i + 1];

  }

  elements[size - 1] = null;

  size -= 1;

  return e;

  }

  /**

  * 查詢指定下標的元素

  * @param index 指定的下標,但是不能超出有效下標

  * @return 返回元素

  */

  @SuppressWarnings("unchecked")

  public E get(int index){

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

  throw new ArrayIndexOutOfBoundsException(index);

  }

  //該方法返回的是E型別,而element陣列是Object型別,所以需要做一個強轉

  return (E) elements[index];

  }

  /**

  * 替換指定下標的元素

  * @param index 指定的下標,但是必須在有效範圍內

  * @param e 要替換的元素,符合泛型約束

  * @return 被替換的元素

  */

  public E set(int index, E e){

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

  throw new ArrayIndexOutOfBoundsException(index);

  }

  //獲取指定下標的元素

  E temp = get(index);

  //替換

  elements[index] = e;

  return temp;

  }

  /**

  * 判斷指定元素是否存在

  * @param obj 需要判斷的元素

  * @return 存在返回true 不存在返回false

  */

  public boolean contains(Object obj){

  //根據indexOf方法來判斷元素是否存在,如果元素存在,indexOf方法就會返回

  //該元素第一次的下標位置,肯定大於-1,然後返回true

  //如果不存在,indexOf返回-1,等於-1,返回false

  return indexOf(obj) > -1;

  }

  /**

  * 判斷指定list集合是否是原集合的子集合

  * @return

  */

  public boolean containsAll(){

  return true;

  }

  /**

  * 判斷集合是不是空集合

  * @return 如果為空返回true,否則返回false

  */

  public boolean isEmpty(){

  return size == 0;

  }

  /**

  * 獲取集合中有效元素的個數

  * @return 有效元素個數

  */

  public int size(){

  return size;

  }

  /**

  * 獲取當前集合的子集合,要頭不要尾

  * @param fromIndex fromIndex <= endIndex,但是不得小於0擷取開始的位置

  * @param endIndex endIndex >= fromIndex,小於等於size,擷取結束的位置

  * @return 擷取得到的MyArrayList子集合物件

  */

  MyArrayList subList(int fromIndex, int endIndex){

  if(fromIndex > endIndex || fromIndex < 0 || endIndex > size){

  throw new ArrayIndexOutOfBoundsException();

  }  鄭州人流多少錢

  MyArrayList listTemp = new MyArrayList<>(endIndex - fromIndex);

  for(int i = fromIndex; i < endIndex; i++){

  listTemp.add(this.get(i));

  }

  return listTemp;

  }

  /**

  * 查詢指定元素在集合中第一次出現的下標位置

  * @param obj 指定的元素

  * @return 返回值大於等於0表示找到元素,否則返回-1

  */

  public int indexOf(Object obj){

  int index = -1;

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

  if(obj.equals(elements[i])){

  index = i;

  break;

  }

  }

  return index;

  }

  /**

  * 查詢指定元素在集合中最後一次出現的下標位置

  * @param obj 指定的元素

  * @return 返回值大於等於0表示找到元素,否則返回-1

  */

  public int lastIndexOf(Object obj){

  int index = -1;

  for(int i = size - 1; i >= 0; i--){

  if(obj.equals(elements[i])){

  index = i;

  break;

  }

  }

  return index;

  }

  /**

  * 返回MyArrayList集合中所有有效元素的Object陣列

  * @return 包含集合所有元素的Object型別陣列

  */

  public Object[] toArray(){

  //size 是有效元素個數,透過該方法可以獲得一個只有當前陣列中有效元素個數的陣列

  return Arrays.copyOf(elements,size);

  }

  /*

  * 這裡需要一個類內可以使用的用於判定當前容量是否滿足新增要求的方法

  * 如果滿足直接進入新增模式,如果不滿足就執行grow方法,完成底層陣列的擴容問題

  */

  /**

  * 每一次新增元素,都需要進行容量判斷,如果滿足可以進行新增操作,不滿足需要執行grow方法

  * @param minCapacity 要求的最小容量

  */

  private void ensureCapacity(int minCapacity){

  if(minCapacity > elements.length){

  grow(minCapacity);

  }

  }

  /**

  * 底層陣列的擴容方法,原理是建立新陣列,移植資料,儲存陣列新地址

  * @param minCapacity 要求的最小容量

  */

  private void grow(int minCapacity){

  //1.獲取原陣列容量

  int oldCapacity = elements.length;

  //2.計算得到新陣列容量

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

  //oldCapacity >> 1 就是oldCapacity除以2

  //3.判斷新陣列容量是否滿足要求

  if(newCapacity < minCapacity){ //代表容量不足,新陣列容量還沒有達到最小的陣列容量要求

  newCapacity = minCapacity;

  }

  //新陣列容量是大於允許的最大陣列容量

  if(newCapacity > MAX_ARRAY_SIZE){

  //二次判斷minCapacity是否小於MAX_ARRAY_SIZE

  if(minCapacity < MAX_ARRAY_SIZE){

  //最小要求是不大於MAX_ARRAY_SIZE,程式碼可以執行

  newCapacity = minCapacity;

  } else{

  throw new OutOfMemoryError("Overflow MAX_ARRAY_SIZE");

  }

  }

  //4.使用陣列工具類方法完成操作

  elements = Arrays.copyOf(elements, newCapacity);

  }

  }


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945560/viewspace-2681099/,如需轉載,請註明出處,否則將追究法律責任。

相關文章