我有一个转换长度的Swing应用程序。英寸到厘米,脚到院子,等等。我想知道我是否能让超大的HashMap变得更小,或者更高效。任何其他建议也将受到赞赏。
import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import javax.swing.*;
public class LengthConverter{
private JFrame frame;
private JLabel welcomeLabel;
private JPanel fromPanel;
private JLabel centerLabel;
private JTextField fromField;
private JComboBox<String> fromBox;
private JPanel toPanel;
private JTextField toField;
private JComboBox<String> toBox;
private JButton submitButton;
private JLabel noteLabel;
private JPanel bottomPanel;
private final String[] lengthTypes = {"Inches", "Centimeters", "Feet", "Yards", "Meters", "Millimeters"};
private final HashMap<String, HashMap<String, Double>> conversions = new HashMap<>();
public LengthConverter() {
conversions.put("Inches", new HashMap<>());
conversions.get("Inches").put("Inches", 1.0);
conversions.get("Inches").put("Centimeters", 2.54);
conversions.get("Inches").put("Feet", 0.0833333);
conversions.get("Inches").put("Yards", 0.0277778);
conversions.get("Inches").put("Meters", 0.0254);
conversions.get("Inches").put("Millimeters", 25.4);
conversions.put("Centimeters", new HashMap<>());
conversions.get("Centimeters").put("Inches", 0.393701);
conversions.get("Centimeters").put("Centimeters", 1.0);
conversions.get("Centimeters").put("Feet", 0.0328084);
conversions.get("Centimeters").put("Yards", 0.0109361);
conversions.get("Centimeters").put("Meters", 0.01);
conversions.get("Centimeters").put("Millimeters", 10.0);
conversions.put("Feet", new HashMap<>());
conversions.get("Feet").put("Inches", 12.0);
conversions.get("Feet").put("Centimeters", 30.48);
conversions.get("Feet").put("Feet", 1.0);
conversions.get("Feet").put("Yards", 0.3333333);
conversions.get("Feet").put("Meters", 0.3048);
conversions.get("Feet").put("Millimeters", 304.8);
conversions.put("Yards", new HashMap<>());
conversions.get("Yards").put("Inches", 36.0);
conversions.get("Yards").put("Centimeters", 91.44);
conversions.get("Yards").put("Feet", 3.0);
conversions.get("Yards").put("Yards", 1.0);
conversions.get("Yards").put("Meters", 0.9144);
conversions.get("Yards").put("Millimeters", 914.4);
conversions.put("Meters", new HashMap<>());
conversions.get("Meters").put("Inches", 39.3701);
conversions.get("Meters").put("Centimeters", 100.0);
conversions.get("Meters").put("Feet", 3.28084);
conversions.get("Meters").put("Yards", 1.09361);
conversions.get("Meters").put("Meters", 1.0);
conversions.get("Meters").put("Millimeters", 1000.0);
conversions.put("Millimeters", new HashMap<>());
conversions.get("Millimeters").put("Inches", 0.0393701);
conversions.get("Millimeters").put("Centimeters", 0.1);
conversions.get("Millimeters").put("Feet", 0.00328084);
conversions.get("Millimeters").put("Yards", 0.00109361);
conversions.get("Millimeters").put("Meters", 0.001);
conversions.get("Millimeters").put("Millimeters", 1.0);
}
public static void main(String[] args) {
new LengthConverter().go();
}
public void go() {
frame = new JFrame("Length Conversions");
fromPanel = new JPanel();
centerLabel = new JLabel("Is...");
fromField = new JTextField(10);
fromBox = new JComboBox<>(lengthTypes);
toPanel = new JPanel();
toBox = new JComboBox<>(lengthTypes);
toField = new JTextField(10);
toField.setEnabled(false);
welcomeLabel = new JLabel("Welcome to the length converter!");
submitButton = new JButton("Convert!");
noteLabel = new JLabel("Note: Rounds to fit the text field.");
bottomPanel = new JPanel();
submitButton.addActionListener(new SubmitListener());
fromPanel.setLayout(new BoxLayout(fromPanel, BoxLayout.X_AXIS));
fromPanel.add(fromField);
fromPanel.add(fromBox);
toPanel.setLayout(new BoxLayout(toPanel, BoxLayout.X_AXIS));
toPanel.add(toField);
toPanel.add(toBox);
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.X_AXIS));
bottomPanel.add(noteLabel);
bottomPanel.add(submitButton);
Font labelFont = new Font("Arial", Font.BOLD, 24);
welcomeLabel.setFont(labelFont);
frame.setLayout(new BorderLayout());
Container window = frame.getContentPane();
window.add(BorderLayout.NORTH, welcomeLabel);
window.add(BorderLayout.WEST, fromPanel);
window.add(BorderLayout.EAST, toPanel);
window.add(BorderLayout.CENTER, centerLabel);
window.add(BorderLayout.SOUTH, bottomPanel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
class SubmitListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Double numToConvert = Double.parseDouble(fromField.getText());
Double conversionRate = conversions.get(fromBox.getSelectedItem()).get(toBox.getSelectedItem());
String result = Double.toString(numToConvert * conversionRate);
int length = result.length();
if (length > 4) {
Dimension d = frame.getSize();
frame.setSize(length + d.width - 16, d.height);
toField.setColumns(length);
}
else {
toField.setColumns(4);
frame.pack();
}
toField.setText(result);
frame.revalidate();
}
}
}发布于 2015-04-21 20:53:52
与包含从每个单元到每个其他单元的转换因子的嵌套散列映射不同,只需将每个单元映射为单个公共单元即可,例如仪表:
HashMap<String, Double> conversions = new HashMap<>();
conversions.put("Centimeters", 0.01);
conversions.put("Inches", 0.0254);
// ...然后,两个单位之间的转换系数可以简单地计算为
Double conversionRate = conversions.get(fromUnit) / conversions.get(toUnit);实际上,您根本不需要一个散列映射,您可以将信息存储在两个并行数组中:
private final String[] lengthTypes = { "Inches", "Centimeters", "Feet", "Yards", "Meters", "Millimeters"};
private final double[] conversionFactors = { 0.054, 0.01, 0.3048, 0.9144, 1.0, 0.001 };然后
double conversionRate = conversionFactors[fromBox.getSelectedIndex()] / conversionFactors[toBox.getSelectedIndex()];或者,定义
class Unit {
String name;
double conversionFactor;
Unit(String name, double conversionFactor) {
this.name = name;
this.conversionFactor = conversionFactor;
}
}和可用单位的清单
Unit[] units = {
new Unit("Centimeters", 0.01),
new Unit("Inches", 0.0254)
// ...
};然后将单元名称和相应的因子定义在一起,如果对单元进行重新排序或重命名,则不太容易出错。然后,组合框将被填充
for (Unit unit : units) {
fromBox.addItem(unit.name);
toBox.addItem(unit.name);
}两个单位之间的换算系数是
double conversionRate = units[fromBox.getSelectedIndex()].conversionFactor / units[toBox.getSelectedIndex()].conversionFactor;发布于 2015-04-21 22:13:43
LengthConverter是做什么的?它会显示按钮,对点击做出反应吗?或者转换长度?
这显然违反了分离关注点原则。只需将转换提取到单独的类。
实际上,Martin .S的Unit已经这么做了,您也可以使用枚举(注释来自隆布克,但是应该是显而易见的)。
@RequiredArgsConstructor @Getter
public enum Unit {
METER(1.0),
CENTIMETER(0.01),
INCH(0.0254),
FURLONG(201.168),
...
;
double convertFrom(double amount, Unit unit) {
return amount * unit.meters / this.meters;
}
private final double meters;
}有一个类似的表情
Unit.INCH.convertFrom(2, Unit.LIGHT_YEAR);告诉你有多少英寸等于2光年。不需要地图。
枚举的明显缺点是它们不能被扩展,但是对于作者来说,这是没有问题的(无论如何,有用的单元集是相当有限的)。
https://codereview.stackexchange.com/questions/87594
复制相似问题