java - 比较器数据结构排序 - 如何在另一个字段上排序时保持插入顺序?
问题描述
我有一个数据结构,它需要一个可选Comparator
的自定义排序(在这种情况下它是 aTreeSet
但实际上没关系,我可以在PriorityQueue
不破坏我的代码的情况下换掉 a )。目前,它是按price
结构存储的对象上的字段排序的。
当 2 个对象的价格相同时,我想timestamp
成为决胜局,时间戳为System.CurrentTime
. 要在比较器中指定它,我必须使用:
if (Object1.getPrice == Object2.getPrice && Object1.Timestamp > Object2.Timestamp) return 1
问题是,当我这样做时,这会打破相等的情况,TreeSet.floor()
或者TreeSet.ceiling()
- 该方法不再识别 2 个对象的价格相同,但仍会识别价格是否更高/更低。我该如何减轻这种情况?
解决方案
由Comparator
您决定集合的顺序是什么(实际上也是它们的“唯一性”!)。
所以你必须决定对象是否相等:
- 如果价格相同
- 如果价格和时间戳相同
也许为这种不同的用途使用不同的数据结构将是一个选项或不同的选项,可以涵盖两者。取决于代码的其他要求和边界。
看看这里:https ://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html
基于 TreeMap 的 NavigableSet 实现。元素使用它们的自然顺序或在集合创建时提供的 Comparator 进行排序,具体取决于使用的构造函数。
所以你提供了比较器。
请注意,如果要正确实现 Set 接口,集合维护的顺序(无论是否提供显式比较器)必须与 equals 一致。(参见 Comparable 或 Comparator 以获得与 equals 一致的精确定义。)这是因为 Set 接口是根据 equals 操作定义的,但TreeSet 实例使用其 compareTo(或 compare)方法执行所有元素比较,所以两个从集合的角度来看,这种方法认为相等的元素是相等的。
因此,如果equals
Set 中已经有一个对象(咨询比较器),则需要再次添加它,因为它将根据顺序放置在 Set 中的相同位置(如果您不喜欢,请不要使用放)。它们应该以一致的方式实现(即使很难,编译器也不会强制执行)。因此,它没有直接equals
使用,而是使用了比较器。
在内部,比较器可以使用equals
对象的运算符(在 if 语句中,如if(obj1.equals(obj2)){return 0;}
)。
但是如何实现equals
- 在内部它将依赖于一些属性比较(就像你现在在比较器中所做的那样)。
如果你不喜欢你的数据结构可能不使用(树)集。根据需要,地图或列表可能会很好。
选择正确的集合:
http ://www.javapractices.com/topic/TopicAction.do?Id=65
==
对于和 之间的区别equals
:
==
正在比较引用,假设指向容器的指针,如果为 true,则它是同一个实例。equals
正在比较对象,可以说对象容器的内容,如果为真,则它具有相同的值(在其属性中)
但是外面可能有数百万篇关于它的令人筋疲力尽的文章。
注意: equals
对象的实现应该与 hashCode() 方法一致。对于 (Tree)Set,比较器的实现应该与equals
(也许使用类似的东西if(obj1.equals(obj2)){return 0;}
)一致。此外,其他Set
实现为此使用 hasCode()。
推荐阅读
- csv - 有没有办法在 Paraview 中自动加载 csv 文件?
- javascript - 地图功能与箭头功能反应
- reactjs - NextJs 中单页的多条路由
- c# - 使用动画C#更改网格的位置
- android - Flutter 文件选择器创建符号链接
- python - 根据条件生成熊猫数据框
- javascript - 如何修改此搜索表以遍历所有列
- apache-spark - 如何利用 Spark 的管道在字符串中查找短语然后添加特征类别?
- python - TypeError:列表索引必须是整数或切片,而不是 str | 姜戈 | 反应 | 邮差
- javascript - 将多维数组从 PHP 传递到 JavaScript