0

I am trying to count the occurences of numbers entered in a program by a user as the user inputs the numbers. They all are integers. This must be displayed in a TextArea. If more than one number has the same count of occurences it also must be displayed in the TextArea.

I have found some very confusing information about how to do this.

I have begun by using a TreeMap to add the numbers to and as each number is inputted it checks to see if that number has already been inputted or not. If not then it enters it into the key and assignes it a value of 1, otherwise it adds to the value by 1.

I have read the Java API over and over. I have found the SortedMap but that does me no good as essentially, from what I understand, it is already sorted by key in a TreeMap. I would like the TreeMap to sort by value then pick out all the keys with that same corresponding value. I have found a method to sort it by value but when I implement it it only allows me to get the .last().getKey().intValue(). I had thought maybe an array would be ideal but I am not sure how to go about that.

Oh and I am in my second class of Java, so I know little and know even less of what I don't know so please keep that in mind.

public class NumberCounterGUI extends JFrame {

    JLabel jlblEnteranumber = new JLabel("Enter a number:");

    JTextField jtfEnteranumber = new JTextField();

    JTextArea jtaNumbers = new JTextArea();
    JTextArea jtaMessages = new JTextArea();

    JScrollPane numbersScrollPane = new JScrollPane(jtaNumbers);

    JPanel panel1 = new JPanel();
    JPanel panel2 = new JPanel();
    JPanel panel3 = new JPanel(new BorderLayout());

    Color defaultBackgroundColor = new Color(238, 238, 238);

    Font defaultFontBold = new Font("Dialog", Font.BOLD, 12);

    TreeMap<Integer, Integer> numbersEntered = new TreeMap<>();

    int numberEntered, value;

    public NumberCounterGUI() {

        jtfEnteranumber.setPreferredSize(new Dimension(84, 20));
        jtfEnteranumber.setToolTipText("Integers Only");
        jtfEnteranumber.addActionListener(new NumberCounterGUI.Listener());

        jtaNumbers.setEditable(false);
        jtaNumbers.setLineWrap(true);
        jtaNumbers.setWrapStyleWord(true);

        numbersScrollPane.setVerticalScrollBarPolicy(JScrollPane
                .VERTICAL_SCROLLBAR_AS_NEEDED);
        numbersScrollPane.setPreferredSize(new Dimension(300, 75));

        jtaMessages.setFont(defaultFontBold);
        jtaMessages.setBackground(defaultBackgroundColor);
        jtaMessages.setEditable(false);

        panel1.add(jlblEnteranumber);
        panel1.add(jtfEnteranumber);

        panel2.add(jtaMessages);

        panel3.add(panel1, BorderLayout.NORTH);
        panel3.add(numbersScrollPane, BorderLayout.CENTER);
        panel3.add(jtaMessages, BorderLayout.SOUTH);

        add(panel3);
    }

    class Listener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            try {
                Long numberEnteredLong = Long.valueOf(jtfEnteranumber.getText());
                if (numberEnteredLong <= 2147483647 &&
                        numberEnteredLong >= -2147483647) {
                    numberEntered = Integer.valueOf(jtfEnteranumber.getText());
                    jtaNumbers.insert(jtfEnteranumber.getText() + " ", 1);
                    if (numbersEntered.get(numberEntered) == null) {
                        numbersEntered.put(numberEntered, 1);
                    } else {
                        value = numbersEntered.get(numberEntered).intValue();
                        value++;
                        numbersEntered.put(numberEntered, value);
                    }
                    jtaMessages.setText(entriesSortedByValues(numbersEntered)
                            .last().getKey().intValue() +" occurred most often");
                    jtfEnteranumber.setText("");
                } else {
                    Toolkit.getDefaultToolkit().beep();
                    jtaMessages.setText(jtfEnteranumber.getText()
                            + " is out of integer range!");
                    jtfEnteranumber.setText("");
                }
            } catch (NumberFormatException z) {
                Toolkit.getDefaultToolkit().beep();
                jtaMessages.setText(jtfEnteranumber.getText()
                        + " is not a number!");
                jtfEnteranumber.setText("");
            }
            pack();
        }
    }

    // Found at http://stackoverflow.com/questions/2864840/treemap-sort-by-value
    static <K, V extends Comparable<? super V>> SortedSet<Map.Entry<K, V>>
            entriesSortedByValues(Map<K, V> map) {
        SortedSet<Map.Entry<K, V>> sortedEntries = new TreeSet<>(
                new Comparator<Map.Entry<K, V>>() {
                    @Override
                    public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) {
                        int res = e1.getValue().compareTo(e2.getValue());
                        return res != 0 ? res : 1;
                    }
                });
        sortedEntries.addAll(map.entrySet());
        return sortedEntries;
    }

    public static void main(String[] args) {
        NumberCounterGUI frame = new NumberCounterGUI();
        frame.setTitle("Enter Numbers (Integers 1 - 999)");
        frame.pack();
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}
Erick Robertson
  • 32,125
  • 13
  • 69
  • 98
Java noob
  • 19
  • 4
  • Forgot to add my imports to the code... import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; – Java noob Aug 05 '12 at 14:51
  • How to either use the current method I was able to find on this website, or an alternate method to find the numbers with the highest occurence? – Java noob Aug 05 '12 at 14:59
  • 3
    Suggest distilling this question down by removing all the swing parts. – Reimeus Aug 05 '12 at 15:07

3 Answers3

2

- Use the Collections.frequency(Collection c, Object o) method to get the occurrence of certain Object in the collection.

Kumar Vivek Mitra
  • 33,294
  • 6
  • 48
  • 75
0

Considering that you need to track the number of occurrences for every entered number, you need a map from entered_number(key) to number_of_occurrences(value).

If you use the number_of_occurrences as a key, each time the number of occurrences of an entered number changes you'll have to remove the key and add it again incremented. Suppose you do this for half of the total number of entered numbers, you will end up with a complexity of O(n/2 * logn) = O(nlogn) if you use a heap like data structure.

If you use a standard map data structure (HashMap for instance) in which you store the entered_number(key) and the number of occurrences(value) you will end up with a complexity of O(n) given by the iterations at the end when you have to discover the maximum number of occurrences first and then retrieve all the entered numbers having that frequency. So I recommend this second version.

Razvan
  • 9,925
  • 6
  • 38
  • 51
  • HashMap would be the only practical method, but then how do I actually find the occurrences and then get those to display? A loop? – Java noob Aug 05 '12 at 15:16
  • These methods of a HashMap might help you: entrySet(), values(), keySet(). They all suppose using a loop on the returned Sets/List – Razvan Aug 05 '12 at 15:18
  • returned Sets/List? These methods don't allow me to get the key from a value that is determined to be the maximum if there is more than one key with the same value. – Java noob Aug 05 '12 at 15:32
  • You have to use values(). Discover the maximum. Then, use entrySet(). Iterate through the set and each time you find an entry having a value equal to the previously discovered maximum print it's key. – Razvan Aug 05 '12 at 15:43
  • That's the issue I've been having, getting the corresponding key to display/print. I've tinkered around with the methods you've suggested but have found no way to display the key(s) based on the value found. Any thoughts? – Java noob Aug 05 '12 at 15:57
  • My previous comment describes the procedure exactly. – Razvan Aug 05 '12 at 16:20
0

One easy way to build your reference histogram would be to first gather your input data into a List. When you're ready to tabulate counts of each integer, you first sort your List, then iterate it, tracking and outputting counts with each change in value into a Map. Keep track of your highest count. Once that map is assembled, your answer is a simple lookup by that count returning the List of values matching it.

Map<Integer,List<Integer>> countedIntegers=new HashMap<Integer,List<Integer>>();
phatfingers
  • 9,770
  • 3
  • 30
  • 44