Java Comparator不会比较每个对象

时间:2018-12-09 10:55:14

标签: java comparator

我在使用Java Comparator时遇到了一些麻烦。因此,我有一个具有子节点列表的父节点。我想对这些子项进行排序,从表面上看似乎很简单,但是当Comparator进行排序时,它仅根据某些对象检查某些对象,然后我推测它会推断对象的位置,例如ad之前,fd之后,bd之前,这意味着b在{{1之前}}。

下面是我当前设置的一个示例。我有一个父节点f和4个子节点abel。当我对这些子项进行排序时,我希望顺序为gbgl,因此请按字母排序并始终确保父节点排在最前面

(不好意思的画)

enter image description here

很简单,我有一个e类,它包含一个ID,因此是字母,然后是孩子列表。

Node

然后,我有了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;
        }
    }
}

因此它永远不会将L与E进行比较,因此它无法知道应该先出现。

4 个答案:

答案 0 :(得分:4)

您的订单违反了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

由于您的Comparator不是有效的Comparator,因此很可能会产生异常或意外结果。

答案 1 :(得分:1)

好的排序算法会尽量减少比较次数,以实现良好的性能。这不是问题,而是这些排序算法的功能。如果将每个元素彼此比较,则不会改变结果。

如果订购不符合您的预期,则应该仔细查看比较器。

答案 2 :(得分:1)

正如您所指出的,您的比较器违反了比较器合同...但是按照您自己描述的方式进行排序并不应该太复杂,您可能想要类似的东西:

Vectorize

即使您想保留比较器的某些内容,也可以使用Character.compare()从其中删除一半的逻辑,例如:

myfun <- function(x, y) sum((myMat[x,] - myMat[y,])^2)
myfun_v <- Vectorize(myfun)

norm <- matrix(myfun_v(ind$Var1, ind$Var2), NRows, NCols)
norm
#           [,1]      [,2]      [,3]      [,4]
# [1,] 0.0000000 0.7408859 0.9713548 0.9768185
# [2,] 0.7408859 0.0000000 0.8285694 0.1746331
# [3,] 0.9713548 0.8285694 0.0000000 0.3690422
# [4,] 0.9768185 0.1746331 0.3690422 0.0000000

答案 3 :(得分:0)

它所做的比较是正确的,并且可以预期。如果L> G且G> E,则根据比较器规则,L> E。

在这方面,比较器遵循正常的算术规则。 3> 2和2> 1表示3> 1(传递性)。

您的问题可能是E是A的孩子。通常,它不应该在这类树中。拥有多个父代会使树处理变得相当复杂。如果在进行比较时删除了该链接并使用某种递归算法遍历树,则该树应该起作用。