Хранение данных в DefaultListModel vs ConcurrentHashMap
Я пишу графический интерфейс в swing для отображения несогласованных запросов от клиентов. Сервер заполняет LinkedBlockingQueue, в то время как другой поток берет из очереди, когда есть доступные данные. Запросы хранятся в виде Object. Вот так:
while(should_take) {
//getRequest() is blocking
Object request = server.getRequest();
//Add request to user interface
GUI.addToList(request);
}
Теперь мой вопрос, не лучше ли было бы:
Решение 1:
Храните request в ConcurrentHashMap<Integer, Object> с ключом в качестве хэша запроса и значением в качестве объекта. Затем я буду использовать a DefaultListModel для хранения идентификатор (напр. тип запроса) запроса и хэш-значения. DefaultListModel будет использоваться для заполнения JList, эффективно отображая запрос пользователю. Значение запросаselected (выбранного пользователем) затем может быть извлечено из ConcurrentHashMap с помощью хэша, сохраненного в DefaultListModel.
Пример кода:
ConcurrentHashMap<Integer, Object> requests = new ConcurrentHashMap<>();
DefaultListModel listData = new DefaultListModel();
JList theList = new JList();
...
public void addToList(Object request) {
//Place in HashMap
requests.put(request.hashCode(), request);
//Create a DataHolder with the Hashvalue and identifier of the request
DataHolder holder = new DataHolder(request.getID(), request.hash);
//Add the element to the ListModel
listData.addElement(holder);
//Assign the list model to the JList
theList.setModel(listData);
}
Когда пользователь выбирает элемент в списке:
DataHolder holder = (DataHolder)theList.getSelectedValue();
//Get request from HashMap
Object request = requests.get(holder.getHash());
//Do something with request
Решение 2:
Я заполняю новый объект, назовите его DataHolder, с идентификатором запроса и значением запроса. Теперь я могу заполнить JList с DefaultListModel, который содержит DataHolder, и никакая ссылка не требуется на любую другую структуру данных, чтобы получить фактическое значение запроса. Поскольку DefaultListModel используется для заполнения JList, я чувствую, что это может повлиять на производительность и может привести к тому, что список будет заполняться/не заполняться медленнее.
Пример кода:
DefaultListModel listData = new DefaultListModel();
JList theList = new JList();
...
public void addToList(Object request) {
//Removed HashMap
//Create a DataHolder with the Hashvalue and *actual value* of the request
DataHolder holder = new DataHolder(request.getID(), request);
//Add the element to the ListModel
listData.addElement(holder);
//Assign the list model to the JList
theList.setModel(listData);
}
Когда пользователь выбирает элемент в списке:
//No more HashMap
DataHolder holder = (DataHolder)theList.getSelectedValue();
Object request = holder.getData();
//Do something with request
Какое решение будет дать более быстрые результаты? Есть ли более эффективный способ сделать это? Любая помощь в этом вопросе будет очень признательна.
Еще немного информации:
- Запрос может подаваться в виде пакетов. (50+ за серию)
- запросы будут состоять из 20-50 строк XML
- запросы будут удалены из структуры данных случайным образом
Правка:
Последовательность, добавляющая сообщения в список, теперь обернута вinvokeLater. С моей реализацией, каждый раз, когда сообщение будет добавлено в список, будет создан новый поток, который выполнит всю работу и завершится, как только сообщение окажется в списке. Конечно, это влияет на ответ. Если 50 потоков создаются в плотной последовательности (с каждым вызовом addToList), какое решение будет выполняться быстрее?1 ответ:
Решение 3: Расширить
SwingWorker,class MessageWorker extends SwingWorker<List<DataHolder>, DataHolder> {}В вашей реализации
doInBackground(),publish()промежуточные результаты по мере их появления. При реализацииprocess(), обновление модели представления компонента. Удобно, чтоSwingWorkerбудет объединятьpublish()вызовы в устойчивом темпе. профиль ваше приложение для проверки. Другие примеры можно найти здесь.