Java Generics:compareTo和“capture#-of?”

时间:2015-01-28 01:14:15

标签: java generics binary-tree comparable

我试图编写BinaryTree的实现,其对象可以是任何实现Comparable的类型。但是,我意识到这不会完全奏效。例如,即使它们都实现Comparable,A String和Double也不能插入到同一个树中。

所以,我想知道是否可以编写代码,以便可以使用类型实现Comparable的任何值来实例化BinaryTree,但是添加到树中的任何后续元素都必须全部与root的值共享相同的超类型。

这是我到目前为止的代码:

public class BinaryTree {

    private Node root;

    public BinaryTree() {

        this.root = null;
    }

    public Node lookup(Comparable<Object> value) {

        return lookup(this.root, value);
    }

    private Node lookup(Node node, Comparable<Object> value) {

        Node match = null;

        if (match != node) {

            if (value == node.value) {
                match = node;
            } else if (value.compareTo(node.value) < 0) {
                return lookup(node.left, value);
            } else {
                return lookup(node.right, value);
            }
        }

        return match;
    }

    public Node lookupNonRecursively(Comparable<Object> value) {

        return lookupNonRecursively(this.root, value);
    }

    private Node lookupNonRecursively(Node node, Comparable<Object> value) {

        Node match = null;

        if (match != node) {

            if (value == node.value) {
                match = node;
            } else {

                Node root = node;
                boolean found = false;

                while (!found && root != null) {

                    if (root.value.compareTo(value) < 0) {

                        if (root.left == null) {

                            root.left = match = new Node(value);
                            found = true;
                        } else {
                            root = root.left;
                        }
                    } else {
                        if (root.right == null) {

                            root.right = match = new Node(value);
                            found = true;
                        } else {
                            root = root.right;
                        }
                    }
                }
            }
        }

        return match;
    }

    public Node insert(Comparable<Object> value) {

        return insert(this.root, value);
    }

    private Node insert(Node node, Comparable<Object> value) {

        if (node == null) {
            node = new Node(value);
        } else {
            if (node.value.compareTo(value) <= 0) {
                insert(node.left, value);
            } else {
                insert(node.right, value);
            }
        }

        return node;
    }

    public Node insertNonRecursively(Comparable<Object> value) {

        return insertNonRecursively(this.root, value);
    }

    private Node insertNonRecursively(Node node, Comparable<Object> value) {

        if (node == null) {
            node = new Node(value);
        } else {

            Node root = node;
            boolean inserted = false;

            while (!inserted) {

                if (node.value.compareTo(root.value) < 0) {

                    if (root.left == null) {
                        root.left = node = new Node(value);
                        inserted = true;
                    } else {
                        root = root.left;
                    }
                } else {
                    if (root.right == null) {
                        root.right = node = new Node(value);
                        inserted = true;
                    } else {
                        root = root.right;
                    }
                }
            }
        }

        return node;
    }

    public static class Node {

        private Node left;
        private Node right;
        private Comparable<Object> value;

        public Node(Comparable<Object> value) {

            this.left = null;
            this.right = null;
            this.value = value;
        }
    }
}

作为测试,如果我尝试运行如下代码,则会抛出错误The method insert(Comparable<Object>) in the type BinaryTree is not applicable for the arguments (Integer)

BinaryTree tree = new BinaryTree();
tree.insert(new Integer(1));

您可以看到我已为此类实施了一些不同的BinaryTree方法,但需要应用相同的规则:传入lookup()insert()的任何值也会需要分享root的超类型。我有一种感觉,这是<T extends Comparable<? super T>>的一些变体将要发挥作用的地方,但我的想法只是没有想出这个。

关于如何实现这一目标的任何想法?

正如@ jp-jee所指出的,这是我的解决方案(还有未经测试的第一次尝试修复的逻辑和其他错误),它的工作非常好:

public class BinaryTree<T extends Comparable<T>> {

    private Node<T> root;

    public BinaryTree() {

        this.root = null;
    }

    public Node<T> lookup(T value) {

        return lookup(this.root, value);
    }

    private Node<T> lookup(Node<T> node, T value) {

        Node<T> match = null;

        if (match != node) {

            if (value.equals(node.value)) {
                match = node;
            } else if (value.compareTo(node.value) < 0) {
                return lookup(node.left, value);
            } else {
                return lookup(node.right, value);
            }
        }

        return match;
    }

    public Node<T> lookupNonRecursively(T value) {

        return lookupNonRecursively(this.root, value);
    }

    private Node<T> lookupNonRecursively(Node<T> node, T value) {

        Node<T> match = null;

        if (match != node && value != null) {

            if (value.equals(node.value)) {
                match = node;
            } else {

                Node<T> searchRoot = node;
                boolean found = false;

                while (!found && searchRoot != null) {

                    if (value.equals(searchRoot.value)) {
                        match = searchRoot;
                        found = true;
                    } else if (value.compareTo(searchRoot.value) < 0) {
                        searchRoot = searchRoot.left;
                    } else {
                        searchRoot = searchRoot.right;
                    }
                }
            }
        }

        return match;
    }

    public void insert(T value) {

        this.root = insert(this.root, value);
    }

    private Node<T> insert(Node<T> node, T value) {

        if (node == null) {
            node = new Node<T>(value);
        } else {
            if (value.compareTo(node.value) <= 0) {
                node.left = insert(node.left, value);
            } else {
                node.right = insert(node.right, value);
            }
        }

        return node;
    }

    public void insertNonRecursively(T value) {

        this.root = insertNonRecursively(this.root, value);
    }

    private Node<T> insertNonRecursively(Node<T> node, T value) {

        if (node == null) {
            node = new Node<T>(value);
        } else {

            Node<T> runner = node;
            boolean inserted = false;

            while (!inserted) {

                if (value.compareTo(runner.value) < 0) {

                    if (runner.left == null) {
                        runner.left = new Node<T>(value);
                        inserted = true;
                    } else {
                        runner = runner.left;
                    }
                } else {
                    if (runner.right == null) {
                        runner.right = new Node<T>(value);
                        inserted = true;
                    } else {
                        runner = runner.right;
                    }
                }
            }
        }

        return node;
    }

    public static class Node<T extends Comparable<T>> {

        private Node<T> left;
        private Node<T> right;
        private T value;

        public Node(T value) {

            this.left = null;
            this.right = null;
            this.value = value;
        }

        public Node<T> getLeft() {
            return left;
        }

        public Node<T> getRight() {
            return right;
        }

        public T getValue() {
            return value;
        }
    }
}

1 个答案:

答案 0 :(得分:4)

使您的二叉树具有通用性,如

public class BinaryTree<T extends Comparable<T>>{
   ...
}

每当创建BinaryTree实例时,请指定包含类型:

new BinaryTree<MyClass>();

MyClass必须实现Comparable<MyClass>,即与同一类的对象相比。

您的方法将读作(示例):

 public Node lookup(T value) { ... }

同样适用于您的Node课程。以同样的方式使它具有通用性。