java - Java Comparator 不比较每个对象
问题描述
我对 Java 有一些复杂的情况Comparator
。所以我有一个父节点,它有一个子节点列表。我想对这些孩子进行排序,从表面上看似乎很简单,但是当Comparator
排序时它只检查某些对象与某些对象,然后我想它推断对象的位置,比如 if a
is before d
,f
is after d
, b
is befored
哪个意思b
是 before f
。
以下是我当前设置的示例。我有一个父节点a
,有 4 个子节点b
, e
, l
, g
。当我对这些孩子进行排序时,我希望顺序是b
, g
, l
, e
,所以按字母排序并始终确保父节点排在第一位。
(请原谅劣质图)
很简单,我有一个Node
类,它包含一个 ID,所以它是字母,然后是孩子的列表。
public class Node {
private char id;
private Node parent;
private List<Node> children = new ArrayList<>();
public Node(char id) {
this.id = id;
}
public void addChild(Node child) {
this.children.add(child);
}
public List<Node> getChildren() {
return children;
}
public char getId() {
return id;
}
public void setParent(Node parent) {
this.parent = parent;
}
public Node getParent() {
return parent;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public boolean equals(Object obj) {
return ((Node) obj).getId() == this.id;
}
}
然后我有一个NodeComparator
类,它首先检查节点是否是你的孩子,然后如果他们是你先去,反之亦然,然后按字母顺序排列。
@Override
public int compare(Node o1, Node o2) {
if (o1.getChildren().contains(o2)) {
return -1;
}
if (o2.getChildren().contains(o1)) {
return 1;
}
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int firstNodeIndex = -10;
int secondNodeIndex = -10;
for (int i = 0; i < alphabet.length(); i++) {
if (alphabet.charAt(i) == o1.getId()) {
firstNodeIndex = i;
}
if (alphabet.charAt(i) == o2.getId()) {
secondNodeIndex = i;
}
}
if (firstNodeIndex > secondNodeIndex) {
return 1;
} else if (firstNodeIndex == secondNodeIndex) {
return 0;
}else {
return -1;
}
}
}
问题是,当排序完成时,它会检查:
E against B
G against E
L against G
所以它永远不会检查 L 和 E,所以它无法知道应该先出现。
解决方案
您的订购违反了Comparator
的合同:
实现者还必须确保关系是可传递的: ((compare(x, y)>0) && (compare(y, z)>0)) 意味着 compare(x, z)>0。
compare('G','E') > 0 // since 'G' comes after 'E' in the alphabet
和
compare('E','L') > 0 // since 'E' is a child of 'L'
但
compare('G','L') < 0 // since 'G' comes before 'L' in the alphabet
由于 yourComparator
不是 valid Comparator
,因此可能会产生异常或意外结果。
推荐阅读
- python - 如何在 python 3 中调用特定的类和方法到另一个 python 文件?
- angular - 在运行时使用 i18n 翻译 Angular 8 应用程序
- python - 使用 Anaconda 创建新环境的问题
- r - 2列之间的R逐行runif()
- sed - sed:删除双破折号之前的所有字符,包括双破折号
- twig - 如何使用 Twig 和十月 CMS 从博客列表中排除已知类别
- selenium - 如何在 selenium webdriver 中选择多个复选框
- macos - 音频不适用于 Safari 11(Mac OS)
- java - 封装重组
- javascript - Formik - TypeError:无法读取未定义的属性“类型”?