【问题标题】:Using Comparator with List of Objects in Java在 Java 中使用带有对象列表的比较器
【发布时间】:2018-05-02 20:30:24
【问题描述】:

我想通过键(字符串类型)对我的 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 类

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;
    }
}

我做错了什么?

【问题讨论】:

  • K 不符合 Comparable in AVLNode
  • Java 8. 编辑了我的问题

标签: java generics java-8 comparator


【解决方案1】:

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

试试Comparator&lt;AVLNode&lt;String, ?&gt;&gt;

不相关,也用new AVLNode&lt;&gt;(...)

【讨论】:

    【解决方案2】:

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

    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(...)代替匿名类,例如:

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

    【讨论】:

      【解决方案3】:

      AVLNode 中的K 不包括与Comparable 的一致性(compareTo 可能来自哪里)

      您可以向K 添加一个附加约束,以便所有键都必须符合Comparable,类似于...

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

      这将限制放在AVLNode 本身,所以要小心(所有键都必须实现Comparable

      【讨论】:

        【解决方案4】:

        如上所述,编译器不知道n1.getKey() 返回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}
        

        附:实际上,我检查了@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

        【讨论】:

          【解决方案5】:

          您在比较器中声明原始 AVLNode 对象。这就是为什么只有 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;
                  }
              };
          

          【讨论】:

          • Cuboid 在这个比较器中实际上是无关紧要的。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-01-15
          • 1970-01-01
          • 2018-02-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多