Java學習分享-->集合-->鏈表

來源:互聯網
上載者:User

標籤:http   情況   基礎   logs   結果   思考   移動   分享   隨機   

鏈表是一個有序集合,它將每個對象存放在獨立的結點中,每個結點還存放著下一個結點的引用。在Java中由於鏈表是雙向連結的,每個結點還存放著前一個結點的引用。

                                                  (圖片引自Java核心技術 卷1 基礎知識)

 

刪除鏈表中間的一個元素,只需要更新被刪除元素附近的結點。假設我們有三個結點,刪除第二個結點後,第一個結點將原本存放第二個結點的引用更新為第三個結點的引用(這裡對應我們前面提到的“每個結點還存放著下一個結點的引用”),而第三個結點將原本存放第二個結點的引用更新為第一個結點的引用(這裡對應我們前面提到的“每個結點還存放著前一個結點的引用”)。

                                                 (圖片引自Java核心技術 卷1 基礎知識)

 

正常調用add()方法是將元素添加進鏈表的尾部,但可能會出現把元素添加進鏈表中間的情況。這時就需要使用ListIterator來實現,從名稱上來我們知道這也是一種迭代器,不過這個迭代器中提供了一個add()方法(注意要和鏈表本身的add()方法分開理解)。調用迭代器的add()方法會在迭代器位置之前添加一個元素。而在另外一種Set類型中,由於其中的元素是無序的,其Iterator介面中就沒有add()方法。因此我們得出一個結論:“只有對自然有序的集合使用迭代器添加元素才有實際意義”。

 

那這一實現過程是怎樣的呢?首先我們需要明確要將新元素添加到鏈表中哪個已存在的元素之後,確定了位置之後利用迭代器的next()方法越過到已存在的元素之後,再通過調用迭代器的add()方法就可以把新元素添加到鏈表的指定位置。

 

在明確了上面的操作步驟後,有以下幾個問題可以來思考下?

①需要向鏈表的表頭添加元素

   1)我們可以在拿到剛剛返回的ListIterator對象後就調用迭代器的add()方法,以下為example

        List<String> list = new LinkedList<String>();        list.add("Andy");                ListIterator<String> iterator = list.listIterator();        iterator.add("Amy");                while (iterator.hasNext()) {            //這裡輸出的結果是Andy            System.out.println(iterator.next());        }                iterator = list.listIterator();                while (iterator.hasNext()) {            //這裡會輸出兩次,一次是Amy,一次是Andy            System.out.println(iterator.next());        }

為什麼第一個while迴圈中的println只輸出一次,而且輸出的還是Andy?

根據我們前面提到的“調用迭代器的add()方法會在迭代器位置之前添加一個元素”,在我們第一次拿到這個迭代器對象的引用時,迭代器的位置在Andy這個元素前面,通過調用迭代器的add()方法,Amy這個元素被添加到了迭代器所在位置的前面,這樣在執行hasNext()方法時,迭代器對象中還有可供訪問的元素Andy,返回true。再調用next()就返回了元素Andy的引用。

而在執行第二個while之前,重新拿到了迭代器對象的引用,此時迭代器的位置就位於Amy之前,由於迭代器對象中有兩個可供訪問的元素,因此println分別列印出了Amy和Andy。

 

②需要向鏈表的表尾添加元素

   1)直接調用鏈表本身的add()方法

   2)當迭代器的hasNext()方法返回false時,這說明迭代器已經越過鏈表的最後一個元素,再調用迭代器的add()方法

        List<String> list = new LinkedList<String>();        list.add("Andy");                ListIterator<String> iterator = list.listIterator();                while (iterator.hasNext()) {            iterator.next();        }                iterator.add("Amy");                iterator = list.listIterator();                while (iterator.hasNext()) {            System.out.println(iterator.next());        }

 

③鏈表中有多少個位置是可以添加元素的

 如果鏈表中有n個元素,那麼就會有n+1個位置可以添加元素。例如鏈表中有AB兩個元素,那麼A的前面、AB的中間、B的後面都是可以添加元素的。

 

我們前面提到的add()方法(這裡指鏈表本身的add()方法),是向鏈表的尾部添加元素。鏈表中還有一個set()方法,它是做什麼用的呢?set()方法會將傳入的新元素取代調用next()或previous()方法返回的元素,此時這個鏈表就被修改了。需要額外說明的是add()、remove()方法是對鏈表結構性的修改,而set()方法不被視為結構性修改。

 

鏈表不支援快速隨機訪問,如果要查看鏈表中的第n個元素,就必須從頭開始,越過n-1個元素。這意味著如果你使用get(2)來訪問鏈表中的第三個元素,就必須越過前兩個元素。如果要訪問鏈表中第四個元素呢?get(3)這種方式好像可行,雖然它確實也訪問到了第四個元素,但這一過程付出了越過前三個元素的代價。

 

想一想如果使用迭代器呢?當我們用迭代器訪問到鏈表中第三個元素後,再去訪問第四個元素會這麼麻煩嗎?

不會,因為此時迭代器只需要再向後移動,越過第四個元素,就能返回剛剛所越過的這個元素的引用。

 

鑒於此如果你需要通過整數索引來訪問元素,那麼就不應該選用鏈表。

 

那麼說了這麼多,我們在什麼情境下選擇鏈表呢,唯一理由就是想要盡量減少在列表中間插入或刪除元素所付出的代價。

 

 

最後附幾個與鏈表有關的筆試題:

一、請寫出println列印的結果

        LinkedList<String> list = new LinkedList<String>();        list.add("one");        list.add("two");        list.add("three");        list.add("four");        list.add("five");
ListIterator<String> iteratorOne = list.listIterator(2); ListIterator<String> iteratorTwo = list.listIterator(iteratorOne.nextIndex());
if (iteratorTwo.hasNext()) { System.out.println(iteratorTwo.next()); }

 

二、請寫出各println列印的結果

        List<String> a = new LinkedList<>();        a.add("Amy");        a.add("Carl");        a.add("Erica");                List<String> b = new LinkedList<>();        b.add("Bob");        b.add("Doug");        b.add("Frances");        b.add("Gloria");                ListIterator<String> aIter = a.listIterator();        Iterator<String> bIter = b.iterator();                while (bIter.hasNext()) {            if (aIter.hasNext()) aIter.next();            aIter.add(bIter.next());        }                System.out.println(a);        bIter = b.iterator();                while (bIter.hasNext()) {            bIter.next();                        if (bIter.hasNext()) {                bIter.next();                bIter.remove();            }        }                System.out.println(b);                a.removeAll(b);                System.out.println(a);

Java學習分享-->集合-->鏈表

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.