我有一个存储键和值的模型类:
public class KeyValue {
private Object key;
private String value;
KeyValue () {
}
KeyValue (Object key, String value) {
this.key=key;
this.value=value;
}
public Object getKey() {
return this.key;
}
public void setKey(Object key) {
this.key=key;
}
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value=value;
}
@Override
public String toString() {
return this.value;
}
}
我使用这个类来填充JComboBox
的模型:
for (int i = 0; i < universes.length; i++) {
ComboBox_Universes.addItem(new KeyValue(infoObject.ID,infoObject.title));
}
我想重构这个逻辑,使用一个可以支持两个目标的Java集合类(称之为KeyValueCollection
):
1)KeyValueCollection
可用于填充JComboBox
的模型。类似的东西:
//get a KeyValueCollection filled with data from helper class
KeyValueCollection universeCollection = Repository.getUniverseCollection();
//use this collection as the JComboBox's model
ComboBox_Universes.setModel(universeCollection);
2)我可以使用KeyValueCollection
将密钥转换为值:
//ID retrieve from another control
int universeID = (int)this.Table_Values.getModel().getValueAt(row, COLUMN_ID);
//convert ID to name
String universeName = universeCollection.get(universeID).getValue();
在.NET世界中,我会使用KeyedCollection类,但我对Java不是很熟悉。
非常感谢帮助。
答案 0 :(得分:3)
你可以使用像这样的自定义类(运行main函数来查看它的行为):
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
public class KeyValueComboboxModel extends AbstractListModel implements ComboBoxModel, Map<String, String> {
private TreeMap<String,String> values = new TreeMap<String,String>();
private Map.Entry<String, String> selectedItem = null;
public Object getSelectedItem() {
return selectedItem;
}
public void setSelectedItem(Object anItem) {
this.selectedItem = (java.util.Map.Entry<String, String>) anItem;
fireContentsChanged(this, -1, -1);
}
public Object getElementAt(int index) {
List<Map.Entry<String, String>> list = new ArrayList<Map.Entry<String, String>>(values.entrySet());
return list.get(index);
}
public int getSize() {
return values.size();
}
public void clear() {
values.clear();
}
public boolean containsKey(Object key) {
return values.containsKey(key);
}
public boolean containsValue(Object value) {
return values.containsValue(value);
}
public Set<java.util.Map.Entry<String, String>> entrySet() {
return values.entrySet();
}
public String get(Object key) {
return values.get(key);
}
public Set<String> keySet() {
return values.keySet();
}
public String put(String key, String value) {
return values.put(key, value);
}
public String remove(Object key) {
return values.remove(key);
}
public int size() {
return values.size();
}
public Collection<String> values() {
return values.values();
}
public boolean isEmpty() {
return values.isEmpty();
}
public void putAll(Map<? extends String, ? extends String> m) {
values.putAll(m);
}
private static String entryToString(Map.Entry<String, String> entry) {
String str = "" + entry.getKey() + "->" + entry.getValue();
return str;
}
public static void main(String[] args) {
Map<String,String> map= new HashMap<String,String>(){{
put("1","blue");
put("2","red");
put("3","white");
put("4","black");
}};
JFrame f = new JFrame();
f.setContentPane(new JPanel(new BorderLayout()));
KeyValueComboboxModel model = new KeyValueComboboxModel();
model.putAll(map);
final JComboBox combo = new JComboBox(model);
combo.setRenderer(new DefaultListCellRenderer(){
@Override
public Component getListCellRendererComponent(JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
if(value instanceof Map.Entry){
Map.Entry<String,String> entry = (java.util.Map.Entry<String, String>) value;
String str = entryToString(entry);
return super.getListCellRendererComponent(list, str, index, isSelected, cellHasFocus);
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
});
final JLabel lab = new JLabel("Nothing selected");
combo.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
if(combo.getSelectedItem()!=null){
lab.setText(entryToString((java.util.Map.Entry<String, String>) combo.getSelectedItem()));
} else {
lab.setText("");
}
}
});
f.getContentPane().add(combo,BorderLayout.CENTER);
f.getContentPane().add(lab,BorderLayout.SOUTH);
f.setSize(300,80);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
编辑:要处理选定的项目和键,您可以添加以下方法:
public void setSelectedKey(String key){
selectedItem = values.ceilingEntry(key);
setSelectedItem(key);
}
public void setSelectedItem(String key, String value){
values.put(key, value);
setSelectedKey(key);
}
默认情况下,值按照键的自然顺序排序(键的字母顺序,这里,因为它们是String
)。如果您需要其他排序,请在java.util.Comparator
中添加TreeMap
(请参阅TreeMap文档)。
答案 1 :(得分:1)
Map(实现HashMap)是一个Key-Value类。
它使用方法#get。
从键转换为值还有访问所有键,所有值等的方法。因此,用它来填充模型应该没有问题。
它还包含一个名为Map.Entry的键值对。
答案 2 :(得分:1)
java.util.Map
实施怎么样?
HashMap
,您可以:
Map<Object, String> map = new HashMap<Object, String>();
map.put(key, value);
Object value = map.get(key);
但是,您无法使用JComboBox
直接填充Map
。您可以将所有键添加到JComboBox
,然后在需要时获取相应的值。添加可以通过多种方式完成,其中两种方式:
new JComboBox(map.keySet().toArray(new Object[]));
循环:
for (Object key : map.keySet() {
comboBox.addItem(key);
}
答案 3 :(得分:1)
您的第二个要求表明您需要Map,但ComboboxModel是ListModel,这表明您希望能够通过“索引”有效地检索元素。
我不相信任何标准集合都可以为您完成此操作,就像您想要的那样。您可以创建一个Map,然后将值复制到单独的List / ComboboxModel,也可以使用类似IndexedList的东西(一个维护索引Map的List实现)。
答案 4 :(得分:0)
我认为普通HashMap<Object,String>
可以满足您的大部分需求:
// Build the map
Map<Object,String> map = new HashMap<Object,String>();
for(InfoObject io : universes)
map.put(io.ID,io.title);
// Populate the ComboBox
for(String s : map.values())
ComboBox_Universes.addItem(s);
// Convert ID to name
int universeID = (int)this.Table_Values.getModel().getValueAt(row, COLUMN_ID);
String universeName = map.get(universeID);
答案 5 :(得分:0)
我使用以下代码:
/**
* This class is slightly modified version of the Pair class from this thread:
* http://stackoverflow.com/questions/156275/what-is-the-equivalent-of-the-c-pairl-r-in-java
* As suggested in the thread above, I have made first & second to be final members.
* I have made it into an Map.Entry<K,V> type, so it is suitable to be an element
* of any Java Hash map...
*
* @author Dejan Lekic - http://dejan.lekic.org
*/
public class Pair<KeyT, ValueT> implements Map.Entry<KeyT, ValueT> {
protected KeyT first;
protected ValueT second;
public Pair(final KeyT argFirst, final ValueT argSecond) {
super();
this.first = argFirst;
this.second = argSecond;
}
@Override
public int hashCode() {
int hashFirst = (first != null) ? first.hashCode() : 0;
int hashSecond = (second != null) ? second.hashCode() : 0;
return (hashFirst + hashSecond) * hashSecond + hashFirst;
}
@Override
public boolean equals(final Object other) {
if (other instanceof Pair) {
Pair otherPair = (Pair) other;
return ((this.first == otherPair.first
|| (this.first != null && otherPair.first != null
&& this.first.equals(otherPair.first)))
&& (this.second == otherPair.second
|| (this.second != null && otherPair.second != null
&& this.second.equals(otherPair.second))));
} // if
return false;
} // equals() method
@Override
public String toString() {
// previously we used " - " as a separator. Now we will use the 0x1f character, called the UNIT
// SEPARATOR to separate two fields in a String object. See the Sise class for more information.
return first + "\u001f" + second;
}
public KeyT getFirst() {
return first;
}
public void setFirst(final KeyT argFirst) {
this.first = argFirst;
}
public ValueT getSecond() {
return second;
}
public void setSecond(final ValueT argSecond) {
this.second = argSecond;
}
@Override
public ValueT setValue(final ValueT argNewValue) {
ValueT oldValue = second;
second = argNewValue;
return oldValue;
}
@Override
public ValueT getValue() {
return second;
}
@Override
public KeyT getKey() {
return first;
}
} // Pair class
// $Id: Pair.java 149 2012-01-13 12:30:59Z dejan $