1
\$\begingroup\$

This program I made takes a word as an input and prints all the anagrams of the word in a given word base from a txt file. I would like advice for code style, Java specific practices etc as I'm new to to the Java language (about 2 months).

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;

public class Anagrams {
    public static void main(String[] args) throws FileNotFoundException {
        Scanner s = new Scanner(new File("bg.txt"));

        ArrayList<String> words = new ArrayList<String>();
        while (s.hasNext()) {
            words.add(s.next());
        }

        HashMap<String, ArrayList<String>> map = new HashMap<>();

        for (String str : words) {
            char[] temp = str.toCharArray();
            Arrays.sort(temp);
            String key = new String(temp).toLowerCase();
            if (map.get(key) != null) {
                map.get(key).add(str.toLowerCase());
            } else {
                ArrayList<String> anagramList = new ArrayList<>();
                anagramList.add(str);
                map.put(key, anagramList);
            }
        }
        Scanner input = new Scanner(System.in);
        String str = input.next();
        char[] key = str.toCharArray();
        Arrays.sort(key);
        str = new String(key).toLowerCase();
        if (!map.containsKey(str)) {
            System.out.print("word not found");
        } else if (map.get(str).size() != 1) {
            for (String p : map.get(str)) {
                System.out.print(p + " ");
            }
        } else {
            System.out.print("No anagrams found");
        }
        s.close();
        input.close();
    }
}
\$\endgroup\$
1
\$\begingroup\$

Use more functions

The current implementation is all in the main method. Break the problem down to smaller pieces, so that each function has a single responsibility, for example:

  • Read words from a text file into a List and return it
  • Convert a word to "normalized" form (sorted and lowercased)
  • Convert a list of words to a map of normalized form to list of anagrams
  • Read input and respond with the list of anagrams

Use interface types instead implementations

Instead of these:

ArrayList<String> words = new ArrayList<String>();
// ...

HashMap<String, ArrayList<String>> map = new HashMap<>();

It's better to use interface types in declarations, like this:

List<String> words = new ArrayList<>();
// ...

Map<String, List<String>> map = new HashMap<>();

And on the right-hand side, use the diamond operator <> when possible.

Use try-with-resources when working with resources

Instead of this:

Scanner s = new Scanner(new File("bg.txt"));

ArrayList<String> words = new ArrayList<String>();
while (s.hasNext()) {
    words.add(s.next());
}

// much much later...
s.close();

Write like this:

List<String> words = new ArrayList<>();
try (Scanner s = new Scanner(new File("bg.txt"))) {
    while (s.hasNext()) {
        words.add(s.next());
    }
}

Notice that s.close() is no longer necessary. That also means you cannot "forget" to close a resource manually.

You can read more about this here: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

\$\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.