简体   繁体   English

在 DefaultListModel 与 ConcurrentHashMap 中存储数据

[英]Storing Data in DefaultListModel vs ConcurrentHashMap

I am writing a GUI in swing to display incomming requests from clients.我正在用 Swing 编写一个 GUI 来显示来自客户端的传入请求。 The server populates a LinkedBlockingQueue , while another thread takes from the queue when there is data available.服务器填充LinkedBlockingQueue ,而另一个线程在有数据可用时从队列中取出。 The requests are stored as an Object .请求存储为Object Like so:像这样:

while(should_take) {
    //getRequest() is blocking
    Object request = server.getRequest();

    //Add request to user interface
    GUI.addToList(request);
}

Now my question comes in, would it be better to:现在我的问题来了,最好是:

Solution 1:解决方案1:

Store the request in a ConcurrentHashMap<Integer, Object> with the key as the hash of the request and the value as the Object.request存储在ConcurrentHashMap<Integer, Object> ,键作为请求的哈希值,值作为对象。 I will then use a DefaultListModel to store the identifier (eg. request type) of the request and the hash value.然后我将使用DefaultListModel来存储请求的标识符(例如请求类型)和哈希值。 The DefaultListModel will be used to populate a JList , effectively displaying the request to the user. DefaultListModel将用于填充JList ,有效地向用户显示请求。 The value of the selected request (selected by the user) can then be retrieved from the ConcurrentHashMap using the hash saved in the DefaultListModel .然后可以使用保存在DefaultListModel的哈希从 ConcurrentHashMap 中检索所选请求(由用户选择)的值。

Some example code:一些示例代码:

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);
}

When a user selects an item in the list:当用户选择列表中的项目时:

DataHolder holder = (DataHolder)theList.getSelectedValue();
//Get request from HashMap

Object request = requests.get(holder.getHash());
//Do something with request

Solution 2:解决方案2:

I populate a new Object, call it DataHolder , with the request identifier and request value.我使用请求标识符和请求值填充一个新对象,称为DataHolder I can now populate the JList with DefaultListModel that contains DataHolder and no reference is needed to any other data structure to retrieve the actual request value.我现在可以使用包含DataHolder DefaultListModel填充JList ,并且不需要引用任何其他数据结构来检索实际请求值。 Because DefaultListModel is used to populate the JList , I feel it can impact performance and may cause the list to populate/unpopulate slower.因为DefaultListModel用于填充JList ,我觉得它会影响性能并可能导致列表填充/取消填充变慢。

Some example code:一些示例代码:

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);
}

When a user selects an item in the list:当用户选择列表中的项目时:

//No more HashMap
DataHolder holder = (DataHolder)theList.getSelectedValue();

Object request = holder.getData();
//Do something with request

Which solution will yield quicker results?哪种解决方案会产生更快的结果? Is there a more efficient way to do this?有没有更有效的方法来做到这一点? Any help on the matter will be greatly appreciated.对此事的任何帮助将不胜感激。

Some more info:更多信息:

  • Request may be delivered in bursts.请求可以突发传送。 (50+ per burst) (每次爆发 50+)
  • Requests will consist of between 20 and 50 lines of XML请求将由 20 到 50 行 XML 组成
  • Requests will be removed from the data structure randomly请求将从数据结构中随机删除

EDIT:编辑:

The sequence that adds messages to the list has now been wrapped in invokeLater .将消息添加到列表的序列现在已包含在invokeLater With my implementation, every time a message will be added to the list, a new thread will be created to do all the work, and end once the message is in the list.在我的实现中,每次将消息添加到列表中时,都会创建一个新线程来完成所有工作,并在消息进入列表后结束。 Surely this effects the answer.这肯定会影响答案。 If 50 threads are created in tight succession (with each call to addToList), which solution will execute quicker?如果连续创建 50 个线程(每次调用 addToList),哪个解决方案执行得更快?

Solution 3: Extend SwingWorker ,解决方案 3:扩展SwingWorker

class MessageWorker extends SwingWorker<List<DataHolder>, DataHolder> {}

In your implementation of doInBackground() , publish() intermediate results as they become available.doInBackground()实现中, publish()中间结果可用。 In your implementation of process() , update the view component's model.process()实现中,更新视图组件的模型。 Conveniently, SwingWorker will coalesce publish() invocations at a sustainable pace .方便的是, SwingWorker将以可持续的速度合并publish()调用。 Profile your application to verify.配置您的应用程序以进行验证。 More examples may be found here .可以在此处找到更多示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM