4
\$\begingroup\$

I've made a program that works, but i want to make it reusable. This code reads in a dictionary object created in another class (that i made), as well as read in a text file to put in said dictionary object. The code then loads in another text file, compares it with the dictionary, updates its frequency values and outputs to a vector. Everything works, but as i said i'm looking to make it reusable. What i mean by this is once the values have been stored in the vector, i'd like the dictionaries frequency values to reset back to 0, ready for the next text document to be compared with the dictionary, then output that to a different vector - this process will be repeated 10-12 times.

String Counter

public class StringCounter {

private LinkedList<Integer> list = new LinkedList<>();

public StringCounter(LinkedList<Integer> list) {
    this.list = list;
}

public static void main(String[] args) {

    HashMap<String, Integer> dictionary = new HashMap<String, Integer>();

    List<String> textFileList = Arrays.asList("Test.txt", "Test2.txt");

    try {

        Dictionary reader = new Dictionary(dictionary);

        for (String text : textFileList) {
            reader.fileScanner(text);
        }

        Scanner textFile = new Scanner(new File("Test4.txt"));
        ArrayList<String> file = new ArrayList<String>();

        while(textFile.hasNext()) {
            file.add(textFile.next().trim().toLowerCase());
        }

        for(String word : file) {
            Integer dict = dictionary.get(word);
            if (!dictionary.containsKey(word)) {
                    dictionary.put(word, 1); 
            } else {
                    dictionary.put(word, dict + 1);
            }
        }

        textFile.close();

        } catch(FileNotFoundException e){
            e.printStackTrace();
        } 

    Vector<Integer> vec1 = new Vector<>(dictionary.values());

    for (Integer count : vec1) {
        System.out.println(count);
    }   
}
}

Dictionary

public class Dictionary {
    // Declare set in a higher scope (making it a property within the object)
    private HashMap<String, Integer> dictionary = new HashMap<String, Integer>();

    // Assigns the value of the parameter to the field of the same name
    public Dictionary(HashMap<String, Integer> dictionary) {
        this.dictionary = dictionary;
    }

    // Gets input text file, removes white spaces and adds to dictionary object
    public void fileScanner(String textFileName) {
        try {

            Scanner textFile = new Scanner(new File(textFileName));

            while (textFile.hasNext()) {
                 dictionary.put(textFile.next().trim(), 0);
            }

            textFile.close();

        } catch (FileNotFoundException e) {
             e.printStackTrace();
        }
    }

    public void printDict(HashMap<String, Integer> dictionary) {
        System.out.println(dictionary.keySet());
    }    
}
\$\endgroup\$
  • 1
    \$\begingroup\$ The Dictionary class has been included in the question \$\endgroup\$ – FeelingLikeAJabroni Jun 20 '18 at 12:42
3
\$\begingroup\$

Usage of interfaces

HashMap<String, Integer> dictionary = ...

Try to use interfaces on the lefthand side as a best practice: Map, List, ... as it will make you independent of hashmap, linkedhashmap,...

also try not to use vector unless really necessary (https://stackoverflow.com/questions/2986296/what-are-the-differences-between-arraylist-and-vector)

Naming

HashMap<String, Integer> dictionary = new HashMap<String, Integer>(); 
...
Dictionary reader = new Dictionary(dictionary);

There is a class dictionary, a map with the same name and when initalizing an instance of Dictionary, then it is called "reader". This is confusing

reader.fileScanner(text)

This method name does not really indicate an action. reader.scanFile(text) would be better.

Reusing dictionary data

you could make the counting of the words a method of the dictionary where you build a new map with only a count for the words encountered in the new text file(s) and return that map.

Comments

avoid comments like

// Assigns the value of the parameter to the field of the same name

as they describe what you do in the code, which you can see by reading the code. When putting a comment then at least tell why some piece of code is implemented as such (specific issue, specific algorithm, ...)

Error handling

e.printstacktrace is by preference replaced by a logging framework (log4j2, logback, slf4j as façade, ...) Perhaps you can make the method throw ioException and make the calling code handle this?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.