Java 实现Comparable接口踩坑记录
来源:互联网 发布:数据库开发工具有哪些 编辑:程序博客网 时间:2024/06/07 03:48
好久没有写代码了,最近尝试写个A*算法练练手,过程中遇到了一些问题记录下来。
由于A*算法在获取当前格的时候取一个集合中的最小值,所以尝试使用TreeSet作为数据结构。
自定义类型实现了Comparable接口用以存放进TreeSet。
而实现的compareTo(Object o)方法的定义实在需要谨慎,因为我就在这遇到了一个毁天灭地大问题。
我的目标是让一个自定义类型根据某个变量的大小进行排序,想当然写了如下代码:
public int compareTo(Apath apath) { // TODO 自动生成的方法存根 if(F>apath.getF()){ return 1; }else if(F<apath.getF()){ return -1; }else { return 0; }}
问题来了,return 0意味着两个对象相等,比如我这里使用的TreeSet调用contains(Object o)方法时,两个不同对象的F相同时会当成同一个对象。愚蠢。
接下来一拍脑袋,加了一点东西,以为这样就没事了。
public int compareTo(Apath apath) { // TODO 自动生成的方法存根 if(F>apath.getF()){ return 1; }else if(F<apath.getF()){ return -1; }else if(this == apath){ return 0; }else { return 1; }}
这样子两个相同的对象才会真正被当成相同的处理,正如这句话所说。
强烈推荐(虽然不是必需的)使自然排序与 equals 一致。所谓与equals一致是指对于类 C 的每一个 e1 和 e2 来说,当且仅当 (e1.compareTo((Object)e2) == 0) 与e1.equals((Object)e2) 具有相同的布尔值时,类 C 的自然排序才叫做与 equals 一致 。
这下好了吧?看似Bug消灭了,其实只是隐藏的更深了!!
这时候我发现有时候TreeSet中会包含多个一样的对象,即contains(Object o)方法失效。找来找去,发现还是在自定义的CompareTo(Object o)函数的问题上。
通过了解,我知道了实际上TreeSet是二叉树实现,那么使用的必须是二叉搜索了。上面的代码在最后一个else里胡乱丢了一个return 1 ,实际上这棵树有可能是乱的。因为当两个对象F相同时,他们谁大于谁是不确定的!
你可以想象:
当 a1.F == a2.F
a1.compareTo(a2)==1
a2.compareTo(a1)==1
也就导致后来的有关二叉搜索的函数都乱套了。
最后改成了这样。所有对象之间的大小关系唯一确定才行。
说起来简单,马马虎虎导致的问题。
public int compareTo(Apath apath) { // TODO 自动生成的方法存根 if(F>apath.getF()){ return 1; }else if(F<apath.getF()){ return -1; }else if(this == apath){ return 0; }else if(this.hashCode() > apath.hashCode()){ return 1; }else { return -1; }}
这样一来,即使两个对象的参数完全一样,都能比较出大小了。
- Java 实现Comparable接口踩坑记录
- java 集合 实现comparable接口
- 《Effective java》读书记录-第12条-考虑实现Comparable接口
- Effective Java Item12-考虑实现Comparable接口
- Java朝花夕拾の实现Comparable接口
- java 对ArrayList排序,实现Comparable接口
- java 对ArrayList排序,实现Comparable接口
- JAVA内部比较器:实现Comparable接口
- effective java (12) 考虑实现Comparable接口
- 【JAVA 日常练习 13.10】+ comparable接口实现
- Effective Java读书笔记-考虑实现Comparable接口
- 实现Comparable接口
- 实现Comparable接口
- Comparable接口的实现
- Comparable<T>接口实现
- 考虑实现Comparable接口
- StudentTest实现Comparable接口
- 考虑实现Comparable接口。
- 论文阅读:ICML 2016 Large-Margin Softmax Loss for Convolutional Neural Networks
- 网络编程六:https请求(双向验证)
- 一篇让你真正理解 Laravel IoC 模式的文章
- sublimeText 搭建react-native 开发环境
- android应用方法数超出
- Java 实现Comparable接口踩坑记录
- Android 蓝牙技术 带你实现终端间数据传输
- 子页面eventMap管理事件绑定不起作用
- 图片横向滚动-兼容IE8和Chrome浏览器
- view的滑动讲解
- 1.4 起步 - 命令行
- Java进阶-----详解匿名内部类
- 语音播报TTS
- 机房收费系统---用户手册