摘要:類屬性是基于數組實現的,其屬性有其中常量表示數組的基礎容量。表示數組表當前長度數組元素個數,作索引時,表示數組的最后一個元素,而表示新添加的項可以被放置的位置。
PS:如果覺得文章有什么地方寫錯了,哪里寫得不好,或者有什么建議,歡迎指點。
ArrayList 類提供了 List ADT 的可增長數組的實現。
一、自定義實現的 ArrayList 類 MyArrayList源碼鏈接:戳此進GitHub查看
MyArrayList 泛型類實現了 Iterable 接口從而可以擁有增強 for 循環(for each 循環)。
public class MyArrayList1. 類屬性implements Iterable { @Override public Iterator iterator() { return new ArrayListIterator(); } }
MyArrayList 是基于數組實現的,其屬性有:
private static final int DEFAULT_CAPACITY = 10; private int theSize; private AnyType[] theArrays;
其中常量 DEFAULT_CAPACITY 表示數組的基礎容量。theSize 表示數組表當前長度(數組元素個數),作索引時,A[theSize - 1] 表示數組的最后一個元素,而 A[theSize] 表示新添加的項可以被放置的位置。泛型數組 theArrays 為 MyArrayList 類的數組實現,即對 MyArrayList 對象的操作實際為對數組 theArrays 的操作。
2. 構造方法當實例化 MyArrayList 對象時,調用構造方法:
public MyArrayList(){ theArrays = (AnyType[])new Object[DEFAULT_CAPACITY]; doClear(); }
在構造方法中先實例化泛型數組 theArrays。由于泛型數組的創建是非法的,所以我們需要創建一個泛型類型限界的數組;即創建一個 Object[] 類型的數組,然后向泛型類型數組 AnyType[] 強制轉型。
然后調用 doClear() 方法對數組表進行清空、初始化的操作,此方法僅類內部可調用:
private void doClear(){ theSize = 0; expandCapacity(DEFAULT_CAPACITY); }
此處先設置 theSize = 0,然后調用 expandCapacity() 方法改變數組容量為基礎容量。(在 expandCapacity() 方法的實現中,若擴充的容量(參數)小于 theSize 時表示非法的操作。)
3. 成員方法數組擴容方法 expandCapacity() :
public void expandCapacity(int newCapacity){ if (newCapacity < theSize){ return; } // 數組容量的擴充: AnyType[] newArrays = (AnyType[])new Object[newCapacity]; // 利用 System.arraycopy() 方法拷貝數組 System.arraycopy(theArrays,0,newArrays,0,theSize); theArrays = newArrays; }
System.arraycopy() 方法:get 方法的實現
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
/** * 根據下標得到數組元素的值 */ public AnyType get(int idx){ if (idx <0 || idx >= theSize){ throw new ArrayIndexOutOfBoundsException(); } return theArrays[idx]; }set 方法的實現
/** * 根據下標設置數組元素的值 * 返回該下標元素的原值 */ public AnyType set(int idx,AnyType newVal){ if (idx <0 || idx >= theSize){ throw new ArrayIndexOutOfBoundsException(); } AnyType oldVal = theArrays[idx]; theArrays[idx] = newVal; return oldVal; }add 方法的實現
/** * 根據下標向數組插入新元素 */ public boolean add(int idx,AnyType newVal){ // 當 idx=theSize 時,在 A[theSize] 位置處插入元素 if (idx < 0 || idx > theSize){ throw new ArrayIndexOutOfBoundsException(); } // 數組滿時擴充容量 if (theArrays.length == theSize){ expandCapacity(theSize*2 + 1); } // 數組元素后移 for (int i=theSize;i>idx;i--){ theArrays[i] = theArrays[i-1]; } theArrays[idx] = newVal; theSize++; return true; } /** * 在數組末尾插入新元素 */ public boolean add(AnyType newVal){ add(theSize,newVal); return true; }remove 方法的實現
/** * 根據下標刪除元素 * 返回被刪除的元素 */ public AnyType remove(int idx){ if (idx < 0 || idx >= theSize){ throw new ArrayIndexOutOfBoundsException(); } // 數組元素前移 AnyType removedElem = theArrays[idx]; for (int i = idx; i < theSize-1; i++) { theArrays[i] = theArrays[i+1]; } theSize--; return removedElem; }4. Iterator 迭代器 關于 Iterator 接口
實現 Iterable 接口的集合必須提供 iterator 方法,該方法返回一個 Iterator (java.util.Iterator)類型的對象:
public interface Iterator{ boolean hasNext(); AnyType next(); void remove(); }
即每個集合均可通過 iterator 方法創建并返回給客戶一個實現 Iterator 接口的對象,并把 當前位置 的概念在對象內部存儲下來。根據當前位置項每次調用 hasNext() 來判斷是否存在下一項,調用 next() 來給出下一項,而 remove() 方法則刪除由 next() 方法最新返回的項(即當調用一次 remove() 后,直到對 next() 再調用一次后才能調用 remove() 方法)。例:
public staticvoid print(Collection coll){ Iterator itr = coll.iterator(); while(itr.hasNext()){ AnyType item = itr.next(); System.out.println(item); // itr.remove(); } }
Java 中的增強 for 循環(for each)底層即是通過這種迭代器模式來實現的,當使用增強 for 循環時也就是間接的使用 Iterator。
MyArrayList 中 Iterator 的實現import java.util.Iterator; import java.util.NoSuchElementException; public class MyArrayListimplements Iterable { ...... @Override public Iterator iterator() { return new ArrayListIterator(); } private class ArrayListIterator implements Iterator { // 初始時當前位置為 0 private int current = 0; @Override public boolean hasNext() { return current < theSize; } @Override public AnyType next() { if (!hasNext()){ throw new NoSuchElementException(); } return theArrays[current++]; } @Override public void remove() { /* 因為 remove() 方法有相同的,MyArrayList.this 表示外部類當前對象的一個引用 */ MyArrayList.this.remove(--current); } } }
iterator() 方法直接返回 ArrayListIterator 類的一個實例,該類是一個實現 Iterator 接口的類。ArrayListIterator 存儲當前位置的概念,并提供 hasNext()、next()、remove() 的實現。當前位置 表示要被查看的下一元素(的數組下標),因此初始化當前位置為 0。
其中,泛型類 ArrayListIterator 是一個 內部類,使用內部類的目的及優點:
next() 方法中使用當前位置作為下標訪問數組元素然后將當前位置向后推進,而迭代器中是沒有數組的,使用內部類可以訪問外部類的域 theArrays;
theArrays 是 MyArrayList 的私有域,使用內部類訪問可以很好的滿足面向對象編程的基本原則,即讓數據盡可能地隱藏;
滿足迭代器 Iterator 的特性,即當集合(外部類)不存在的時候,迭代器(內部類)也是不存在的。
二、MyArrayList 類各方法的算法分析因為 ArrayList 是基于數組實現的,所以和數組相似:ArrayList 的 get() 和 set() 方法花費常數時間 O(1);而使用 add() 和 remove() 方法時為了保持內存數據的連續性,需要做大量的數據搬移工作,其花費的時間代價為 O(n)。
歡迎您的點贊、收藏和評論!
(完)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74022.html
摘要:自定義類的概述自定義類的概述代碼映射成現實事物的過程就是定義類的過程。自定義類的格式自定義類的格式使用類的形式對現實中的事物進行描述。 01引用數據類型_類 * A: 數據類型 * a: java中的數據類型分為:基本類型和引用類型 * B: 引用類型的分類 * a: Java為我們提供好的類,比如說:Scanner,Random等。 * b: 我們自己創建的類...
摘要:加載因子是哈希表在其容量自動增加之前可以達到多滿的一種尺度。當哈希表中的條目數超出了加載因子與當前容量的乘積時,則要對該哈希表進行操作即重建內部數據結構,從而哈希表將具有大約兩倍的桶數。成員變量每個對由封裝,存在了對象數組中。 雖是讀書筆記,但是如轉載請注明出處 http://segmentfault.com/blog/exploring/ .. 拒絕伸手復制黨 LinkedLis...
摘要:在最近寫程序題的時候,需要存儲一個為為的后來需要根據的長度對從小到大進行排序。用代替,然后中的元素為配對類,變相實現了一個鍵對應一個值的集合,并且能夠排序。 在最近寫程序題的時候,需要存儲一個key為char,value為string的map,后來需要根據string的長度對map從小到大進行排序。 showImg(https://segmentfault.com/img/bVbiZz...
摘要:閱讀本文約分鐘處理戰艦游戲前言你聽說過有些程序員上班總是遲到,而下班又很準時嗎因為他們使用了。復現上一章我們的程序運行起來了,但是還存在一些低級或者嚴重的,即當用戶擊中一個坐標后可以重復擊殺來快速接受游戲。 閱讀本文約 6分鐘 ArrayList處理戰艦游戲BUG 前言 你聽說過有些程序員上班總是遲到,而下班又很準時嗎?因為他們使用了Java API。核心Java函數庫是由一堆等著被...
摘要:集合代表一個元素有序可重復的集合,集合中每個元素都有其對應的順序索引。集合默認按元素的添加順序設置元素的索引。 List集合代表一個元素有序、可重復的集合,集合中每個元素都有其對應的順序索引。List集合可以通過索引來訪問指定位置的集合元素。List集合默認按元素的添加順序設置元素的索引。 Java8改進的List接口和ListIterator接口 普通方法 List是有序集合,因此L...
閱讀 1164·2021-11-22 15:24
閱讀 4440·2021-09-23 11:51
閱讀 2302·2021-09-08 09:36
閱讀 3514·2019-08-30 15:43
閱讀 1295·2019-08-30 13:01
閱讀 1116·2019-08-30 12:48
閱讀 530·2019-08-29 12:52
閱讀 3366·2019-08-29 12:41