Самый эффективный способ проверить файл на наличие списка слов

У меня только что было домашнее задание, которое требовало, чтобы я добавил все ключевые слова Java в HashSet. Затем прочитайте файл .java и подсчитайте, сколько раз какое-либо ключевое слово появилось в файле .java.

Я выбрал следующий маршрут: создал массив String[], содержащий все ключевые слова. Создал HashSet и использовал Collections.addAll для добавления массива в HashSet. Затем, когда я перебирал текстовый файл, я проверял его с помощью HashSet.contains(currentWordFromFile);

Кто-то рекомендовал использовать HashTable для этого. Затем я увидел аналогичный пример с использованием TreeSet. Мне было просто любопытно... какой рекомендуемый способ сделать это?

(Полный код здесь: http://pastebin.com/GdDmCWj0)


person snowBlind    schedule 27.04.2011    source источник


Ответы (2)


Попробуйте Map<String, Integer>, где String — это слово, а Integer — количество просмотров слова.

Одним из преимуществ этого является то, что вам не нужно обрабатывать файл дважды.

person TofuBeer    schedule 27.04.2011
comment
Кажется, что таким образом будет проще подсчитывать конкретные ключевые слова по отдельности. Как вы думаете, есть ли недостатки в том, как я это сделал, учитывая, что мне не нужно подсчитывать каждое ключевое слово по отдельности? - person snowBlind; 27.04.2011
comment
Запустите карту, содержащую только ключевые слова и значение 0 для каждого из них. Вызовите Map.get, чтобы получить значение, если оно возвращает ненулевое значение, увеличьте его и повторно сохраните. Если оно было нулевым, то делать нечего, потому что это не ключевое слово. - person TofuBeer; 27.04.2011

Вы сказали "было домашнее задание", так что я предполагаю, что вы закончили с этим.

Я бы сделал немного по другому. Во-первых, я думаю, что некоторые ключевые слова в вашем массиве String были неверными. Согласно Википедии и Oracle, Java содержит 50 ключевых слов. Во всяком случае, я довольно хорошо прокомментировал свой код. Вот что я придумал...

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Map;
import java.util.HashMap;

public class CountKeywords {

    public static void main(String args[]) {

        String[] theKeywords = { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while" };

        // put each keyword in the map with value 0 
        Map<String, Integer> theKeywordCount = new HashMap<String, Integer>();
        for (String str : theKeywords) {
            theKeywordCount.put(str, 0);
        }

        FileReader fr;
        BufferedReader br;
        File file = new File(args[0]);

        // attempt to open and read file
        try {
            fr = new FileReader(file);
            br = new BufferedReader(fr);

            String sLine;

            // read lines until reaching the end of the file
            while ((sLine = br.readLine()) != null) {

                // if an empty line was read
                if (sLine.length() != 0) {

                    // extract the words from the current line in the file
                    if (theKeywordCount.containsKey(sLine)) {
                        theKeywordCount.put(sLine, theKeywordCount.get(sLine) + 1);
                    }
                }
            }

        } catch (FileNotFoundException exception) {
            // Unable to find file.
            exception.printStackTrace();
        } catch (IOException exception) {
            // Unable to read line.
            exception.printStackTrace();
        } finally {
                br.close();
            }

        // count how many times each keyword was encontered
        int occurrences = 0;
        for (Integer i : theKeywordCount.values()) {
            occurrences += i;
        }

        System.out.println("\n\nTotal occurences in file: " + occurrences);
    }
}

Каждый раз, когда я встречаю ключевое слово из файла, я сначала проверяю, есть ли оно на карте; если это не так, это недопустимое ключевое слово; если это так, то я обновляю значение, с которым связано ключевое слово, т. е. я увеличиваю связанное Integer на 1, потому что мы видели это ключевое слово еще раз.

В качестве альтернативы вы можете избавиться от этого последнего цикла for и просто вести текущий счет, поэтому вместо этого у вас будет...

if (theKeywordCount.containsKey(sLine)) {
    occurrences++;
}

... и вы распечатываете счетчик в конце.

Я не знаю, является ли это самым эффективным способом сделать это, но я думаю, что это хорошее начало.

Дайте знать, если у вас появятся вопросы. Надеюсь, это поможет.
Христо

person Hristo    schedule 27.04.2011
comment
Христо, пока я не просмотрела весь твой код, да, домашнее задание выполнено. Кроме того, почему у меня более 50 ключевых слов, в домашнем задании указано, что мы также должны включить 3 зарезервированных слова; false, null и true... что я забыл упомянуть. Спасибо за пост .. Я собираюсь прочитать и посмотреть, как вы это сделали сейчас. Я определенно ценю подход, к которому подойдет тот, у кого гораздо больше опыта программирования. - person snowBlind; 27.04.2011
comment
1. попался. Я добавлю их в свой список. 2. У меня не так много опыта программирования. Я все еще студент колледжа :) 3. удачи! дайте мне знать, что вы думаете, и если у вас есть вопросы. А пока я собираюсь немного поспать. - person Hristo; 27.04.2011
comment
br.close относится к оператору finally. java.util.Scanner кажется гораздо менее сложным в использовании, чем br(fr(file)). Комментарии - это шум (FileNotFoundException exception) {// Unable to find file. или // Unable to read line. Вместо if (a == 0) {/*empty*/} else ... просто напишите if (a != 0) { ... . - person user unknown; 27.04.2011
comment
спасибо за ваши предложения. что касается Scanner, по моему опыту, это медленнее, чем использование FileReader и BufferedReader - person Hristo; 27.04.2011