0

私が現在取り組んでいるプロジェクトでは、テキスト ファイルから単語を読み取り、それらを配列 (最終的にはバイナリ ツリーですが、後で完成します) にロードします。単語と単語の頻度 (最初は 1) の両方を配列にロードする必要があるため、両方の変数を object にパックしましたWordNode。単語を配列にロードすることはできますが、単語が既に配列にあるかどうかを確認しようとすると、うまくいきません。そうであれば、頻度を 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

考えられる原因の1つは、あなたの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

Generics を使用すると、Javaは型情報を消去し、実行時にキャストを実行します。これは、コードの一部に が含まれている場合、代わりにT[]としてコンパイルされることを意味しますObject[]

wordArray.list[index].setFrequency()とへの参照に基づいて、ArrayUnorderedListのフィールドの型としてwordArray.list[index].getFrequency()使用されているようです。これはジェネリックの正しい使い方ではありません。Java は、配列のインデックスにアクセスする前にtoをキャストしようとします。ある配列型を別の配列型にキャストすると、常に ClassCastException が生成されます。T[]listObject[] listWordNode[]

listフィールドに直接アクセスする代わりにpublic T get(int index)、ArrayUnorderedList にメソッドを実装することを検討してください。Tメソッド シグネチャでのジェネリック型の使用は、ジェネリック コレクションでオブジェクト アクセスを実装する適切な方法です。ここでは、配列アクセスのに暗黙のキャストが発生します。

または、代わりに java.util.ArrayList または java.util.HashSet クラスを使用することを検討してください。どちらもジェネリック コレクションです。

于 2012-04-11T22:35:47.980 に答える
0

単語とその頻度しか気にしないのに、代わりにマップまたはセットを使用しないのはなぜですか? キーは単語、値は頻度になります。そうすれば、単に Map.contains(word) を呼び出すだけで、それが既に含まれているかどうかを確認してから、それに対してやりたいことを何でも実行できます。

于 2012-04-13T14:26:24.217 に答える
0

equals メソッドは、常に WordNode パラメータを指定して呼び出す必要があります。

パラメータオブジェクトの型を確認する必要があります

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));
}

Setとにかく、代わりにa を使用してみませんか? これは、ケースに使用できる最適なデータ構造です。

于 2012-04-11T22:15:28.340 に答える