채팅에 관한 토론 에서처럼 가능한 해결책은 다음과 같습니다. 나는 디버깅도이 있으므로주의의 위험 부담 테스트하지 않았습니다 :
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 (...)'메소드를 사용할 수 있습니다. –
@HovercraftFullOfEels 답장을 보내 주셔서 감사합니다. :) 아마도 대신 TreeSet을 사용할 것입니다. 내 자신을 구현 ListModel에 관해서는 - 나는 실제로 시도했다. Set에 캡슐화하는 방법과 ListDataListeners로 처리하는 방법을 이해할 수 없었습니다. – Vlad
엄밀히 말하면'HashSet'인가, 아니면 단순히 비슷한 기능과 성능을 지닌 속성일까요? –