使用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
相关产品推荐
相关产品推荐

