You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何每秒获取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 08:45:18