java 容器_我也來聊聊,JAVA容器與迭代器

30bc6f80b78d0240bf50faecc9a3f80e.png

java的容器與迭代器是一個老生常談的話題了。

本文旨在與大家分享一些關于雙向鏈表與迭代器的運用小技巧,并希望本篇文章的內容能夠在項目中給你帶來幫助。

Stack與LinkedList

Stack是一個LIFO(后進先出)的容器。若要在java中定義一個Stack應該怎么辦?

也許你馬上會想到,java中對Stack類型的容器提供了源生支持,所以我們使用jdk包中提供的Stack類不就解決問題了嗎?

是的,這是很合理的思路。重復造輪子不是java的風格。那么就讓我們來看看源生的Stack容器應該如何使用。

先來一睹jdk中的源生Stack容器類:

* @author Jonathan Payne * @since JDK1.0 */publicclass Stack extends Vector { /** * Creates an empty Stack. */ public Stack() { } /** * Pushes an item onto the top of this stack. This has exactly * the same effect as: * 
 * addElement(item)
* * @param item the item to be pushed onto this stack. * @return the item argument. * @see java.util.Vector#addElement */ public E push(E item) { addElement(item); return item; } ....... ..... ... .

嗯?等等,Stack繼承自Vector?!

糟了!我們僅僅想要一個單純的LIFO容器,而大名鼎鼎的Vector不僅速度慢還帶有一堆我們不需要的“特性”,繼續使用源生的Stack顯然不是一個好的選擇。

這下可棘手了,我們現在要如何實現一個Stack呢?

ad436333e2cd21335da61d271e15fa6e.png

LinkedList

LinkedList是一個雙向鏈表。關于它,想必不用介紹太多,光看名字就應該能夠猜到,你想要的數據結構它應該都能實現。

所以,我們是不是可以通過LinkedList來實現一個自己的Stack類呢?

import java.util.LinkedList;public class Stack {  // 容器 private LinkedList lt = new LinkedList();  // 模擬棧的push方法 public void push(T e) { // 壓棧 lt.addLast(e); } // 模擬棧的pop方法 public T pop() { // 彈棧 return lt.removeLast(); } // 模擬棧的peek方法 public T peek() { // 取得棧頂元素 return lt.getLast(); } public boolean isEmpty() { return lt.isEmpty(); } public static void main(String[] args) { Stack sk = new Stack(); sk.push("hello"); sk.push("world"); System.out.println(sk.pop()); System.out.println(sk.pop()); }}---------------------worldhello

太好了。通過LinkedList,我們模擬了一個LIFO數據結構的實現,并且這個類的名字也叫做Stack。

除此之外他還沒有Vector的一大堆“特性”。這就是我們需要的單純的LIFO容器。

迭代器

在上一小節,我們實現了我們自己的LIFO容器。在這一小節,我們想辦法讓這個LIFO容器變得更“完美”一些。

在Java中,任何容器都屬于可迭代對象,且能被foreach所迭代。

顯然,我們創造的Stack容器目前還未擁有迭代器特征。由于追求完美和代碼潔癖是一個合格的程序員所應該具有的素養,所以接下來讓我們對這個Stack進行一點小小的改造。

import java.util.Iterator;import java.util.LinkedList;// 繼承Iterable接口,使其成為可迭代對象。public class Stack implements Iterable {  // 容器 private LinkedList lt = new LinkedList();  // 模擬棧的push方法 public void push(T e) { // 壓棧 lt.addLast(e); } // 模擬棧的pop方法 public T pop() { // 彈棧 return lt.removeLast(); } // 模擬棧的peek方法 public T peek() { // 取得棧頂元素 return lt.getLast(); } public boolean isEmpty() { return lt.isEmpty(); }  // 可迭代對象的標準迭代方法 @Override public Iterator iterator() { return lt.iterator(); } public static void main(String[] args) { Stack sk = new Stack(); sk.push("hello"); sk.push("world"); // 通過foreach迭代對象(內部通過獲取迭代器進行迭代) for (String s : sk) { System.out.println(s); }  // 顯示的通過獲取Stack迭代器進行迭代 Iterator skit = sk.iterator(); while (skit.hasNext()) { System.out.println(skit.next()); }  System.out.println(sk.pop()); System.out.println(sk.pop()); }}---------------------helloworldhelloworldworldhello

現在,Stack是一個標準的LIFO容器了。他就像其他的源生java容器一樣,是一個可迭代對象并且能夠被foreach所迭代。任何一個Java程序員,都能夠像使用其他源生容器一樣使用我們的自定義Stack容器了!

反向迭代

好景不長。

正當你在項目中愉快的使用上面的Stack容器解決一個又一個需求時,難題出現了。

業務方提出了一個討人厭的需求,它需要反向遍歷Stack容器。而追求嚴謹優雅的你,絕對不會允許使用for循環去遍歷容器的這種low逼方式出現。

看來只好再對Stack容器的功能進行一些增強了。

import java.util.Iterator;import java.util.LinkedList;// 繼承Iterable接口,使其成為可迭代對象。public class Stack implements Iterable {  // 容器 private LinkedList lt = new LinkedList();  // 模擬棧的push方法 public void push(T e) { // 壓棧 lt.addLast(e); } // 模擬棧的pop方法 public T pop() { // 彈棧 return lt.removeLast(); } // 模擬棧的peek方法 public T peek() { // 取得棧頂元素 return lt.getLast(); } public boolean isEmpty() { return lt.isEmpty(); } // 可迭代對象的標準迭代方法 @Override public Iterator iterator() { return lt.iterator(); } // 返回一個可迭代對象。重寫可迭代對象的iterator方法,返回重寫了next()方法的迭代器對象。 public Iterable reversed() { return new Iterable() { public Iterator iterator() { return new Iterator() { private int current = lt.size() - 1;  // 實現hasNext方法 @Override public boolean hasNext() { return current >= 0; }  // 實現next方法,實現反向迭代 @Override public T next() { if (!hasNext()) { return null; } // 先輸出結果再-- T element = lt.get(current--); return element; }  // 實現remove方法。remove掉最新迭代出的對象。(與源生容器的迭代器實現保持一致) @Override public void remove() { lt.remove(current + 1); } }; } }; } public static void main(String[] args) { Stack sk = new Stack(); sk.push("hello"); sk.push("world"); for (String s : sk) { System.out.println(s); }  Iterator skit = sk.iterator(); while (skit.hasNext()) { System.out.println(skit.next()); }  // 通過foreach反向迭代sk for (String s : sk.reversed()) { System.out.println(s); } // 顯示的調用反向迭代器反向迭代sk Iterator reversedSkit = sk.reversed().iterator(); while (reversedSkit.hasNext()) { System.out.println(reversedSkit.next()); reversedSkit.remove(); }  if (!sk.isEmpty()) { System.out.println(sk.pop()); System.out.println(sk.pop()); } else { System.out.println("容器為空"); } }}---------------------helloworldhelloworldworldhelloworldhello容器為空

現在的Stack容器不僅是一個可迭代對象。通過調用reversed()方法還能支持反向迭代。利用這個容器不僅能解決問題,還能讓解決問題的方式變得更優雅。真棒!

總結

大多數情況下,我認為都應該使用LinkedList來實現Stack。同理LinkedList也能夠用來實現Queue。不過,需要注意的是通過這種方法實現的容器,依然和java中其他容器一樣,默認情況下在并發狀態中是不安全的。

并且,對于自己實現的容器,盡量通過迭代器設計模式對其進行功能增強,以符合java Collection的標準,并滿足項目中的需求。

6ae20a3c4d10ea8819939ed3345109ee.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/276568.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276568.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276568.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

VS2005調試時變慢解決辦法

vs2005生成代碼以及調試運行時,如果設置斷點系統運行非常緩慢,從網上查閱一些資料后解決: 主要解決辦法是: 打開VS2005菜單項"工具"---->"導入導出設置"----->"重置所有設置" 本文參考:http:…

apache目錄的訪問控制

轉載鏈接&#xff1a;http://blog.sina.com.cn/s/blog_7be8a2150100trml.html 1.根目錄的訪問控制 DocumentRoot "/var/www/html" <Directory /> Options FollowSymLinks AllowOverride None </Directory> 解釋一下&#xff1a; <Dir…

廣東高院駁回快播對深圳市場監管局2.6億罰款案上訴

雷帝網 樂天 12月29日報道據廣東高院官方微信消息&#xff0c;廣東省高級人民法院對深圳市快播科技有限公司&#xff08;簡稱快播&#xff09;訴深圳市市場監督管理局&#xff08;簡稱市場監管局&#xff09;著作權行政處罰糾紛案作出終審宣判&#xff0c;駁回上訴&#xff0c;…

【Vegas原創】恢復Oracle Package的笨方法

imp沒有恢復package的參數&#xff0c;所以&#xff0c;只能用笨辦法&#xff1a;rowsn&#xff0c;只導入表結構和物件。 步驟&#xff1a; 1&#xff0c;dbca新建一個test數據庫&#xff1b; 2&#xff0c;新增user&#xff0c;表空間&#xff0c;給user賦予權限 3&#xff0…

python enumerate函數_關于python中enumerate和zip函數的用法及舉例

關于python中enumerate和zip函數的用法及舉例關于enumerate函數&#xff1a;enumerate函數可以同時返回列表或元組等可迭代對象的下標和內容&#xff0c;但實際上&#xff0c;enumerate函數實際返回的是一個enumerate類型的可迭代對象&#xff0c;下面是用法舉例&#xff1a;se…

php 解析xml 的四種方法(轉)

轉載鏈接&#xff1a;http://www.cnblogs.com/likwo/archive/2011/08/24/2151793.html XML處理是開發過程中經常遇到的&#xff0c;PHP對其也有很豐富的支持&#xff0c;本文只是對其中某幾種解析技術做簡要說明&#xff0c;包括&#xff1a;Xml parser, SimpleXML, XMLReader,…

Golang 微服務系列 go-kit(Log,Metrics,Tracing)

go-kit Log & Metrics & Tracing 微服務監控3大核心 Log & Metrics & Tracing Log Log 模塊源碼有待分析&#xff08;分析完再補上&#xff09; Metrics 主要是封裝 Metrics 接口&#xff0c;及各個 Metrics(Prometheus,InfluxDB,StatsD,expvar) 中間件的封裝。…

GDI+

載解壓GDI開發包&#xff1b; 2&#xff0e; 正確設置include & lib 目錄&#xff1b; 3&#xff0e; stdafx.h 添加&#xff1a; #ifndef ULONG_PTR #define ULONG_PTR unsigned long* #endif #include <gdiplus.h> 4&#xff0e; 程序中添加GDI的包含文件gdip…

shell 練習3

1、編寫腳本/root/bin/createuser.sh&#xff0c;實現如下功能&#xff1a;使用一個用戶名做為參數&#xff0c;如果指定參數的用戶存在&#xff0c;就顯示其存在&#xff0c;否則添加之&#xff1b;顯示添加的用戶的id號等信息2、編寫腳本/root/bin/yesorno.sh&#xff0c;提示…

HTML5文件實現拖拽上傳

轉載鏈接&#xff1a;http://www.cnblogs.com/caonidayecnblogs/archive/2010/09/09/1821925.html 通過HTML的文件API &#xff0c;Firefox、Chrome等瀏覽器已經支持從操作系統直接拖拽文件&#xff0c;并上傳到服務器。 相對于使用了十多年的HTML表單&#xff0c;這是一個革命…

兩個數組結果相減_學點算法(三)——數組歸并排序

今天來學習歸并排序算法。分而治之歸并算法的核心思想是分而治之&#xff0c;就是將大問題轉化為小問題&#xff0c;在解決小問題的基礎上&#xff0c;再去解決大問題。將這句話套用到排序中&#xff0c;就是將一個大的待排序區間分為小的待排序區間&#xff0c;對小的排序區間…

python實習生面試題_大數據分析實習生面試題庫

原標題&#xff1a;大數據分析實習生面試題庫大數據分析是一個有吸引力的領域&#xff0c;因為它不僅有利可圖&#xff0c;而且您有機會從事有趣的項目&#xff0c;而且您總是在學習新事物。如果您想從頭開始&#xff0c;請查看大數據分析實習生面試題庫以準備面試要點。大數據…

JavaScript編程語言 基礎 (1)

問題&#xff1a;什么是web前端前端&#xff1a;指界面&#xff0c;計算機&#xff08;PC&#xff09;軟件桌面的界面&#xff1b; 計算機端的瀏覽器界面&#xff1b; 移動端的軟件&#xff08;app&#xff09;界面&#xff1b; 移動端的瀏覽器界面。HtmlcssJavaScript 使用網頁…

shell結合expect寫的批量scp腳本工具

轉載鏈接&#xff1a;http://www.jb51.net/article/34005.htm expect用于自動化地執行linux環境下的命令行交互任務&#xff0c;例如scp、ssh之類需要用戶手動輸入密碼然后確認的任務。有了這個工具&#xff0c;定義在scp過程中可能遇到的情況&#xff0c;然后編寫相應的處理語…

ASP記數器

這兩天有好幾個老的ASP網站要改&#xff0c;其中有要求加記數器&#xff0c;為圖簡單&#xff0c;就用文本文件的形式存儲記數。以前用ifream的形式嵌入&#xff0c;不能很好的控制記數器顯示的風格&#xff0c;現在改進了一下&#xff0c;可以很好的與嵌入板塊風格結合了。把做…

php利用openssl實現RSA非對稱加密簽名

轉載鏈接&#xff1a;http://liuxufei.com/weblog/jishu/376.html 1. 先用php生成一對公鑰和私鑰 $res openssl_pkey_new(); openssl_pkey_export($res,$pri); $d openssl_pkey_get_details($res); $pub $d[key]; var_dump($pri,$pub); 2. 保存好自己的私鑰&#xff0c;把公…

[轉] DevExpress 第三方控件漢化的全部代碼和使用方法

DevExpress.XtraEditors.Controls 此控件包中包含的控件最多&#xff0c;包括文本框&#xff0c;下拉列表&#xff0c;按鈕&#xff0c;等等 DevExpress.XtraGrid 網格 DevExpress.XtraBars 菜單欄 和 工具欄 DevExpress.XtraNavBar 導航條 DevExpress.XtraPr…

QPM 性能監控組件總篇

QPM &#xff08;Quality Performance Monitor&#xff09; 是一個質量性能監控組件&#xff0c;可以很方便的查看當前 App 的性能和常用數據。目前主要運行在 Android 平臺上&#xff0c;通過集成 QPM 組件&#xff0c;可以在 App 中通過懸浮窗可視化相關實時數據。意在幫助廣…

福音!微信個人公眾號可以改名了!

微信個人公眾號可以改名了&#xff01;&#xff01;&#xff01;今年&#xff0c;我們學校從景德鎮陶瓷學院更名為景德鎮陶瓷大學&#xff0c;但苦于微信限制&#xff0c;很多微信公眾號無法更名。很多組織社團就放棄了原先的關注量&#xff0c;重新申請注冊賬號。當前我們的訂…

js list刪除指定元素_刪除js數組中的指定元素,有這兩步就夠了

js數組是js部分非常重要的知識&#xff0c;有時我們有這么個需求js數組刪除指定元素&#xff0c;先定義一個函數來獲取刪除指定元素索引值&#xff0c;然后用js數組刪除的方法&#xff0c;來刪除指定元素即可&#xff0c;就兩步不難&#xff0c;很簡單。1、JS的數組對象定義一個…