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.mzph.cn/news/276568.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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;…

shell 练习3

1、编写脚本/root/bin/createuser.sh&#xff0c;实现如下功能&#xff1a;使用一个用户名做为参数&#xff0c;如果指定参数的用户存在&#xff0c;就显示其存在&#xff0c;否则添加之&#xff1b;显示添加的用户的id号等信息2、编写脚本/root/bin/yesorno.sh&#xff0c;提示…

两个数组结果相减_学点算法(三)——数组归并排序

今天来学习归并排序算法。分而治之归并算法的核心思想是分而治之&#xff0c;就是将大问题转化为小问题&#xff0c;在解决小问题的基础上&#xff0c;再去解决大问题。将这句话套用到排序中&#xff0c;就是将一个大的待排序区间分为小的待排序区间&#xff0c;对小的排序区间…

ASP记数器

这两天有好几个老的ASP网站要改&#xff0c;其中有要求加记数器&#xff0c;为图简单&#xff0c;就用文本文件的形式存储记数。以前用ifream的形式嵌入&#xff0c;不能很好的控制记数器显示的风格&#xff0c;现在改进了一下&#xff0c;可以很好的与嵌入板块风格结合了。把做…

[转] DevExpress 第三方控件汉化的全部代码和使用方法

DevExpress.XtraEditors.Controls 此控件包中包含的控件最多&#xff0c;包括文本框&#xff0c;下拉列表&#xff0c;按钮&#xff0c;等等 DevExpress.XtraGrid 网格 DevExpress.XtraBars 菜单栏 和 工具栏 DevExpress.XtraNavBar 导航条 DevExpress.XtraPr…

福音!微信个人公众号可以改名了!

微信个人公众号可以改名了&#xff01;&#xff01;&#xff01;今年&#xff0c;我们学校从景德镇陶瓷学院更名为景德镇陶瓷大学&#xff0c;但苦于微信限制&#xff0c;很多微信公众号无法更名。很多组织社团就放弃了原先的关注量&#xff0c;重新申请注册账号。当前我们的订…

js list删除指定元素_删除js数组中的指定元素,有这两步就够了

js数组是js部分非常重要的知识&#xff0c;有时我们有这么个需求js数组删除指定元素&#xff0c;先定义一个函数来获取删除指定元素索引值&#xff0c;然后用js数组删除的方法&#xff0c;来删除指定元素即可&#xff0c;就两步不难&#xff0c;很简单。1、JS的数组对象定义一个…

计算机协会丨让技能得到提升,让思维受到启迪

“ 各位2016级新生&#xff0c;新的学期马上就要开始了&#xff0c;学校的各个组织和社团你真的了解了吗&#xff1f;在眼花缭乱的社团里如何找到自己真正喜欢的呢&#xff1f;或许看完计算机协会的纳新微信你就都明白啦&#xff01;关键词&#xff1a;计算机协会景德镇陶瓷大学…

ondestroy什么时候调用_尾调用和尾递归

尾调用1. 定义尾调用是函数式编程中一个很重要的概念&#xff0c;当一个函数执行时的最后一个步骤是返回另一个函数的调用&#xff0c;这就叫做尾调用。注意这里函数的调用方式是无所谓的&#xff0c;以下方式均可&#xff1a;函数调用: func()方法调用: obj.method()call调用:…

dhl:使用return RedirectToAction()和 return view()

一个Action&#xff1a; Code/// <summary> /// Friend好友的地 /// </summary> /// <returns></returns> public ActionResult FriendFarm(string pid) {BLL.DTOFarm farm new AppleGrange.BLL.DTOFarm(pid); …

radio切换控制div显示_JavaScript连载31图片动态切换以及关闭图片案例

一、图标切换31.1点击那两个按钮可以做到轮番显示图片二、关闭图片案例31.2点击右上角的叉&#xff0c;图片会消失。三、源码&#xff1a;D31_iconSwitch.htmlD31_2_CloseImage.html地址:https://github.com/ruigege66/JavaScript/blob/master/D31_iconSwitch.htmlhttps://gith…

工作一年后,我有些感悟(写于2017年)

时间拉回到2016年5月23日&#xff0c;当天拍毕业照&#xff0c;晚上是大学毕业酒会&#xff0c;那一晚整个酒店都弥漫着伤感的气息。那一晚大家为了找KTV拖延到很晚&#xff0c;最后一群人选择来到了操场&#xff0c;凌晨两点多一群人还在操场上玩着游戏。5月25日离校&#xff…

PHP基础学习之数组使用要点

一、什么是PHP数组&#xff1f;数组 array 是一组有序的变量&#xff0c;其中每个变量都被称为一个元素。每个元素由一个特殊的标识符来区分&#xff0c;这个标识符称之为键&#xff08;也可以称之为下标&#xff09;。数组中的每个元素都包含两项&#xff1a;键和值。可以通过…

高考七年后、工作三年后的感悟

本打算端午假期发表这文章&#xff0c;后来因为文章还需要有些调整&#xff0c;工作日又比较忙&#xff0c;就到今天周三才发。随便写了近3000字&#xff0c;文章最后有免费送书活动&#xff0c;欢迎留言参与。又一年高考结束了。转眼高考过去七年了&#xff0c;工作了三年。很…

蚂蚁金服天街:OceanBase 在大促 5 年来的技术演进

为了与金融从业者、科技从业者共同探讨金融 业务的深层次问题&#xff0c;蚂蚁金服联手 TGO 鲲鹏会&#xff0c;在 12 月 8 日举办了「走进蚂蚁金服&#xff1a;双十一背后的蚂蚁金服技术支持」活动。蚂蚁金服高级技术专家天街为大家分享了《蚂蚁双 11 大促 OceanBase 核心技术…

学习 jQuery 源码整体架构,打造属于自己的 js 类库

虽然现在基本不怎么使用 jQuery了&#xff0c;但 jQuery流行 10多年的 JS库&#xff0c;还是有必要学习它的源码的。也可以学着打造属于自己的 js类库&#xff0c;求职面试时可以增色不少。本文章学习的是 v3.4.1版本。unpkg.com源码地址&#xff1a;https://unpkg.com/jquery3…

5分钟轻松教您如果组建100-500路大型拼接监控系统!

冰山融汇百家号17-07-2700:41大型监控系统如何组网&#xff0c;分布式还是集中式&#xff1f;可靠性与性价比又如何取舍&#xff1f;什么才是最合适的视频监控存储产品&#xff1f;在不同地区、行业的项目中&#xff0c;这些疑问均成为业主、专家、系统集成商等各方面共同关注的…

(转)mssql2005生成表字典

出处不详 CodeSELECT TOP 100 PERCENT --a.id, CASE WHEN a.colorder 1 THEN d.name ELSE END AS 表名, CASE WHEN a.colorder 1 THEN isnull(f.value, ) ELSE END AS 表说明, a.colorder AS 字段序号, a.name AS 字段名, CASE WHEN COLUMNPROPERTY(a.id, a.name, IsIdenti…

表操作

2019独角兽企业重金招聘Python工程师标准>>> 字段修改 alter table TA drop partition (day<2018-12-10); ALTER TABLE TB ADD COLUMNS (userStatus String) CASCADE; ALTER TABLE TC change appversion appCommonVersion String CASCADE; ALTER TABLE TD DROP C…