将比较器与 Java 中的对象列表一起使用

Using Comparator with List of Objects in Java

我想按键(字符串类型)对 AVLNode 类型的对象进行排序。我实例化了一个 Comparator 并想在 String 属性上应用 compareTo 方法。但是,我的 IDE 显示错误 Cannot resolve method compareTo。我不明白为什么我不能在这一点上对字符串使用 compareTo 方法。

import java.util.*;

public class AVLTreeTest {
    public static void main(String[] args){

        Comparator<AVLNode>myComp2 = new Comparator<AVLNode>() {
            @Override public int compare(AVLNode n1, AVLNode n2) {
                return n1.getKey().compareTo(n2.getKey());
            }
        };

        AVLNode<String, AVLNode> a1 = new AVLNode( "test3", new Cuboid (2,3,4,5,6,7) );
        AVLNode<String, AVLNode> a2 = new AVLNode( "test2", new Cuboid (2,3,4,5,6,7) );
        AVLNode<String, AVLNode> a3 = new AVLNode( "test8", new Cuboid (2,3,4,5,6,7) );
        AVLNode<String, AVLNode> a4 = new AVLNode( "test1", new Cuboid (2,3,4,5,6,7) );

        List<AVLNode> listOfNodes = new ArrayList<AVLNode>();
        listOfNodes.add(a1);
        listOfNodes.add(a2);
        listOfNodes.add(a3);
        listOfNodes.add(a4);
        Collections.sort(listOfNodes, myComp2);

        for (AVLNode node : listOfNodes){
            System.out.println(node);
        }
    }
}

这是我的 AVLNode Class

public class AVLNode<K, V>  {

    private AVLNode<K, V> left, right, parent;
    private int height = 1;
    private K key;
    private V value;

    public AVLNode() {}
    public AVLNode(K key, V value) {
        this.key = key;
        this.value = value;
    }


    public V getValue() {
        return value;
    }

    public K getKey() {
        return key;
    }
}

我做错了什么?

AVLNode 是通用的,用 KV 参数化。在你的 Comparator<AVLNode> 中,AVLNode 是原始的。也就是说,KV 是未知的。这意味着编译器实际上不知道 K 是否为 Comparable.

尝试制作它 Comparator<AVLNode<String, ?>>

无关,但也用new AVLNode<>(...)

您正在比较器中声明原始 AVLNode 对象。这就是为什么只有 class Object 的方法可用于 AVLNode.getKey().

将您的比较器声明更改为此

Comparator<AVLNode<String, Cuboid>> myComp2 = new Comparator<AVLNode<String, Cuboid>>() {
        @Override
        public int compare(AVLNode<String, Cuboid> o1, AVLNode<String, Cuboid> o2) {
            return 0;
        }
    };

K in AVLNode 不包括对 Comparable 的遵从(compareTo 可能来自哪里)

您可以向 K 添加一个额外的约束,以便所有键都必须符合 Comparable,例如...

public class AVLNode<K extends Comparable<K>, V> {
    //...
}

这将限制置于 AVLNode 本身,因此请注意(所有键必须实现 Comparable

如上所述,编译器不知道 n1.getKey() returns String,因此它假定将返回 Object。无论如何,Collections.sort() 可以通过这种方式修改您的代码,请参见下文。您还没有提供 Cuboid 的实现,因此我将其替换为字符串。

public class AVLTreeTest {

  public static void main(String[] args) {

    Comparator myComp2 = new Comparator<AVLNode>() {
      @Override
      public int compare(AVLNode n1, AVLNode n2) {
        return ((String)n1.getKey()).compareTo((String)n2.getKey());
      }
    };

    AVLNode<String, AVLNode> a1 = new AVLNode("test3", "asd");
    AVLNode<String, AVLNode> a2 = new AVLNode("test2", "bds");
    AVLNode<String, AVLNode> a3 = new AVLNode("test8", "asdfas");
    AVLNode<String, AVLNode> a4 = new AVLNode("test1", "asdfasdf");

    List<AVLNode> listOfNodes = new ArrayList<AVLNode>();
    listOfNodes.add(a1);
    listOfNodes.add(a2);
    listOfNodes.add(a3);
    listOfNodes.add(a4);
    Collections.sort(listOfNodes, myComp2);

    for (AVLNode node : listOfNodes) {
      System.out.println(node);
    }
  }
}

class AVLNode<K, V> {

  private AVLNode<K, V> left, right, parent;
  private int height = 1;
  private K key;
  private V value;

  public AVLNode() {
  }

  public AVLNode(K key, V value) {
    this.key = key;
    this.value = value;
  }


  public V getValue() {
    return value;
  }

  public K getKey() {
    return key;
  }

  @Override
  public String toString() {
    return "AVLNode{" +
        "left=" + left +
        ", right=" + right +
        ", parent=" + parent +
        ", height=" + height +
        ", key=" + key +
        ", value=" + value +
        '}';
  }
}

输出:

AVLNode{left=null, right=null, parent=null, height=1, key=test1, value=asdfasdf}
AVLNode{left=null, right=null, parent=null, height=1, key=test2, value=bds}
AVLNode{left=null, right=null, parent=null, height=1, key=test3, value=asd}
AVLNode{left=null, right=null, parent=null, height=1, key=test8, value=asdfas}

P.S。实际上,我检查了@MadProgrammer 的建议。它也是这样工作的

...

Comparator myComp2 = new Comparator<AVLNode>() {
      @Override
      public int compare(AVLNode n1, AVLNode n2) {
        return n1.getKey().compareTo(n2.getKey());
      }
    };

...

class AVLNode<K extends Comparable<K>, V> {

...

编译器只需要知道您的 key 实现了 Comparable

不要使用原始类型,最好这样写:

Comparator<AVLNode<Type1, Type2> comparator ...

例如:

Comparator<AVLNode<String, Cuboid>> myComp2 = new Comparator<>() {
    @Override
    public int compare(AVLNode<String, Cuboid> n1, AVLNode<String, Cuboid> n2) {
        return n1.getKey().compareTo(n2.getKey());
    }
};

顺便说一句,您可以使用Comparator.comparing(...)代替匿名class,例如:

Comparator<AVLNode<String, Cuboid>> comparator = Comparator.comparing(AVLNode::getKey);