A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© duanshengqiang 中级黑马   /  2016-4-28 23:28  /  556 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 龚冼敏老师 于 2016-4-22 22:57 编辑


在整个java基础中,用到比较器的有两个地方,分别是TreeSetTreeMap.
在学TreeSet的时候,有几道练习有特殊的要求,需要TreeSet实现保留重复元素并排序.
举例:
从键盘接收一个字符串, 程序对其中所有字符进行排序,例如键盘输入: helloitcast
程序打印:acehillostt,这个练习需要给TreeSet传入一个比较器,才能实现该需求.
[size=0.83em]图片1.png (9.78 KB, 下载次数: 0)
下载附件  [url=]保存到相册[/url]
[color=rgb(153, 153, 153) !important]6 天前 上传




结果,很多同学产生了一个错误的观念,他们认为,每次写比较器的时候,都需要保留其中的重复元素,所以每次写比较器的时候,都会习惯性的写成这样:

让比较器不会返回0. 这个比较器使用在TreeSet中并不会出现太大的问题,最多就是有重复元素,但是用在TreeMap中就有一个很大的问题出现了.
例如: 定义一个TreeMap,键为String,存储学生姓名,值为Integer,存储学生年龄,需求按字符串字典顺序的倒序排序.
正常情况下,代码应该如下:

但是学生习惯性保留重复元素,写成了这样:

存储元素的过程是没有问题的:



但是在通过键来获取对应的值的时候就出问题了:

结果是这样的:


得到的值全部是null

这是为什么呢?

这就要分析一下TreeMap集合中的get(Object key)方法了,看看它是如何根据key返回value.
首先,通过查看源码:

发现它其实是调用了一个叫getEntry()的方法,我们再跟进去看看:

这里面第一句代码,就是判断是否有比较器,如果有,调用getEntryUsingComparator(key)这个方法,很明显是有比较器的,所以我们不用再看下面的代码了,直接进入getEntryUsingComparator(key)方法:

从红线框出来的地方可以看得出来,只有当比较器返回0的时候,才会返回p这个对象.而之前我们传进来的比较器永远不会返回0,所以,get方法自然也就获取不到任何的值了,只能得到null.
SO,建议大家在写比较器的时候,不要盲目的根据从前的经验来写,一定要根据需求来.更加不要在TreeMap中存储重复元素!

1 个回复

倒序浏览
谢谢分享,一起加油
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马