为什么我的程序没有正确检查列表是否已包含特定的字符?

时间:2012-10-28 23:53:13

标签: java

我正在创建一个解析文件中所有字符的类,并查找每个字母的出现次数。

一步,当我浏览添加字符的文件时,我会检查字符列表是否已包含我所在的特定字符。如果没有,则将其添加到列表中,其出现值为1,如果已经包含它,则会将出现值增加1。

但是,我的下面的代码没有正确确定列表是否已包含特定字符。

我正在使用一个ArrayList,我知道我必须覆盖我所做的CharProfile类中的equals方法,以便让包含()的equals()方法正常工作。

在CharProfile中覆盖等于方法:

    @Override
    public boolean equals(Object o) {
        if (this.character == ((Character)o)) {
            return true;
        }
        else {
            return false;
        }
    }

代码:

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

public class HuffmanCoder {
    public static void main(String[] args) throws IOException {
        Scanner keyboard = new Scanner(System.in);

        System.out.print("Please enter the name of the file to be read from: ");
        String fileName = keyboard.nextLine();

        File file = new File(fileName);
        Scanner inputFile = new Scanner(file);

        int charCount = 0;
        ArrayList<CharProfile> charOccurrences = new ArrayList<CharProfile>();

        while (inputFile.hasNext()) {
            // Grabs the next word in the file and converts it into a char array
            String word = inputFile.next();
            char[] wordArray = word.toCharArray();

            // Parses the word on a char-by-char basis
            for (int i = 0; i < wordArray.length; i++) {
                if (wordArray[i] != ' ') {
                    charCount++;

                    // Constructs the list of chars and their respective number of occurrences
                    if (!charOccurrences.contains(wordArray[i])) {
                        charOccurrences.add(new CharProfile(wordArray[i]));
                    }
                    else {
                        for (int j = 0; j < charOccurrences.size(); j++) {
                            if (charOccurrences.get(j).getCharacter() == wordArray[i]) {
                                charOccurrences.get(j).incremementOccurrences();
                                break;
                            }
                        }
                    }
                }
            }
        }

        // Figure out each char's probability
        for (int i = 0; i < charOccurrences.size(); i++) {
            System.out.println(charOccurrences.get(i).getCharacter());
        }
    }   
}

Full CharProfile类:

public class CharProfile {
    private char character;
    private int occurrences;
    private double probability;

    public CharProfile(char character) {
        this.character = character;
        occurrences = 1;
    }

    public void incremementOccurrences() {
        occurrences++;
    }

    public char getCharacter() {
        return character;
    }

    public void setCharacter(char character) {
        this.character = character;
    }

    public int getOccurrences() {
        return occurrences;
    }

    public void setOccurrences(int occurrences) {
        this.occurrences = occurrences;
    }

    public double getProbability() {
        return probability;
    }

    public void setProbability(double probability) {
        this.probability = probability;
    }

    public boolean equals(char character) {
        if (this.character == character) {
            return true;
        }
        else {
            return false;
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this.character == ((Character)o)) {
            return true;
        }
        else if (this.character == ((Character)o).charValue()) {
            return true;
        }
        else {
            return false;
        }
    }
}

问题简而言之:当检查列表是否已包含该char时,它不会返回true,而是总是返回false,导致文件中的每个char都被添加到列表中,而它应该只是唯一的

2 个答案:

答案 0 :(得分:1)

这只是将对象引用比较为相同,并且实例是Character而不是CharProfile

@Override
public boolean equals(Object o) {
    if (this.character == ((Character)o)) {
        return true;
    }
    else {
        return false;
    }
}

您需要更改等号方法以接受CharProfile的实例并比较其中的字符值,如下所示:

@Override
public boolean equals(Object o) {
    if(this.character == ((CharProfile)o).getCharacter()) {
        return true;
    }else {
        return false;
    }
}

编辑:您的等号方法未被调用,因为您将char传递给contains方法。

请将其更改为:

         // Constructs the list of chars and their respective number of occurrences
         CharProfile charProfile = new CharProfile(wordArray[i]);
         if (!charOccurrences.contains(charProfile)) {
              charOccurrences.add(charProfile);
         }

答案 1 :(得分:0)

您犯了一个经典错误:==equals()混淆。

在java(与javascript不同)中:

  • ==测试两个操作数是否相同的实例
  • equals()的默认行为与==相同,但实施时通常会测试两个操作数是否具有相同的

如果您将所有==更改为.equals(),则应修复问题。


您的equals()方法代码太多了 - 可以将其替换为完全相同的东西:

@Override
public boolean equals(Object o) {
    return this.character.equals(o);
}

但我会这样做,处理所有合理的类型:

@Override
public boolean equals(Object o) {
    if (o instanceof Character) {
        return character.equals(o);
    }
    if (o instanceof CharProfile) {
        return character.equals(((CharProfile)o).character);
    }
    return false;
}


此外,当覆盖equals()时,您还应覆盖hashCode()以保持一致 - 即返回正在比较的值的hashCode,如下所示:

@Override
public int hashCode() {
    return character.hashCode();
}