本帖最后由 龚冼敏老师 于 2016-4-22 22:57 编辑
在整个java 基础中,用到比较器的有两个地方,分别是TreeSet和TreeMap.
在学 TreeSet的时候,有几道练习有特殊的要求,需要TreeSet实现保留重复元素并排序.
举例 :
从键盘接收一个字符串 , 程序对其中所有字符进行排序,例如键盘输入: helloitcast
程序打印 :acehillostt,这个练习需要给TreeSet传入一个比较器,才能实现该需求.
结果 ,很多同学产生了一个错误的观念,他们认为,每次写比较器的时候,都需要保留其中的重复元素,所以每次写比较器的时候,都会习惯性的写成这样:
让比较器不会返回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中存储重复元素!
|