有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何验证arraylist中是否存在具有特定属性值的对象?

我希望通读文本文档,然后只将唯一的单词添加到“Word”对象的arraylist中。我现在的代码似乎根本没有在wordList arraylist中输入任何单词

public ArrayList<Word> wordList = new ArrayList<Word>();
    String fileName, word;
    int counter;
    Scanner reader = null;
    Scanner scanner = new Scanner(System.in);

try {
            reader = new Scanner(new FileInputStream(fileName));
        }
        catch(FileNotFoundException e) {
            System.out.println("The file could not be found. The program will now exit.");
            System.exit(0);
        }

    while (reader.hasNext()) {
                word = reader.next().toLowerCase();
                for (Word value : wordList) {
                    if(value.getValue().contains(word)) {
                        Word newWord = new Word(word);
                        wordList.add(newWord);
                    }
                }
                counter++;
            }

    public class Word {

        String value;
        int frequency;

        public Word(String v) {
            value = v;
            frequency = 1;
        }

        public String getValue() {
            return value;
        }

    public String toString() {
        return value + " " + frequency;
    }

}

共 (3) 个答案

  1. # 1 楼答案

    好的,让我们从修复当前代码开始。您遇到的问题是,仅当列表中已经存在一个新的word对象时,才将其添加到列表中。相反,当不存在单词对象时,需要添加一个新单词对象,否则需要增加频率。下面是一个修复示例:

        ArrayList<Word> wordList = new ArrayList<Word>();
        String fileName, word;
        Scanner reader = null;
        Scanner scanner = new Scanner(System.in);
    
        try {
            reader = new Scanner(new FileInputStream(fileName));
        }
        catch(FileNotFoundException e) {
            System.out.println("The file could not be found. The program will now exit.");
            System.exit(0);
        }
    
        while (reader.hasNext()) {
                word = reader.next().toLowerCase();
                boolean wordExists = false;
                for (Word value : wordList) {
                   // We have seen the word before so increase frequency.
                   if(value.getValue().equals(word)) {
                        value.frequency++;
                        wordExists = true;
                        break;
                   }
                }
                // This is the first time we have seen the word!
                if (!wordExists) {
                    Word newValue = new Word(word);
                    newValue.frequency = 1;
                    wordList.add(newValue);
                 }
            }
    }
    

    然而,这是一个非常糟糕的解决方案(O(n^2)运行时)。相反,我们应该使用称为Map的数据结构,这将使我们的运行时降到(O(n))

        ArrayList<Word> wordList = new ArrayList<Word>();
        String fileName, word;
        int counter;
        Scanner reader = null;
        Scanner scanner = new Scanner(System.in);
    
        try {
            reader = new Scanner(new FileInputStream(fileName));
        }
        catch(FileNotFoundException e) {
            System.out.println("The file could not be found. The program will now exit.");
            System.exit(0);
        }
        Map<String, Integer> frequencyMap = new HashMap<String, Integer>();
        while (reader.hasNext()) {
           word = reader.next().toLowerCase();
           // This is equivalent to searching every word in the list via hashing (O(1))
           if(!frequencyMap.containsKey(word)) {
              frequencyMap.put(word, 1);
           } else {
              // We have already seen the word, increase frequency.
              frequencyMap.put(word, frequencyMap.get(word) + 1);
           } 
        }
    
        // Convert our map of word->frequency to a list of Word objects.
        for(Map.Entry<String, Integer> entry : frequencyMap.entrySet()) {
          Word word = new Word(entry.getKey());
          word.frequency = entry.getValue();
          wordList.add(word);
        }
    }
    
  2. # 2 楼答案

    for-each循环正在wordList上迭代,但这是一个空的ArrayList,因此代码永远不会到达wordList.add(newWord);

  3. # 3 楼答案

    我很感激,也许你想对你的算法不起作用的原因提出批评,或者这是一个更大问题的例子,但如果你想做的只是计算发生次数,有一种更简单的方法

    使用Java8中的Streams,您可以将其归结为一种方法—在文件中创建Stream行,将它们小写,然后使用Collector对它们进行计数

    public static void main(final String args[]) throws IOException
    {
        final File file = new File(System.getProperty("user.home") + File.separator + "Desktop" + File.separator + "myFile.txt");
    
        for (final Entry<String, Long> entry : countWordsInFile(file).entrySet())
        {
            System.out.println(entry);
        }
    }
    
    public static Map<String, Long> countWordsInFile(final File file) throws IOException
    {
        return Files.lines(file.toPath()).map(String::toLowerCase).collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    }
    

    到目前为止,我还没有对Streams做过任何事情,所以欢迎任何批评