Использование компаратора со списком объектов в Java - PullRequest
0 голосов
/ 02 мая 2018

Я бы хотел отсортировать мои объекты типа AVLNode по их ключу (тип String). Я создал экземпляр Comparator и хочу применить метод compareTo к атрибуту String. Но моя 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;
    }
}

Что я делаю не так?

Ответы [ 5 ]

0 голосов
/ 02 мая 2018

Не используйте необработанные типы, лучше написать:

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);
0 голосов
/ 02 мая 2018

Как упоминалось выше, компилятор не знает, что 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}

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

0 голосов
/ 02 мая 2018

Вы объявляете необработанные AVLNode объекты в вашем компараторе. Поэтому для AVLNode.getKey().

доступны только методы класса Object.

Измените декларацию Comparator на эту

Comparator<AVLNode<String, Cuboid>> myComp2 = new Comparator<AVLNode<String, Cuboid>>() {
        @Override
        public int compare(AVLNode<String, Cuboid> o1, AVLNode<String, Cuboid> o2) {
            return 0;
        }
    };
0 голосов
/ 02 мая 2018

K в AVLNode не включает в себя соответствие Comparable (откуда может исходить compareTo)

Вы можете добавить дополнительное ограничение к K, чтобы все ключи соответствовали Comparable, что-то вроде ...

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

Это накладывает ограничение на сам AVLNode, поэтому будьте осторожны (что все ключи должны реализовывать Comparable)

0 голосов
/ 02 мая 2018

AVLNode является общим, параметризованным с K и V. В вашем Comparator<AVLNode>, AVLNode есть сырье. То есть K и V неизвестны. Это означает, что компилятор фактически не знает, является ли K Comparable.

Попробуйте сделать это Comparator<AVLNode<String, ?>>.

Не имеет отношения, но также использует new AVLNode<>(...).

...