簡體   English   中英

如何驗證數組列表中是否存在具有特定屬性值的對象?

[英]How to verify if an object with a particular attribute value exists in an 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;
    }

}

好了,讓我們從修復當前代碼開始。 您遇到的問題是,僅在一個新單詞對象已經存在時才將其添加到列表中。 相反,當不存在新的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);
    }
}

您的for-each循環正在wordList上進行迭代,但這是一個空的ArrayList,因此您的代碼將永遠不會到達wordList.add(newWord);

我很高興您可能想批評為什么算法不起作用,或者這是一個更大問題的例子,但是如果您只想計算發生次數,那么可以采用一種更簡單的方法來完成。

使用Java 8中的流,您可以將其歸結為一種方法-在文件中創建行的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沒有做任何事情,因此歡迎任何批評。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM