0

我现在正在进行的项目涉及我从文本文件中读取单词并将它们加载到数组中(最终是二叉树,但这将在稍后完成)。我必须将单词和单词的频率(最初为 1)都加载到数组中,因此我将两个变量都打包到一个 objectWordNode中。我能够将单词加载到数组中,但是当我尝试检查单词是否已经在数组中时,事情就崩溃了。如果是,我必须将频率增加 1。我编写了一个新equals()方法来覆盖默认方法,以便比较单词而不是变量引用。但是,我现在收到错误消息Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LWordNode;。为什么会出现这种情况?我以为只有WordNode对象被传递给equals().

主要方法:

public class Driver {
/////////////// fields ///////////////
public static ArrayUnorderedList<WordNode> wordArray = new ArrayUnorderedList<WordNode>();
public static LinkedBinarySearchTree<WordNode> wordTree = new LinkedBinarySearchTree<WordNode>();   //tree to hold words

/////////////// methods ///////////////
public static void main(String[] args) throws Exception {
    //ask for filename       
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    System.out.println("Enter the name of the file to read from: ");
    Reader file = new FileReader(reader.readLine());

    //read file
    Scanner input = new Scanner(file);

    while(input.hasNext()) {
        //get words from file
        String word = input.next();

        //remove non-word characters and convert to lowercase
        word = word.replaceAll("\\W", "");
        word = word.toLowerCase();

        //create node
        WordNode newWord = new WordNode(word);

        //if word is already in array
        if(wordArray.contains(newWord)) {
            System.out.println("Word is already in array");

            //increment frequency by 1
            int index = wordArray.find(newWord);
            wordArray.list[index].setFrequency(wordArray.list[index].getFrequency() + 1);
            System.out.println("(" + newWord.getFrequency() + ") " + newWord.getWord());
        } else {
            System.out.println("Word is not yet in array");

            //add word to tree
            System.out.println("(" + newWord.getFrequency() + ") " + newWord.getWord());
            wordArray.addToRear(newWord);
        }
    }

    //insert into tree

    //perform traversals on tree
}

WordNode 类:

public class WordNode {
   protected String word;
   protected WordNode left, right;
   protected int frequency;

   /**
    * Creates a new node with the specified data.
    * @param obj the element that will become a part of the new node
    */
   WordNode(String obj) {
      word = obj;
      left = null;
      right = null;
      frequency = 1;
   }

   /**
    * Method to check for string equivalence.
    * @return true if words are the same
    */
   public boolean equals(Object obj) {
       WordNode tempWord = (WordNode)obj;
       return(tempWord.getWord().equals(this.word));
   }

   /**
    * Gets the word.
    * @return the word
    */
   public String getWord() {
      return word;
   }

   /**
    * Sets the word.
    * @param word the word to set
    */
   public void setWord(String word) {
      this.word = word;
   }

   /**
    * Gets the left.
    * @return the left
    */
   public WordNode getLeft() {
      return left;
   }

   /**
    * Sets the left.
    * @param left the left to set
    */
   public void setLeft(WordNode left) {
      this.left = left;
   }

   /**
    * Gets the right.
    * @return the right
    */
   public WordNode getRight() {
      return right;
   }

   /**
    * Sets the right.
    * @param right the right to set
    */
   public void setRight(WordNode right) {
      this.right = right;
   }

   /**
    * Gets the frequency.
    * @return the frequency
    */
   public int getFrequency() {
      return frequency;
   }

   /**
    * Sets the frequency.
    * @param frequency the frequency to set
    */
   public void setFrequency(int frequency) {
      this.frequency = frequency;
   }
}

ArrayList 类的一些方法:

/**
* Returns true if this list contains the specified element.
* @param target the element that the list is searched for
* @return true if the target is in the list, false if otherwise 
*/
public boolean contains(T target) {
    return (find(target) != NOT_FOUND);
}

/**
* Returns the array index of the specified element, or the
* constant NOT_FOUND if it is not found.
* @param target the element that the list will be searched for
* @return the integer index into the array containing the target element, or the NOT_FOUND constant
*/
public int find(T target) {
    int scan = 0, result = NOT_FOUND;
    boolean found = false;

    if (!isEmpty()) {
       while (!found && scan < rear) {
          if (target.equals(list[scan])) {
              found = true;
          } else {
             scan++;
          }
       }
    }

    if (found) {
       result = scan;
    }

    return result;
}
4

5 回答 5

4

一种可能的原因是您的equals方法:

public boolean equals(Object obj) {
    //You need to check that obj is a WordNode
    //For example: if (obj instanceof WordNode) {...
    WordNode tempWord = (WordNode)obj; 
    return(tempWord.getWord().equals(this.word));
}

如果 obj 不是 WordNode,将抛出异常。

你应该看看这个关于如何在 Java 中覆盖 equals 和 hashcode 的讨论

于 2012-04-11T22:10:59.873 回答
1

当您使用泛型时,Java会删除类型信息并在运行时执行强制转换。这意味着如果您的代码的任何部分包含T[],它将被编译为Object[]

根据对wordArray.list[index].setFrequency()and的引用wordArray.list[index].getFrequency(),看起来您已用作ArrayUnorderedList 字段的类型T[]list这不是对泛型的正确使用。Java 将尝试Object[] listWordNode[]访问数组的索引之前强制转换为。将一种数组类型转换为另一种数组类型将始终产生 ClassCastException。

考虑在 ArrayUnorderedList 中list实现一个方法,而不是直接访问该字段。public T get(int index)在方法签名中使用泛型类型T是在泛型集合中实现对象访问的正确方法。这里,隐式转换发生数组访问之后。

或者,考虑改用 java.util.ArrayList 或 java.util.HashSet 类。两者都是通用集合。

于 2012-04-11T22:35:47.980 回答
0

除了应该始终使用 WordNode 参数调用 equals 方法外,不要这样做。

您必须验证参数对象的类型

public boolean equals(Object obj) {
   if(!(obj instanceof WordNone)){
     return false;
   }
   // rest of equals method
}
于 2012-04-11T22:15:06.800 回答
0

假设在 equals 中传递的内容将始终是同一对象的实例是不安全的。你需要做一些检查,比如

public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    WordNode otherWord = (WordNode) obj;

    return(otherWord.getWord().equals(this.word));
}

无论如何,你为什么不使用 aSet代替?这是您可以用于您的案例的最佳数据结构。

于 2012-04-11T22:15:28.340 回答
0

既然您只关心一个单词及其频率,为什么不使用 Map 或 Set 呢?键是单词,值是频率。这样,您只需调用 Map.contains(word) 并查看它是否已经存在,然后做任何您想做的事情。

于 2012-04-13T14:26:24.217 回答