Java 是否有一种映射可以优化具有相同值的*键序列*?

Java 是否有一种映射可以优化具有相同值的*键序列*?,java,data-structures,map,Java,Data Structures,Map,如果您要将Java short映射到几个不可变对象,并且通常情况下短键(邻居)的连续序列映射到相同的值,那么是否有某种映射结构允许您在保持快速访问速度(O(1)或O(log(N))的同时比哈希映射节省更多内存 我可以反转映射,我将使用更少的内存,但是我必须遍历每个映射,以了解是否映射了特定的short,以及映射到什么(O(N)) 我想某种树形图可以做到这一点;也许在某些集合库中有类似的东西?我曾经使用一个自定义键类和相应的比较器来实现这一点。我的密钥类包含一系列双值的两端。查询被指定为一个两端相

如果您要将Java short映射到几个不可变对象,并且通常情况下短键(邻居)的连续序列映射到相同的值,那么是否有某种映射结构允许您在保持快速访问速度(O(1)或O(log(N))的同时比哈希映射节省更多内存

我可以反转映射,我将使用更少的内存,但是我必须遍历每个映射,以了解是否映射了特定的short,以及映射到什么(O(N))

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

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

尽管如此,仍有一些选择需要做出:

  • 应该如何处理
    remove()

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

  • 将这种行为捆绑在一个新的Map实现中(可能是TreeMap的子类)有意义吗


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


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

看看。

此解决方案非常不同-非常老式,但接近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;
最后,对其他所有内容使用有效的简短对象映射:

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

// just a sketch
public class Value
{
    short shortValue;
    String optional;
}
//用于存储大于255的值
Short2ObjectOpenHashMap objectMap=新的Short2ObjectOpenHashMap();
//只是一张草图
公共阶级价值
{
短值;
字符串可选;
}

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

您能更好地了解有多少键和值吗?这组值是固定的吗?我将使用short作为键,“short加可选数据”作为值。值0-255没有任何“可选数据”,可以“合并”。所有的键都需要映射,但由于估计有50%的键会映射到“0”,所以我打算将这些键忽略,并默认为“0”。虽然有65K个可能的值,其中一些有“可选数据”,但我预计90%的值至少在1到10之间,没有“可选数据”,这些值可以合并。相同值序列的平均长度约为10。仔细看,这似乎太“一般”。他们说:“有效地检索与另一个区间或点重叠的所有区间”,我将只按“点”进行查询,并且只有一个区间匹配。但也许我误解了细节。@Sebastien,这并不意味着你不能使用它们。虽然我可以看到查询树的工作原理,但我认为put和remove在实现上会有问题。换句话说,我怀疑扩展TreeMap,而不是基于AbstractMap编写自己的实现,并不会带来太多好处。这正符合我的问题。为了减少内存使用,我可以将其实现为两个数组。一个用于排序键,一个用于值。因为arraycopy,当我改变地图时,我得到了O(n),但这应该很少发生。实际上,这是我首先想到的。简单明了,但我认为间隔/范围树将为我节省更多的内存。最后,我只需要创建几个实现,包括这一个,并运行一个基准来做出选择!
// Use to store values larger than 255 
Short2ObjectOpenHashMap<Value> objectMap = new Short2ObjectOpenHashMap();

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