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

使用SortedDictionary填充分组RecyclerView,分组下ViewHolder不显示

嘿,我完全懂你的想法——多余的循环和自定义ListItem类确实是没必要的冗余,不仅增加代码复杂度,还会在数据量较大时拖慢性能。咱们直接来优化这个方案,彻底绕开那些不必要的步骤:

核心思路:直接用有序Map存储分组,跳过中间转换

与其先把事件分组到HashMap,再循环转成一维ArrayList<ListItem>,不如直接用有序的Map结构来保存按DateTime分组的事件集合,后续直接基于这个Map处理UI展示或其他逻辑,完全省去转换环节和自定义类。

1. 高效分组到TreeMap(自带时间排序)

用TreeMap<LocalDateTime, List<Event>>来做分组容器,它会自动按LocalDateTime的自然顺序排序,省掉额外的排序逻辑,而且分组代码非常简洁:

// 假设你的Event类有getDateTime()方法返回LocalDateTime
TreeMap<LocalDateTime, List<Event>> groupedEvents = new TreeMap<>();

for (Event event : allEvents) {
    LocalDateTime eventTime = event.getDateTime();
    // 按原始时间分组,你也可以根据需求截断时间(比如按天分组:eventTime.truncatedTo(ChronoUnit.DAYS))
    groupedEvents.computeIfAbsent(eventTime, key -> new ArrayList<>()).add(event);
}

这里computeIfAbsent一行就完成了“不存在则创建列表,存在则添加事件”的逻辑,比传统的判断+添加写法更简洁高效。

2. 直接基于Map处理UI展示(以RecyclerView为例)

如果是在Android这类需要列表展示分组的场景,不需要自定义ListItem来区分标题和事件,直接在Adapter里处理TreeMap的entrySet即可:

先定义视图类型

private static final int VIEW_TYPE_HEADER = 0;
private static final int VIEW_TYPE_EVENT = 1;

计算总条目数(标题数 + 所有事件数)

@Override
public int getItemCount() {
    int totalCount = 0;
    for (Map.Entry<LocalDateTime, List<Event>> entry : groupedEvents.entrySet()) {
        totalCount += 1 + entry.getValue().size(); // 1个标题 + 该组的事件数量
    }
    return totalCount;
}

区分当前位置的视图类型

@Override
public int getItemViewType(int position) {
    int currentPos = 0;
    for (Map.Entry<LocalDateTime, List<Event>> entry : groupedEvents.entrySet()) {
        // 当前位置是分组标题
        if (currentPos == position) {
            return VIEW_TYPE_HEADER;
        }
        currentPos++;
        // 遍历该组的事件,匹配当前位置
        for (int i = 0; i < entry.getValue().size(); i++) {
            if (currentPos == position) {
                return VIEW_TYPE_EVENT;
            }
            currentPos++;
        }
    }
    return -1;
}

绑定对应视图

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    int currentPos = 0;
    for (Map.Entry<LocalDateTime, List<Event>> entry : groupedEvents.entrySet()) {
        // 绑定分组标题
        if (currentPos == position) {
            HeaderViewHolder headerHolder = (HeaderViewHolder) holder;
            headerHolder.dateTextView.setText(
                entry.getKey().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
            );
            return;
        }
        currentPos++;
        // 绑定事件项
        for (Event event : entry.getValue()) {
            if (currentPos == position) {
                EventViewHolder eventHolder = (EventViewHolder) holder;
                eventHolder.eventTitle.setText(event.getTitle());
                eventHolder.eventDesc.setText(event.getDescription());
                return;
            }
            currentPos++;
        }
    }
}

方案优势

  • 去掉冗余环节:彻底删除了转一维列表的循环和自定义ListItem类,减少对象创建和内存开销
  • 性能提升:少了一次全量遍历转换的过程,数据量越大,性能优势越明显
  • 逻辑更清晰:直接基于原始分组数据操作,代码可读性更高,维护成本更低

内容的提问来源于stack exchange,提问作者Fariz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:39:13