Chris
Chris

Reputation: 1321

Casting with Comparable

I'm trying to find the minimum value of a node within a tree, and in order to detect whether something has smaller value, I'm using the compareTo() function as seen below:

   @SuppressWarnings("unchecked")
   public static Object min(TreeNode t)
   {
      if(t == null) {
         return null;
      }
      
      Comparable<TreeNode> min = (Comparable<TreeNode>) t;
      
      if(t.getLeft() != null) {
         Comparable<TreeNode> leftMin = (Comparable<TreeNode>) min(t.getLeft());
         
         if( ((Comparable<TreeNode>)leftMin).compareTo( (Comparable<TreeNode>)min) < 0) {
            min = leftMin;
         }
      }
      
      if(t.getRight() != null) {
         Comparable<TreeNode> rightMin = (Comparable<TreeNode>) min(t.getRight());
         
         if( ((Comparable<TreeNode>)rightMin).compareTo( (Comparable<TreeNode>)min) < 0) {
            min = rightMin;
         }
      }
      
      return min;
   }

However, I'm receiving the following error: error: incompatible types: Comparable<TreeNode> cannot be converted to TreeNode at the if statement.

I was told that the Object must be cast to Comparable in order to call compareTo()

And I have tried looking at this similiar question, but I don't have access to change the TreeNode Class

TreeNode Class:

public class TreeNode
{
   private Object value; 
   private TreeNode left, right;
   
   public TreeNode(Object initValue)
   { 
      value = initValue; 
      left = null; 
      right = null; 
   }

   /*methods*/

}

And I have also tried: if(leftMin.compareTo(min) < 0) however that yields the same error.

Do you know how to properly cast and convert the following classes?

Upvotes: 0

Views: 176

Answers (2)

user13510609
user13510609

Reputation:

The class TreeNode must implement the Comparable interface:

public class TreeNode implements Comparable<TreeNode> {
    ...
    @Override
    public int compareTo(TreeNode other) {
        ...  // maybe compare 'initValue' here
    }
}

also not sure if it is so good to cast TreeNode to Comparable, I would prefer to work without casting at all (e.g. public static TreeNode min(TreeNode t))


Edit: probably it was meant to cast initValue to Comparable so it can be compared - not very (type-) safe having it declared as Object in that case.


Edit after question changed. Since TreeNode cannot be changed, I think you must clearly split nodes and values, probably something like below (must be completed):

public static TreeNode min(TreeNode node) {
    ...
    TreeNode minNode = node;
    Comparable<?> minValue = (Comparable<?>) minNode.getValue(); // guessed method name

    if (node.getLeft() != null) {
        TreeNode leftMin = min(t.getLeft());
        Comparable<?> leftValue = (Comparable<?>) leftMin.getValue();
        if (leftValue.compareTo(minValue) < 0) {
            minNode = leftNode;
            minValue = leftValue;
        }
    ...

This requires that instances in Value implement Comparable.

Upvotes: 0

m_vemuri
m_vemuri

Reputation: 792

As suggested by others, you can use the comparable interface, which will require you to implement the compareTo method.

The compare to implementation details can be found in the java se docs:

Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.

So we can change your class to something like what is shown below (Note: I recommend converting value to an int or any other primitive type):

 class TreeNode implements Comparable<TreeNode> {
        // recommend to convert value to int or any other primitive type
        private Object value; 
        private TreeNode left, right;
       
        public TreeNode(Object initValue) { 
            value = initValue; 
            left = null; 
            right = null; 
        }
       
        // if value is int, just use ==, < and > 
        // i.e. this.value == o.value, this.value < o.value and so on ...
        @Override
        public int compareTo(TreeNode o) {
            if (this.value.equals(o.value)) return 0;
            else if (this.value.hashCode() < o.value.hashCode()) return -1;
            else return 1;
        }
    
       /*methods*/
}

Then you don't really need to do the casting in the min method. (Note: The implementation below is not actually correct - won't give you the min. It's just shown as to how the implementation would change after implementing the comparable interface).

// This method is not actually correct (i.e. won't actually find the min), 
// but showing how it would change after using the comparable interface 
// on the tree node class. 
public TreeNode min(TreeNode t) {
    if(t == null) {
     return null;
    }
  
    TreeNode min =  t;
  
    if(t.getLeft() != null) {
        TreeNode leftMin = min.getLeft();
     
        if(leftMin.compareTo(min) < 0) {
            min = leftMin;
        }
    }
  
    if(t.getRight() != null) {
        TreeNode rightMin = min.getRight();
        
        if( rightMin.compareTo(min) < 0) {
            min = rightMin;
        }
    }
  
    return min;
}

Upvotes: 1

Related Questions