根据我们在聊天中的讨论,这里有一个可能的解决方案。我还没有调试也不测试这一点,所以买者自负:
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
import javax.swing.*;
public class TreeSetInJListTest extends JPanel {
private static final long serialVersionUID = 1L;
private static final String[] DATA_ARRAY = { "one", "two", "three", "two",
"three", "this is a longer string" };
TreeSetListModel<String> stringListModel = new TreeSetListModel<String>(
String.CASE_INSENSITIVE_ORDER);
JList<String> jList = new JList<String>(stringListModel);
public TreeSetInJListTest() {
for (int i = 0; i < DATA_ARRAY.length; i++) {
stringListModel.add(DATA_ARRAY[i]);
}
add(new JScrollPane(jList));
add(new JButton(new AddToListAction("Add To List", KeyEvent.VK_A)));
}
@SuppressWarnings("serial")
private class AddToListAction extends AbstractAction {
public AddToListAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent arg0) {
String element = JOptionPane.showInputDialog(TreeSetInJListTest.this,
"Enter String:", "Insert Text Into JList",
JOptionPane.OK_CANCEL_OPTION);
stringListModel.add(element);
}
}
private static void createAndShowGui() {
TreeSetInJListTest mainPanel = new TreeSetInJListTest();
JFrame frame = new JFrame("Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class TreeSetListModel<T extends Comparable<T>> extends AbstractListModel<T> {
private static final long serialVersionUID = 1L;
private TreeSet<T> treeSet;
public TreeSetListModel() {
treeSet = new TreeSet<T>();
}
public TreeSetListModel(Comparator<? super T> comparator) {
treeSet = new TreeSet<T>(comparator);
}
@Override
public T getElementAt(int index) {
if (index < 0 || index >= getSize()) {
String s = "index, " + index + ", is out of bounds for getSize() = "
+ getSize();
throw new IllegalArgumentException(s);
}
Iterator<T> iterator = treeSet.iterator();
int count = 0;
while (iterator.hasNext()) {
T t = (T) iterator.next();
if (index == count) {
return t;
}
count++;
}
// out of index. return null. will probably never reach this
return null;
}
@Override
public int getSize() {
return treeSet.size();
}
public int getIndexOf(T t) {
int index = 0;
for (T treeItem : treeSet) {
if (treeItem.equals(treeItem)) {
return index;
}
index++;
}
return -1;
}
public boolean add(T t) {
boolean result = treeSet.add(t);
if (result) {
int index = getIndexOf(t);
fireIntervalAdded(this, index, index + 1);
}
return result;
}
public boolean remove(T t) {
int index = getIndexOf(t);
if (index < 0) {
return false;
}
boolean result = treeSet.remove(t);
fireIntervalRemoved(this, index, index + 1);
return result;
}
}
编辑:我也将扩展[AbstractListModel上](http://docs.oracle.com/javase/7/docs/api/javax/swing /AbstractListModel.html)类,而不是单独使用[ListModel](http://docs.oracle.com/javase/7/docs/api/javax/swing/ListModel.html)接口。这将允许你使用'fireXXX(...)'方法来通知任何监听者数据是否改变。 – 2012-07-11 16:46:41
@HovercraftFullOfEels感谢您的回复。 :)我可能会使用TreeSet。至于试图自己实现一个ListModel - 我确实尝试过。我无法弄清楚如何封装一个Set,以及如何处理ListDataListeners。 – Vlad 2012-07-11 16:47:13
它必须严格是'HashSet',或者只是具有相似功能和性能特征的东西? – 2012-07-11 18:27:35