首页 > 解决方案 > 使用缓存对对象的 ArrayList 进行排序

问题描述

任何关于以下问题的建议将不胜感激。

现状:我有一个对象的ArrayList。我们已经使用比较器实现了排序。该对象有数百个字段。所以 ArrayList 中单个对象的大小并不小。展望未来,当 ArrayList 的大小增加时,由于 ArrayList 的整体大小,我们觉得这会在排序中产生问题。

计划:我们将在缓存中加载对象。我们计划不将对象的 ArrayList 作为输入,而是将 id(字符串)的 ArrayList 作为输入。当比较一个 id 时,我们计划从缓存中获取对象。

问题:我不想加载缓存中的所有对象,因为此缓存仅在排序期间使用。所以我不想为此创建一个巨大的缓存。

我打算做的是仅加载缓存中的一半对象,如果缓存中不存在任何内容,则从数据库加载它并读取它并将其放入缓存中(这将替换缓存中的一个对象)。我不想在数据库中查询单个对象,因为这样我会数万次访问数据库。

我想从数据库中批量读取,但我无法制定策略。

任何建议将不胜感激。

标签: javacachingarraylist

解决方案


你很困惑。

该对象有数百个字段。

无关紧要。Java 使用引用;您拥有的“对象数组列表”由一个数组支持,并且该数组中的每个插槽大约需要 8 个字节(取决于底层 VM 详细信息,也可能是 4 个字节)。这些或多或少代表了对象所在的内存位置。

当 ArrayList 的大小增加时继续前进

....不,它不会。如果您在此列表中放入 100,000 个条目,那么至少对于列表本身而言,这是一个总内存负载,最多为 800,000 字节,这还不到 1 兆字节。这么说吧:在现代硬件上,仅该列表就可以包含 1 亿个项目,您的系统不会出汗(用于引用的内存少于 GB)。现在,如果您也有 1 亿个唯一对象(例如,添加完全相同的对象 1 亿次,或者添加 null 1 亿次),那么该对象也会占用内存。那可能是个问题。但该列表不是相关部分。

由于 ArrayList 的整体大小,我们觉得这会在排序中产生问题。

不。当你对一个数组列表进行排序时,你会得到 ~nlogn 操作来对它进行排序。实际的排序基础设施部分(在列表中移动对象)足够接近零成本(它只是在单个内存页面上将那些 4 到 8 个字节序列传输。假设 .compare() 的调用很便宜,甚至是一次性的100 美元的计算机可以在几分之一秒内对数百万个条目进行排序。这只会留下 .compare() 的 ~nlogn 调用。如果这很昂贵,好吧,你可能有问题。所以,在 100 万个条目的列表中,你是查看您的 compare 方法的大约 1300 万次调用。

它有多快?

如果调用 .compare(a, b) (其中 a 和 b 是指向“数百个字段”对象实例的指针)检查这数百个字段中的每一个,这可能会有点棘手,但如果它只是检查其中一些,这里没有什么可担心的。CPU速度很快。你可能会说:“百万?我的天哪!”,但你的 CPU 会嘲笑这项工作。

我们将在缓存中加载对象。

由于以上原因,这个计划很糟糕。

我想从数据库中批量读取

好的,所以当您开始使用“我们有一个对象数组列表”时,实际上您没有那个,并且您有一个数据库连接?哪一个?

要么将所有数据保存在数组列表中,要么将数据保存在数据库中。如果它都在一个数组列表中,那么数据库部分是无关紧要的。如果您没有将所有数据都放在数组列表中,那么您的问题会误导并且不清楚。

如果数据在数据库中,请设置适当的索引并使用 ORDER BY 子句。


推荐阅读