Alex_B
Alex_B

Reputation: 1661

Java comparing generic types

In Java, I wrote a Binary Search Tree class that adds nodes using recursion. Now I want to generalize it using Generics so I can learn more about them.

public class GBinNode<T> {
    T item;
    GBinNode<T> left;
    GBinNode<T> right;

public GBinNode(T newItem) {
    item = newItem;
    left = null;
    right = null;
    }
public GBinNode(T it, GBinNode<T> le, GBinNode<T> ri) {
    item = it;
    left = le;
    right = ri;
    }
public String toString() {
    return item.toString()+" ";
    }
}

My function to add nodes is in the following class

public class GBinTree<T extends Comparable <T>> {
  GBinNode<T> add(T item, GBinNode<T> bn) {
    if (bn==null) {
        return new GBinNode<T>(item, null, null);
    }
    if (item < bn.item) {        // ERROR HERE
        bn.left = add( item, bn.left);
    }
    else {
        bn.right = add( item, bn.right);
    }
    return bn;
}

public void toString(GBinNode<T> root) {
    GBinNode<T> curr = root;
    if (curr == null)
        return;
    else {
        toString(curr.left);
        System.out.println(curr.toString());    // inorder traversal
        toString(curr.right);
    }
}

The main class has the following code to kick things off. I'm using strings, but the data type could be some complex type.

GBinTree<String> bt = new GBinTree<String>();
    GBinNode<String> root = null;
    root = bt.add("Calex", root);
    root = bt.add("Ealex", root);
    root = bt.add("Balex", root);
    root = bt.add("Dalex", root);       
    bt.toString(root);

I started to use the Comparable interface but then how do I write the CompareTo() function? I don't know what type T will be? The error I got was "The operator < is undefined for the argument type(s) T, T".

Searching for a solution, one answer was Comparing generic types Java:

class Element<T extends Comparable<T>>

I don't understand where this should go, and how it's different from the class implementing Comparable. The only place I know the type is in the main class, so should the compareTo() be there? I looked at making GBinTree an interface, but got confused whether that was the right track? Any help would be appreciated.

Upvotes: 31

Views: 97366

Answers (4)

Tushar Malik
Tushar Malik

Reputation: 26

To address the issue and make your GBinTree class work with generics, you need to make a few modifications. Here's an updated version of your code:

public class GBinNode<T extends Comparable<T>> {
    T item;
    GBinNode<T> left;
    GBinNode<T> right;

    public GBinNode(T newItem) {
        item = newItem;
        left = null;
        right = null;
    }

    public GBinNode(T it, GBinNode<T> le, GBinNode<T> ri) {
        item = it;
        left = le;
        right = ri;
    }

    public String toString() {
        return item.toString() + " ";
    }
}

public class GBinTree<T extends Comparable<T>> {
    GBinNode<T> add(T item, GBinNode<T> bn) {
        if (bn == null) {
            return new GBinNode<T>(item, null, null);
        }
        if (item.compareTo(bn.item) < 0) {
            bn.left = add(item, bn.left);
        } else {
            bn.right = add(item, bn.right);
        }
        return bn;
    }

    public void toString(GBinNode<T> root) {
        if (root == null)
            return;
        else {
            toString(root.left);
            System.out.println(root.toString()); // inorder traversal
            toString(root.right);
        }
    }

    public static void main(String[] args) {
        GBinTree<String> bt = new GBinTree<String>();
        GBinNode<String> root = null;
        root = bt.add("Calex", root);
        root = bt.add("Ealex", root);
        root = bt.add("Balex", root);
        root = bt.add("Dalex", root);
        bt.toString(root);
    }
}

Here are the changes made:

In the GBinNode class, the generic type T is now restricted to implement the Comparable interface using T extends Comparable<T>. This allows you to use the compareTo method for comparing items in the tree.

In the GBinTree class, the add method uses item.compareTo(bn.item) instead of the < operator for comparison. This ensures that the comparison is done using the compareTo method of the generic type T.

The toString method in the GBinTree class now checks for root == null before performing traversal. This prevents errors when the tree is empty.

With these changes, you can now create a GBinTree object with any type that implements the Comparable interface, including custom types. The compareTo method is automatically available for comparisons within the add method.

Note: I also removed the space in the toString method of GBinNode class to align with the standard toString format.

Upvotes: 0

JPG
JPG

Reputation: 1

Came across this problem when writing generic sorting. Best solution that i came up with is to add a Comparator to the argument of sorting function and use the compare method. You will have to override the compare(T o1,To2) method at/before function call while creating new Comparator<T>() , T to be replaced by the desired type.

Upvotes: 0

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 280179

You cannot overload operators in Java. The < operator only applies to primitive (or numeric) types, not reference types. Since T is a type variable that represents a reference type, you cannot use < on variables of type T. You have to use

if (item.compareTo(bn.item) < 0) 

check the value returned and decide to do what you wish with it.

You don't know what the type T will be but you know that it will be a type that implements Comparable and therefore implements the compareTo() method.

Upvotes: 43

user2483498
user2483498

Reputation: 39

You can use this simple approach
for data greater than root.getData = 1, for data equals root.getData = 0,for data lesser than root.getData = -1

public class BST<E extends Number & Comparable<? super E>>{
    void add(){
    ...
    if(data.compareTo(root.getData()) == 1)
    ...
}

Upvotes: 3

Related Questions