Anagram finder in Java

This is the Java implementation of the anagram program. The problem and the solution is described in the main anagram article. Do read that article first.

Also, you may find the C++ article helpful, since it describes member data and functions in some detail, not repeated here. This article describes only the differences between the C++ implementation and this implementation.

The source code

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.Arrays;
import java.util.Vector;

//--------------------------------------------------------------------------------------- Word

class Word {
    public static String get_unified(String value) {
        int len = value.length();
        char[] tmp = new char[len];
        for (int n = 0; n < len; n++)
            tmp[n] = value.charAt(n);
        Arrays.sort(tmp);
        return new String(tmp);
    }

    public Word(int offset, String value) {
        this.offset = offset;
        this.value = value;
        this.unified = get_unified(value);
    }

    int    offset;
    String value;
    String unified;
}

//--------------------------------------------------------------------------------------- AnagramFinder

class AnagramFinder {
    private int          len;
    private Word[]       words;
    private Vector<Word> accepted;
    private int          low_offset;
    public  static int   comparisons = 0;
    public  static int   MINIMUM = 3;

    public AnagramFinder(char[] buf, int len) {
        int end = buf.length - len + 1;
        this.accepted = new Vector<Word>(end);
        this.len     = len;
        this.words   = new Word[end];
        for (int n = 0; n < end; n++)
            words[n] = new Word(n, new String(buf, n, len));
    }

    private void print_one_result() {
        System.out.format("%3d:", accepted.size());
        for (Word it : accepted)
            System.out.format(" %4d:%s", it.offset, it.value);
        System.out.println();
    }

    private void add_candidate(Word cand) {
        if (cand.offset < low_offset)
            return;
        for (var it : accepted)
            if (it.value.equals(cand.value))
                return;
        accepted.add(cand);
        low_offset = cand.offset + len;
    }

    private void add_range(int begin, int end) {
        if ((end-begin) >= MINIMUM) {
            accepted.clear();
            low_offset = 0;
            for (int n = begin; n < end; n++)
                add_candidate(words[n]);
            if (accepted.size() >= MINIMUM)
                print_one_result();
        }
    }

    public void find_all() {
        Arrays.sort(words,
                    new Comparator<Word>() {
                        public int compare(Word a, Word b) {
                            AnagramFinder.comparisons++;
                            int rval = a.unified.compareTo(b.unified);
                            return (0 != rval) ? rval : (a.offset - b.offset);
                        }
                    });
        int begin = 0;
        for (int n = 1; n < words.length; n++) {
            if (!words[n].unified.equals(words[begin].unified)) {
                add_range(begin, n);
                begin = n;
            }
        }
        add_range(begin, words.length);
    }
}

//--------------------------------------------------------------------------------------- Main program

class anagram {
    static char[] text;

    static void read_text() {
        try {
            char[] tmp = new char[500 * 512];
            var is = new InputStreamReader(System.in);
            var in = new BufferedReader(is);
            int ch;
            int nread = 0;
            while ((ch = in.read()) > 0) {
                if (Character.isLetter(ch))
                    tmp[nread++] = Character.toUpperCase((char)ch);
            }
            text = Arrays.copyOf(tmp, nread);
        } catch (Exception ex) {
            System.out.format("%s\n", ex.toString());
        }
    }

    public static void  main(String[] argv) {
        assert 2 == argv.length;
        int from = Integer.parseInt(argv[0]);
        int to   = Integer.parseInt(argv[1]);

        read_text();

        for (int len = from; len <= to; len++) {
            if (len > from)
                System.out.println();
            System.out.format("len = %d\n", len);
            new AnagramFinder(text, len).find_all();
            if (null == System.getenv("NOGC")) System.gc();
        }
        System.out.format("string length = %5d, comparisons = %d\n", text.length, AnagramFinder.comparisons);
    }
}

You can reach me by email at “lars dash 7 dot sdu dot se” or by telephone +46 705 189090

View source for the content of this page.