java queue set_Java学习笔记——浅谈数据结构与Java集合框架(第二篇、Queue、Set)...

江南好,何处异京华。

香散翠帘多在水,绿残红叶胜于花。无事避风沙。

——《纳兰词》

诗词再好,大图不能忘

上大图:

fe584a51e944d5a8d7a6fdd860718edf.png

先说说栈和队列:

栈就好比手枪的弹匣,你往里面压入子弹,最先压入的子弹就到了弹匣最底部的位置,最后压入的子弹在弹匣顶部。发射子弹的时候每次将弹匣顶部的子弹弹出发射。无法越过顶部子弹发射下面的子弹。

栈(stack)是限定仅在表尾进行插入和删除操作的线性表,LIFO

队列就跟上学那会儿排队打饭一样,但是不能加塞儿。

队列(queue)是只允许在队列一端进行插入操作,另一端进行删除操作的线性表,FIFO

这里要特别说明Java中的队列是双向队列(Deque),包括了栈和队列的所有方法

双向队列也分为两种,顺序结构和链式结构。咱们看Deque接口实现类的名字就能看出来ArrayDeque是顺序存储结构,LinkedList是链式存储结构

基本原理就不再赘述了,第一篇已经讲过了顺序结构线性表和链式结构线性表。这里的栈和队列并不是什么新东西,只是两种不同的思维方式,对应了各自不同的方法罢了。

上代码:

1 public classArrayDequeStackDemo {2

3 public static voidmain(String[] args) {4 ArrayDeque stack = new ArrayDeque<>();5 //以下均为栈操作,在逻辑上把队列想象成一个栈,FILO

6 stack.push("疯狂Java讲义");7 stack.push("轻量级Java EE 企业应用实战");8 stack.push("疯狂Android讲义");9 //[疯狂Android讲义, 轻量级Java EE 企业应用实战, 疯狂Java讲义]

10 System.out.println(stack);11

12 //“窥视”栈顶第一个元素,而不出栈。输出:疯狂Android讲义

13 System.out.println(stack.peek());14 //依然输出[疯狂Android讲义, 轻量级Java EE 企业应用实战, 疯狂Java讲义]

15 System.out.println(stack);16

17 //获取栈顶,并pop出栈。输出:疯狂Android讲义

18 System.out.println(stack.pop());19 //[轻量级Java EE 企业应用实战, 疯狂Java讲义]

20 System.out.println(stack);21 }22 }

1 public classArrayDequeQueueDemo {2

3 public static voidmain(String[] args) {4 ArrayDeque queue = new ArrayDeque<>();5 //以下均为队列操作,在逻辑上把队列想象成一个栈,FIFO

6 queue.offer("疯狂Java讲义");7 queue.offer("轻量级Java EE 企业应用实战");8 queue.offer("疯狂Android讲义");9 //[疯狂Java讲义, 轻量级Java EE 企业应用实战, 疯狂Android讲义]

10 System.out.println(queue);11

12 //“窥视”栈顶第一个元素,而不出栈。输出:疯狂Java讲义

13 System.out.println(queue.peek());14 //依然输出[疯狂Java讲义, 轻量级Java EE 企业应用实战, 疯狂Android讲义]

15 System.out.println(queue);16

17 //poll投票的意思,想象玩狼人杀投死第一个人,输出:疯狂Java讲义

18 System.out.println(queue.poll());19 //[轻量级Java EE 企业应用实战, 疯狂Android讲义]

20 System.out.println(queue);21 }22 }

队列和栈的操作基本上就是这些

再说说Set集合

Set集合就像一个袋子,里面装着若干元素,它们无序且不能重复。

HashSet是Set的实现类,HashSet中的元素无序且不可重复

上代码:

1 public classHashSetTest {2

3 public static voidmain(String[] args) {4 HashSet h = new HashSet<>();5 h.add(new ClassA());//A类重写equals(Object o),return true

6 h.add(new ClassA());//equals相等,hashCode不等

7 h.add(new ClassB());//重写hashCode(),return 1

8 h.add(new ClassB());//hashCode相等,equals不等

9 h.add(new ClassC());//重写equals(Object o),return true;重写hashCode(),return 2;

10 h.add(new ClassC());//并没有添加成功,hashCode和equals都相等,这两个对象在HashSet中相等

11 h.add(new ClassC2());//new ClassC2类,重写代码和ClassC一样,一样添加不了.说明hashCode只比较@后面的hashCode值,和@前面的东西无关

12 System.out.println(h);13 //只看包名后面的结果:ClassB@1,ClassB@1,ClassC@2,ClassA@15db9742,ClassA@6d06d69c

14 }15 }

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public classClassA {2

3 publicboolean equals(Object o){4 return true;5 }6 }7 public classClassB {8

9 public inthashCode(){10 return 1;11 }12 }13 public classClassC {14

15 public inthashCode(){16 return 2;17 }18 publicboolean equals(Object o){19 return true;20 }21 }22 public classClassC2 {23

24 public inthashCode(){25 return 2;26 }27 publicboolean equals(Object o){28 return true;29 }30 }

View Code

1、基础知识:HashSet判断连个元素相等的方法:hashCode值相等 && equals 为true。

HashSet集合里的元素都没有索引。当程序向HashSet中添加元素的时候,HashSet会根据该元素的hashCode值来计算它的存储位置。访问数据的时候HashSet先计算该元素的hashCode值,再到对应的位置取元素。

所以HashSet访问元素也是很快的。

2、使用HashSet时可能会重写hashCode方法,如果重写了equals方法或者hashCode方法可能会导致一些问题

上代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 import java.util.HashSet;2 import java.util.Iterator;3

4 public classHashSetTest2 {5

6 public static voidmain(String[] args) {7 HashSet h = new HashSet<>();8 h.add(new ClassR(1));9 h.add(new ClassR(2));10 h.add(new ClassR(3));11 h.add(new ClassR(4));12 h.add(new ClassR(4));//是不能加入相同元素的

13 System.out.println(h);14 h.remove(new ClassR(4));//可以这样删除

15 System.out.println(h);16 Iterator it =h.iterator();17 ClassR r = (ClassR)it.next(); //把第一个元素赋值给r

18 r.count = 2;//将集合中元素ClassR(1)值变成2,这样就和ClassR(2)重复了,hashCode和equals都相等

19 System.out.println(h);20 h.remove(new ClassR(2));//删除classR(2)

21 h.remove(new ClassR(1));//原来的1已经不是1了,现在集合中没有地址为ClassR(1)地址,值为1的元素,所以无法删除

22 System.out.println(h);//这里剩下的应该就是原来的ClassR(1)(现在count值变成了2)和ClassR(3)

23 System.out.println("h中是否包含count为2的对象?"+h.contains(new ClassR(2))24 + "\nh中是否包含count为1的对象?"+h.contains(new ClassR(1)));25 }26 }

View Code

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public classClassR {2

3 intcount;4 public ClassR(intcount){5 this.count =count;6 }7 publicString toString(){8 return "R[count:"+count+"]";9 }10 publicboolean equals(Object o){11 if (this ==o)12 return true;13 if (o != null && o.getClass() == ClassR.class) {14 ClassR r =(ClassR)o;15 return this.count ==r.count;16 }17 return false;18 }19 public inthashCode(){20 return this.count;21 }22 }

View Code

以上是重写hashCode和equals算法的例子,对比不重写hashCode和equals算法,代码用之前的把ClassR中的重写内容删除就行了。

如果不重写,那么new出来的对象都是不同的元素(至少表面上看是这样,遗憾的是hashCode算法是native方法,无需探知。这里假设元素不是很多的情况下hashCode不会重复),但是重写之后你会发现new出来的对象不仅hashCode会相等,甚至更改某对象属性(字段)后居然两个对象equals为true了。这将会导致HashSet无法准确访问该元素。

3、HashSet优点:HashSet可以自由增加自身长度,并且访问元素速度很快

4、HashSet有个子类叫LinkedHashSet.

LinkedHashSet继承了父类的算法和寻址方式,其新增功能是使用链表维护内部顺序。由于需要维护元素的插入顺序,LinkedHashSet性能略低于其父类HashSet,但是在迭代访问Set中全部元素时有很好的性能。

最后TreeSet是Set的另一个实现类,TreeSet中的元素是有序不可重复的。

1、自然排序

TreeSet会调用集合元素的compareTo(Object obj)方法比较元素之间的大小关系,然后将集合中元素按照升序排列,这就是自然排序

2、定制排序

可重写compareTo方法实现定制排序。

Set就说到这里吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值