Java-如何比较泛型类型?

时间:2016-10-26 18:01:05

标签: java oop generics

这是通用二叉搜索树的代码。现在,它运行和编译完美,但有一个我现在只注意到的问题,在我完成这个课程之后。问题是insert方法使用compareTo()(当比较节点'元素时)来决定将下一个节点放在树中的位置根据它的'值。例如输入:

  

1,112,2

而不是获取此树:

 1  
  \   
    2    
     \    
     112

我最终获得的是:

       1
         \
          2
         / 
        112

因为可能以字典方式进行比较,所以它看到2> 112。

这里是Tree类的代码:

import java.util.*;
import java.io.*;
import java.lang.*;

public class Tree<T extends Comparable<T>>
    { private Node<T> root = null;
    static String S="";

    public Tree()
        {File file=new File("date.in.txt");

            try 
            { Scanner input = new Scanner( file );
            while(input.hasNext())
                 insert((T)input.next());} 

            catch (FileNotFoundException ex) 
                { System.out.printf("ERROR: %s!\n", ex); } }


    public void show(){ printLevelOrder(maxDepth()); }

    public void printLevelOrder(int depth) 
        { for (int i = 1; i <= depth; i++) 
            { System.out.print("Level " + (i-1) + ": ");
            String levelNodes = printLevel(root, i);
            System.out.print(levelNodes + "\n"); } }

    public String printLevel(Node<T> t, int level) 
        { if (t == null) 
            return "";
        if (level == 1) 
            return t.element + " ";
         else if (level > 1) 
            { String leftStr = printLevel(t.left, level - 1);
            String rightStr = printLevel(t.right, level - 1);
            return leftStr + rightStr; }
        else 
          return ""; }


    int maxDepth(){ return maxDepth2(root); }

    int maxDepth2(Node<T> node) 
        { if (node == null) 
            return (0);
         else 
            { int leftDepth = maxDepth2(node.left);
            int rightDepth = maxDepth2(node.right);

            if (leftDepth > rightDepth )
                return (leftDepth + 1);
            else
                return (rightDepth + 1); } }


    public String toString(){ return this.InOrder(); }


    public String InOrder(){ inOrder2(root); return S; }

    public void inOrder2(Node<T> root) 
        { if(root !=  null)   
            { inOrder2(root.left);    
            S=S+root.element+" ";  
            inOrder2(root.right); } }


    public boolean insert(T element)  // I N S E R T    M E T H O D
        { if (isEmpty()) 
            { root = new Node<T>(element);
            return true; }

         Node<T> current = root; 
         Node<T> parent;         

         do 
            { parent = current;

             if (element.compareTo(current.element)<0) 
                 current = current.left; 
              else if (element.compareTo(current.element)>0) 
                 current = current.right; 
              else 
                 return false; } 
             while (current != null);

         Node<T> node = new Node<T>(element);


             if ( element.compareTo(parent.element)>0  ) 
                 parent.right = node;
          else 
             parent.left = node;

         return true; } 


    public boolean isEmpty() { return root == null; }


    private static class Node<T extends Comparable<T>>   
        { Node<T> left  = null;
        Node<T> right = null;
        final T element;

        Node(T element) { this.element = element; } } }

以下是主要的:

import java.util.*;
import java.io.*;

public class Main 
    {public static void main(String[]args)
        {Tree <Double> T=new Tree<>(); } }

现在我进行了一些研究并在这里和那里问过,我得到了一种叫做比较器的东西,但我之前还没有用过,而且我不确定如何实现它。现在,如果你有任何解决方法可以解决这个问题,或者添加/做什么,那么我所有的眼睛和耳朵都是如此。

1 个答案:

答案 0 :(得分:3)

您的第insert((T)input.next());行没有意义 - input.next()String,但您将其投放到T,即使T不是Tree此时与真实类型无关。例如,在构建new Tree<Integer>调用者时,可以说insert((Integer)input.next());使这一行显然是Tree,这就是它。

如果您的目标是String始终包含T,请从Tree中删除通用String类型,然后使用Tree。如果您确实想要支持任意类型,则需要将文件读取行为移出Tree<String>构造函数(例如,转换为返回public static Tree<String> readFromFile(Path file) throws FileNotFoundException { try (Scanner input = new Scanner(file)) { Tree<String> tree = new Tree<>(); while(input.hasNext()) { tree.insert(input.next()); } return tree; } } 的静态方法)。

例如:

File

请注意,我使用Path代替main try-with-resources模式,并且我没有抑制异常,而是调用者(可能是catch (IOException e) { throw new RuntimeException("Could not open " + file, e); } 方法)应该正确处理异常(可能通过报告文件不存在和退出)。或者像这样添加一个catch块:

Tree

会避免强制调用者处理异常。

现在我们已经清理了public static Tree<Integer> readIntsFromFile(Path file) throws FileNotFoundException { ... tree.insert(Integer.valueOf(input.next())); ... } 类型,您的订购问题可能更容易回答。如果您打算将元素排序为整数,请将输入转换为整数,例如

Tree<String>

这将根据整数排序对树进行排序,而不是字符串的字典排序。这就是我建议你做的。它很简单,可以做你想要的。

如果你真的想要一个Comparator,但是你想要将它们命名为,就像它们是整数一样,你需要一个自定义的Comparator,正如你所提到的那样。然后,您需要将Tree传递给comparator.compare(element, current.element)的构造函数,然后拨打当前呼叫element.compareTo(current.element)的{​​{1}}。