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

动态key排序查询应选什么数据结构?图书存量变动时如何实现动态排序?

解决方案

核心选型说明

你需要的是支持自动排序、可处理重复quantity值、变更后可自动重排的映射结构,Java原生容器中TreeMap是最匹配的实现,只需要额外解决两个问题:1、quantity重复导致的key冲突;2、quantity变更后触发重排的逻辑。

步骤1:定义可排序的组合Key解决重复值问题

因为不同图书的quantity可能重复,无法直接作为TreeMap的Key(重复Key会触发值覆盖),我们将唯一的图书id和quantity组合为自定义Key,排序规则优先按quantity排序,quantity相同时按id排序,保证Key全局唯一:

// JDK16及以上版本可直接用record,低版本替换为普通类重写equals、hashCode、compareTo方法即可
public record BookSortKey(Long quantity, Long bookId) implements Comparable<BookSortKey> {
    @Override
    public int compareTo(BookSortKey other) {
        // 此处按quantity倒序排序,如需正序将Long.compare的两个参数互换即可
        int quantityCompareRes = Long.compare(other.quantity, this.quantity);
        if (quantityCompareRes != 0) {
            return quantityCompareRes;
        }
        // quantity相同时按id排序,确保Key不会重复
        return Long.compare(this.bookId, other.bookId);
    }
}

步骤2:封装更新逻辑实现自动重排

TreeMap本身不会监听Key的属性变化,因此我们封装容器操作,在quantity更新时自动执行「删除旧Entry-插入新Entry」逻辑,上层调用无需感知排序细节:
首先给原Book类补充getter、setter方法:

public class Book {
    private Long id;
    private Long quantity;

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public Long getQuantity() { return quantity; }
    public void setQuantity(Long quantity) { this.quantity = quantity; }
}

封装排序容器:

import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;

public class SortedBookManager {
    // 底层用TreeMap存储,插入时自动按Key规则排序
    private final TreeMap<BookSortKey, Book> sortedBookMap = new TreeMap<>();

    // 新增图书
    public void addBook(Book book) {
        sortedBookMap.put(new BookSortKey(book.getQuantity(), book.getId()), book);
    }

    // 更新图书库存,自动触发重排
    public void updateQuantity(Long bookId, Long newQuantity) {
        // 查找目标图书
        Book target = sortedBookMap.values().stream()
                .filter(book -> book.getId().equals(bookId))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("不存在ID为" + bookId + "的图书"));
        // 先删除旧的Entry
        sortedBookMap.remove(new BookSortKey(target.getQuantity(), bookId));
        // 更新库存
        target.setQuantity(newQuantity);
        // 插入新Entry,TreeMap会自动将其放到正确的排序位置
        sortedBookMap.put(new BookSortKey(newQuantity, bookId), target);
    }

    // 获取已排序的图书列表,直接按顺序遍历即可
    public List<Book> getSortedBooks() {
        return new ArrayList<>(sortedBookMap.values());
    }
}

注意事项

  • 不要直接修改Book实例的quantity字段,必须通过updateQuantity方法执行更新,否则会出现排序错乱
  • 单次更新的时间复杂度为O(logn),高频更新场景下性能远高于每次全量排序List的方案
  • 多线程并发场景下,可将TreeMap替换为线程安全的ConcurrentSkipListMap,或者给更新方法加锁保证线程安全

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 21:36:00