【问题标题】:Is there a kind of map that optimize for *sequences of keys* that have the same value?是否有一种映射可以优化具有相同值的*键序列*?
【发布时间】:2023-03-17 12:39:01
【问题描述】:

如果您将 Java 短键映射到一些不可变对象,并且通常情况下,连续的短键序列(邻居)映射到相同的值,那么有一些映射结构可以让您节省更多内存一个hashmap,同时保持快速的访问速度(O(1)或O(log(N)))?

我可以反转映射,并且我会使用更少的内存,但是我必须通过每个映射来了解是否映射了特定的短,以及映射到什么 (O(N))。

我想某种树形图可以做到这一点;也许某些收藏库中有类似的东西?

【问题讨论】:

  • 你能更好地了解有多少键和值吗?这组值是固定的吗?
  • 我将短作为键,并将“短加可选数据”作为值。值 0-255 没有任何“可选数据”,可以“合并”。 所有键都需要映射,但由于估计有 50% 将映射到“0”,我打算简单地将它们排除在外并默认为“0”。虽然会有 65K 可能的值,其中一些具有“可选数据”,但我预计至少 90% 将在 1 到 10 之间,没有“可选数据”,并且可以合并这些值。相同值序列的平均长度约为 10。

标签: java data-structures map


【解决方案1】:

看看interval trees

【讨论】:

  • 细看,这似乎太“笼统”了。他们说:“有效地检索与另一个间隔或点重叠的所有间隔”我将仅按“点”查询,并且只能有一个 single 间隔匹配。但也许我误解了细节。
  • @Sebastien,这并不意味着你不能使用它们。
【解决方案2】:

我曾经使用带有自定义键类和相应比较器的TreeMap 来实现这一点。我的键类包含double 值范围的两端。查询被指定为两端相同的范围,其余部分由比较器完成。

不过有几个选择:

  • remove()应该如何处理?

  • 如果发出 get() 的键范围与两个或多个范围重叠,会发生什么情况?

  • 将这种行为捆绑在新的 Map 实现中是否有意义 - 可能是 TreeMap 的子类?

【讨论】:

  • 虽然我可以看到这对于查询树是如何工作的,但我认为 put 和 remove 实施起来会有问题。换句话说,我怀疑您通过扩展 TreeMap 并没有获得太多收益,而不是基于 AbstractMap 编写自己的实现。
【解决方案3】:

您可以使用一棵二叉树,其中每个映射到相同值的短路间隔都有一个条目。 关键是区间的开始,而数据是区间的长度加上映射的对象。

因此要查找给定的short是否被映射,您需要在树中定位节点,其中最高的键小于给定的键(O(logn)),并检查给定的键是否落在该节点表示的区间内。

【讨论】:

  • 这完全符合我的问题。为了最少的内存使用,我可以将它实现为两个数组。一个用于排序的键,一个用于值。然后我在更改地图时得到 O(n),因为 arraycopy,但这应该很少发生。
【解决方案4】:

这个解决方案非常不同 - 非常老式,但接近 O(1),小而快。 90% 的值将适合 4 位,而映射或树条目需要数百位来表示(无需大量自定义重新实现)。因此,首先在一个 4 位条目数组中表示它们:

// Used to store nybbles containing small values, with direct arithmetic mapping.
// A value of 15 indicates that the value is larger than 14.
// Size: 32KB
byte[] zeroTo14Array = new byte[(1<<Short.SIZE)/2];
static final short BIGGER_THAN_NYBBLE = 15;

然后使用高效的短字节映射(从fastutilgnu trove 表示从15 到255 的值:

// Use to store bytes with values 15-255.
// If value is 0, value is larger than 255.
Short2ByteOpenHashMap byteMap = new Short2ByteOpenHashMap();

最后,对其他所有内容使用高效的short-to-object映射:

// Use to store values larger than 255 
Short2ObjectOpenHashMap<Value> objectMap = new Short2ObjectOpenHashMap();

// just a sketch
public class Value
{
    short shortValue;
    String optional;
}

如果您愿意,我可以发布其余的未测试代码。

【讨论】:

  • 其实我最先想到的就是这个。简单直接,但我认为区间/范围树将为我节省更多内存。最后,我只需要创建几个实现,包括这个,然后运行一个基准来做出我的选择。
  • 得到结果后回信!
猜你喜欢
  • 1970-01-01
  • 2013-10-10
  • 1970-01-01
  • 2018-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多