日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java集合——集合接口+迭代器接口

發布時間:2023/12/3 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java集合——集合接口+迭代器接口 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【0】README

0.1) 本文描述轉自 core java volume 1, 源代碼 diy 的, 旨在理解 java集合框架——集合接口+迭代器接口 的相關知識;
0.2) for full source code , please visit https://github.com/pacosonTang/core-java-volume/tree/master/chapter13


【1】將集合的接口與實現分離

1.1)java集合類庫將 接口與實現分離。 我們看一下, 隊列是如何分離的;
1.2)隊列接口指出可以再隊列的尾部添加元素, 在隊列的頭部刪除元素, 并可以查找隊列中元素的個數;

  • 1.2.1)一個隊列接口的最小形式類似下面這樣:
interface Queue<E> {void add(E element);E remove();int size; }
  • 1.2.2)隊列通常有兩種實現方式: 一種是使用循環數組, 另一種是使用鏈表;
  • 1.2.3)每一個實現都可以通過一個實現了 Queue接口的類表示:
class CircularArrayQueue<E> implements Queue<E> // not an actual library class {CircularArrayQueue(int capacity) {...}pubilc void add(E element) {...}public E remove() {...}public int size(){...}private E[] elements;private int head;private int tail; } class LinkedListQueue<E> implements Queue<E> // not an actual library class {LinkedListQueue() {}pubilc void add(E element) {...}public E remove() {...}public int size(){...}private Link head;private Link tail; }

Annotation)

  • A1)如果需要使用循環數組隊列: 可以使用 ArrayDeque 類;
  • A2)如果需要使用 一個鏈表隊列: 就直接使用 LinkedList 類, 這個類實現了 Queue接口;

1.3)使用接口類型存放集合的引用:

Queue<Customer> expressLane = new CircularArrayQueue<>(100); expressLane.add(new Customer("Harry"));
  • 1.3.1)只需要對程序的一個地方做出修改,即調用構造器的地方, 如果覺得LinkedListQueue是個更好的選擇,將代碼修改為:
Queue<Customer> expressLane = new LinkedListQueue<>(100); expressLane.add(new Customer("Harry")); // nothing changed
  • 1.3.2)因為循環數組要比鏈表效率高,因此多數人優先選擇循環數組;循環數組是一個有界集合, 即容量有限。如果程序中要收集的對象數量沒有上限, 就最好使用鏈表來實現;
  • 1.3.3)在研究API文檔時,發現另外一組名字為 Abstract開頭的類: 如, AbstractQueue, 這些類是為類庫實現者而設計的, 如果想要實現自己的隊列類,會發現擴展AbstractQueue類要比實現Queue接口中的所有方法要輕松得多;


【2】java類庫中的集合接口和迭代器接口

2.1)在java類庫中, 集合類的基本接口是 Collection 接口,有兩個基本方法:

public interface Collection<E> {boolean add(E element); Iterator<E> iterator(); }

對上述代碼的分析(Analysis):

  • A1)add方法: 用于向集合添加元素,如果添加元素確實改變了集合就返回ture, 否則返回false;如,如果試圖向集合中添加一個對象, 而這個對象在集合中已經存在, 這個添加請求就沒有實效了,因為集合中不允許有重復的對象;
  • A2)iterator方法:該方法用于返回一個實現了 Iterator接口的對象 。 可以使用這個迭代器對象依次訪問集合中的元素:

2.2)迭代器, Iterator接口包含3個方法:

public interface Iterator<E> {E next();boolean hasNext();void remove(); }
  • 2.2.1)通過反復調用 next方法, 可以逐個訪問集合中的每個元素。但是, 如果達到了集合的末尾,next方法將拋出一個 NoSuchElementException;因此,需要在 next之前調用 hasNext方法;
  • 2.2.2)看個荔枝:
Collection<String> c = ...; //集合 Iterator<String> iter = c.iterator(); //集合迭代器 while(iter.hasNext()) //判斷集合中是否還有下一元素 {String element = iter.next();do sth with element }

Attention)從Java SE 5.0 后, 可以使用for each循環表示上述操作:

for(String elements : c) {do sth with element }


對上述代碼的分析(Analysis):

  • A1)編譯器將簡單地將 “for each”循環翻譯為 帶有迭代器的循環;
  • A2)for each循環可以與任何實現了 Iterator接口的對象一起工作,這個接口只包含一個方法:
public interface Iterable<E> {Iterator<E> iterator(); }

Attention)Collection接口擴展了 Iterable 接口, 因此, 對于標準類庫中的任何集合都可以使用 for each;

  • 2.2.3)元素被訪問的順序取決于集合類型

    • 2.2.3.1)如果對 ArrayList進行迭代, 迭代器將從索引0開始;
    • 2.2.3.2)如果訪問 HashSet中的元素, 每個元素將會按照某種隨機的次序出現;雖然可以確定在迭代過程中能夠遍歷到集合中的所有元素, 但卻無法預知元素被訪問的順序;

      Annotation)編程老手會注意到: Iterator接口的next 和 hasNext方法 與 Enumeration 接口的nextElement 和 hasMoreElements 方法的作用一樣。 java集合類庫的設計者可以選擇使用Enumeration接口。但是, 它們不喜歡這個接口累贅的方法名, 于是引入了較短的方法名的新接口;
  • 2.2.4)java迭代器:應該將java迭代器認為是位于 兩個元素之間, 當調用next 方法時, 迭代器就越過下一個元素, 并返回剛剛越過的那個元素的引用;

Annotation)有用的類推:可以將Iterator.next 和 InputStream.read 看做是等效的。從數據流中讀取一個字節, 就會自動地消耗掉這個字節。下一次調用read將會消耗并返回輸入的下一個字節。用同樣的方式, 反復地調用next 就可以讀取集合中所有元素了;

2.3)刪除元素

  • 2.3.1)Iterator的remove方法 將會刪除上次調用next方法時返回的 元素。在大多數情況下,在決定刪除某個元素前應該先看一下這個元素是很具有實際意義的。然而, 如果想要刪除指定位置上的元素, 仍然需要越過這個元素。
  • 2.3.2)看個荔枝(如何刪除集合中第一個元素):
Iterator<String> it = c.iterator(); it.next(); // skip over the first element it.remove(); // now remove it
  • 你要記住, 要刪除某個元素, 你得要先越過這個元素;
  • 2.3.3)對next方法 和 remove方法的調用具有相互依賴性。 如果調用 remove 之前沒有調用next 將是不合法的。 如果這樣做, 會拋出一個 IllegalStateException 異常;
  • 2.3.4)看個荔枝: 如果想刪除兩個相鄰元素, 不能直接這樣調用:
it.remove(); it.remove(); //ERROR 正確的方法是: it.remove(); it.next(); it.remove();


2.4)泛型使用方法
* 2.4.1)由于Collection 和 Iterator 都是泛型接口,可以編寫操作任何集合類型的實用方法。看個荔枝:下面是一個檢測任意寄賀卡是否包含指定元素的泛型方法:

public static<E> boolean contains(Collection<E> e, Object obj) {for(E element : c)if(element.equals(obj))return true;return false; }
  • 2.4.2)事實上, Collection接口聲明了很多有用的方法, 所有的實現類都必須提供這些方法, 下面列舉了部分:
int size() boolean isEmpty() boolean contains(Object obj) boolean containsAll(Collection<?> c): 這個集合包含other 集合中的所有元素,則返回trueboolean equals(Object other) boolean addAll(Collection<? extends E> from) boolean remove(Object obj) boolean removeAll(Collection<?> c) void clear() :移除集合中的所有元素; boolean retainAll(Collection<?> c) : 從集合中移除所有與 other 集合中的元素不同的元素。如果這個調用改變了集合,返回trueObject[] toArray(); : 返回這個集合的對象數組; <T> T[] toArray(T[] arrtyToFill[]): 返回這個集合的對象數組。如果arrayToFill 數組足夠大, 就將集合中的元素填入這個數組中。 剩余空間填補 null ; 否則, 分配一個新數組, 其成員類型與 arrayToFill 的成員類類型相同, 其長度等于集合的大小, 并添入集合元素;
  • 2.4.3)AbstractCollection:當然, 如果實現 Collection接口的每個類都要提供如此多的例行方法是一件很煩人的事情。為了能夠讓實現者更容易地實現這個接口,java類庫提供了一個 類 AbstractCollection , 它將基礎方法 size 和 iterator 抽象化了;
    (我的理解為: 抽象類AbstractCollection實現部分的例行方法, 其他可變的方法交給用戶去實現)
public abstract class AbstractCollection<E> implements Collection<E> {...public abstract Iterator<E> iterator();public boolean contains(Object obj){for(E element: this) // calls iterator()if(element.equals(obj))return true;return false;}...... }

對以上代碼的分析(Analysis):

  • A1)一個具體集合類可以擴展 AbstractCollection類了;
  • A2)現在要由具體的集合類提供 iterator 方法, 而 contains 方法已由 AbstractCollection超類提供了;

總結

以上是生活随笔為你收集整理的java集合——集合接口+迭代器接口的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。