Zin Yosrim
Zin Yosrim

Reputation: 1684

Using Comparator with List of Objects in Java

I'd like to sort my objects of Type AVLNode by their key (type String). I instantiated a Comparator and want to apply the compareTo Method on the String attribute. But, my IDE shows me the error Cannot resolve method compareTo. I don't understand why I cant use the compareTo method on a string an this point.

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

This is my 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;
    }
}

What am I doing wrong?

Upvotes: 4

Views: 831

Answers (5)

Oleksandr Pyrohov
Oleksandr Pyrohov

Reputation: 16246

Don't use raw types, better to write:

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

For example:

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

By the way, you can use the Comparator.comparing(...) instead of anonymous class, for example:

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

Upvotes: 4

Sergei Sirik
Sergei Sirik

Reputation: 1289

As mentioned above compiler doesn't know that n1.getKey() returns String, so it assumes that Object will be returned. Anyway for Collections.sort() to work your code can be modified this way, see below. You haven't provided implementation of your Cuboid, so I replaced it with string.

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

Output:

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. Actually, I checked @MadProgrammer suggestion. It works this way as well

...

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> {

...

Compiler just needs to know that your key implements Comparable

Upvotes: 1

MadProgrammer
MadProgrammer

Reputation: 347314

K in AVLNode doesn't not include a conformance to Comparable (from where compareTo might come from)

You could add an additional constraint to K so that all keys must conform to Comparable, something like...

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

This places the limitation onto AVLNode itself, so beware (that all keys must implement Comparable)

Upvotes: 2

Ivan
Ivan

Reputation: 8758

You are declaring raw AVLNode objects in your comparator. That is why only methods of class Object are available for AVLNode.getKey().

Change your Comparator declaration to this

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

Upvotes: 1

lexicore
lexicore

Reputation: 43689

AVLNode is generic, parameterized with K and V. In your Comparator<AVLNode>, AVLNode is raw. That is, K and V are unknown. This means the compiler actually does not know if K is Comparable.

Try making it Comparator<AVLNode<String, ?>>.

Unrelated, but also use new AVLNode<>(...).

Upvotes: 5

Related Questions