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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java集合——集合接口+迭代器接口 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【0】README

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


【1】將集合的接口與實(shí)現(xiàn)分離

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

  • 1.2.1)一個(gè)隊(duì)列接口的最小形式類似下面這樣:
interface Queue<E> {void add(E element);E remove();int size; }
  • 1.2.2)隊(duì)列通常有兩種實(shí)現(xiàn)方式: 一種是使用循環(huán)數(shù)組, 另一種是使用鏈表;
  • 1.2.3)每一個(gè)實(shí)現(xiàn)都可以通過(guò)一個(gè)實(shí)現(xiàn)了 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)如果需要使用循環(huán)數(shù)組隊(duì)列: 可以使用 ArrayDeque 類;
  • A2)如果需要使用 一個(gè)鏈表隊(duì)列: 就直接使用 LinkedList 類, 這個(gè)類實(shí)現(xiàn)了 Queue接口;

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

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


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

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

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

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

  • A1)add方法: 用于向集合添加元素,如果添加元素確實(shí)改變了集合就返回ture, 否則返回false;如,如果試圖向集合中添加一個(gè)對(duì)象, 而這個(gè)對(duì)象在集合中已經(jīng)存在, 這個(gè)添加請(qǐng)求就沒(méi)有實(shí)效了,因?yàn)榧现胁辉试S有重復(fù)的對(duì)象;
  • A2)iterator方法:該方法用于返回一個(gè)實(shí)現(xiàn)了 Iterator接口的對(duì)象 。 可以使用這個(gè)迭代器對(duì)象依次訪問(wèn)集合中的元素:

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

public interface Iterator<E> {E next();boolean hasNext();void remove(); }
  • 2.2.1)通過(guò)反復(fù)調(diào)用 next方法, 可以逐個(gè)訪問(wèn)集合中的每個(gè)元素。但是, 如果達(dá)到了集合的末尾,next方法將拋出一個(gè) NoSuchElementException;因此,需要在 next之前調(diào)用 hasNext方法;
  • 2.2.2)看個(gè)荔枝:
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循環(huán)表示上述操作:

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


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

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

Attention)Collection接口擴(kuò)展了 Iterable 接口, 因此, 對(duì)于標(biāo)準(zhǔn)類庫(kù)中的任何集合都可以使用 for each;

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

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

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

Annotation)有用的類推:可以將Iterator.next 和 InputStream.read 看做是等效的。從數(shù)據(jù)流中讀取一個(gè)字節(jié), 就會(huì)自動(dòng)地消耗掉這個(gè)字節(jié)。下一次調(diào)用read將會(huì)消耗并返回輸入的下一個(gè)字節(jié)。用同樣的方式, 反復(fù)地調(diào)用next 就可以讀取集合中所有元素了;

2.3)刪除元素

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


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

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)事實(shí)上, Collection接口聲明了很多有用的方法, 所有的實(shí)現(xiàn)類都必須提供這些方法, 下面列舉了部分:
int size() boolean isEmpty() boolean contains(Object obj) boolean containsAll(Collection<?> c): 這個(gè)集合包含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 集合中的元素不同的元素。如果這個(gè)調(diào)用改變了集合,返回trueObject[] toArray(); : 返回這個(gè)集合的對(duì)象數(shù)組; <T> T[] toArray(T[] arrtyToFill[]): 返回這個(gè)集合的對(duì)象數(shù)組。如果arrayToFill 數(shù)組足夠大, 就將集合中的元素填入這個(gè)數(shù)組中。 剩余空間填補(bǔ) null ; 否則, 分配一個(gè)新數(shù)組, 其成員類型與 arrayToFill 的成員類類型相同, 其長(zhǎng)度等于集合的大小, 并添入集合元素;
  • 2.4.3)AbstractCollection:當(dāng)然, 如果實(shí)現(xiàn) Collection接口的每個(gè)類都要提供如此多的例行方法是一件很煩人的事情。為了能夠讓實(shí)現(xiàn)者更容易地實(shí)現(xiàn)這個(gè)接口,java類庫(kù)提供了一個(gè) 類 AbstractCollection , 它將基礎(chǔ)方法 size 和 iterator 抽象化了;
    (我的理解為: 抽象類AbstractCollection實(shí)現(xiàn)部分的例行方法, 其他可變的方法交給用戶去實(shí)現(xiàn))
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;}...... }

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

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

總結(jié)

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

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。