如何每秒获取HashMap中的前50条数据?原代码失效求助
问题分析与解决方案
现有代码的核心问题
你的代码完全没实现“保留前50条数据”的需求,主要问题包括:
- 仅当Map大小刚好等于50时才清空,而实际Map大小经常是300+,根本触发不到逻辑,更达不到保留前50的目的
- 没有实现裁剪数据的逻辑,反而直接清空整个Map
- 使用的
TreeMap非线程安全,数据更新线程和定时任务线程并发操作时容易抛出ConcurrentModificationException - 不必要地在UI线程执行集合操作,浪费UI线程资源
修正后的实现
1. 线程安全的有序Map选型
因为你的数据按日期键排序,且需要多线程安全操作,推荐使用ConcurrentSkipListMap:
- 天然支持有序遍历(默认按键升序,可指定逆序)
- 线程安全,避免并发修改异常
如果需要保留最新的50条数据,创建Map时指定逆序比较器,让最新的日期键排在最前面:
// 按日期键逆序排序,最新的数据首位排列 Map<String, Object> rightDataDict = new ConcurrentSkipListMap<>(Collections.reverseOrder());
如果需要保留最早的50条数据,直接使用默认升序即可:
Map<String, Object> rightDataDict = new ConcurrentSkipListMap<>();
2. 定时裁剪数据的逻辑
修改TimerTask逻辑,在后台线程处理集合裁剪,仅需更新UI时再切换到UI线程:
right_timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { int currentSize = rightDataDict.size(); if (currentSize > 50) { // 收集需要保留的前50条数据的键 List<String> keepKeys = new ArrayList<>(50); int count = 0; for (String key : rightDataDict.keySet()) { keepKeys.add(key); if (++count >= 50) { break; } } // 删除不在保留列表中的键 rightDataDict.keySet().removeIf(key -> !keepKeys.contains(key)); } // 若需更新UI,再切换到UI线程执行 runOnUiThread(() -> { // 这里写UI更新逻辑,比如打印当前Map大小: // Log.d("ContentValues", "rightdatadict size(): " + rightDataDict.size()); }); } }, 1000, 1000);
3. 数据插入的注意事项
在其他线程插入数据时,直接调用rightDataDict.put()即可,ConcurrentSkipListMap会自动处理线程安全,无需额外加锁。
内容的提问来源于stack exchange,提问作者stack offer
相关产品推荐
相关产品推荐

