“Space and Time Efficient” way of finding all anagram groups
calcProduct

You don't need the L on these lines:


long res = 1L;
return -1L;



Instead of explaining what 65 is in a comment:


    if (c &lt; 65) { // ASCII A = 65



You can use 'A' directly. And checking c &lt; 'A' is not enough. You should also check c &gt; 'Z'.

The method rewritten:

private static long calcProduct(char[] letters) {
    long res = 1;
    for (char c : letters) {
        if (c &lt; 'A' || c &gt; 'Z') {
            return -1;
        }
        int index = c - 'A';
        res = res * PRIMES[index];
    }
    return res;
}


findAllAnagrams

Instead of StringBuffer, it's recommended to use StringBuilder.

Instead of new HashMap&lt;Long, StringBuffer&gt;() you can use the diamond operator &lt;&gt; to simplify.

The anagrams map is written to but never read. You can remove it.

file is a poor name for an array of words. (words would be better)

The concatenation in sb.append("" + word) is pointless, as sb.append(word) has the same effect.

In general, instead of concatenation inside sb.append(...), it's recommended to chain .append(...).append(...) calls.

Instead of creating a new StringBuffer in every iteration of the loop, you could just create when it's actually needed: when putting the first word in the map.

Finally, it's recommended to always use braces on single-statement if-else conditions.

The method rewritten:

public static Map&lt;Long, StringBuilder&gt; findAllAnagrams(String[] words) {
    Map&lt;Long, StringBuilder&gt; result = new HashMap&lt;&gt;();

    for (String word : words) {
        long product = calcProduct(word.toUpperCase().toCharArray());

        StringBuilder sb = result.get(product);
        if (sb == null) {
            result.put(product, new StringBuilder(word));
        } else {
            sb.append(",").append(word);
        }
    }
    return result;
}


But, this is not nearly good enough. It would be better to use a List&lt;String&gt; as the values:

public static Map&lt;Long, List&lt;String&gt;&gt; findAllAnagrams(String[] words) {
    Map&lt;Long, List&lt;String&gt;&gt; result = new HashMap&lt;&gt;();

    for (String word : words) {
        long product = calcProduct(word.toUpperCase().toCharArray());

        List&lt;String&gt; anagrams = result.get(product);
        if (anagrams == null) {
            anagrams = new ArrayList&lt;&gt;();
            result.put(product, anagrams);
        }
        anagrams.add(word);
    }
    return result;
}


main

You should not suppress the raw types warning but fix it. The loop could have been written like this:

for (Map.Entry&lt;Long, StringBuilder&gt; entry : result.entrySet()) {


And since you don't need the keys in the loop body, it's better to iterate over the values:

    for (List&lt;String&gt; anagrams : findAllAnagrams(file).values()) {
        if (anagrams.size() &gt; 1) {
            for (String word : anagrams) {
                System.out.print(word + " ");
            }
            System.out.println();
        }
    }