0

当用户输入数字时,我正在尝试计算用户在程序中输入的数字的出现次数。它们都是整数。这必须显示在 TextArea 中。如果多个数字具有相同的出现次数,则它也必须显示在 TextArea 中。

我发现了一些关于如何执行此操作的非常令人困惑的信息。

我已经开始使用 TreeMap 将数字添加到其中,并且在输入每个数字时,它会检查该数字是否已经输入。如果不是,则将其输入密钥并为其分配值 1,否则将值加 1。

我一遍又一遍地阅读 Java API。我找到了 SortedMap,但这对我没有好处,据我了解,它已经在 TreeMap 中按键排序。我希望 TreeMap 按值排序,然后挑选出具有相同对应值的所有键。我找到了一种按值排序的方法,但是当我实现它时,它只允许我获取 .last().getKey().intValue()。我曾认为阵列可能是理想的,但我不知道该怎么做。

哦,我在我的第二类Java,所以我知道的很少,对我不知道的东西知道得更少,所以请记住这一点。

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);
    }
}
4

3 回答 3

2

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

于 2012-08-05T16:09:07.147 回答
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>>();
于 2012-08-05T16:07:09.750 回答
0

考虑到您需要跟踪每个输入数字的出现次数,您需要一个从entered_number(key) 到number_of_occurrences(value) 的映射。

如果您使用 number_of_occurrences 作为键,则每次输入的数字的出现次数发生变化时,您都必须删除该键并重新添加它以递增。假设您对输入数字总数的一半执行此操作,如果您使用类似堆的数据结构,最终的复杂度将为 O(n/2 * logn) = O(nlogn)。

如果您使用存储输入的数字(键)和出现次数(值)的标准地图数据结构(例如 HashMap),您最终将得到 O(n) 的复杂度,该复杂度由最后的迭代给出您必须首先发现最大出现次数,然后检索所有输入的具有该频率的数字。所以我推荐第二个版本。

于 2012-08-05T15:13:21.903 回答