我正在编写一个使用 TreeMap 的 Java 程序,一旦有成千上万的整数字符映射,性能就会减慢到爬行。
我想知道是否有某种类型的排序集实现的实现,它可以使用 int 和 char 原语并具有类似“headMap”和“tailMap”函数的东西。
我目前正在看 Trove。我还研究了一个使用插入排序但不包括头和尾函数的链表的实现。我认为带有插入排序的链表会比树慢,不是吗?
如果您正在寻找类似的替代品,TreeMap<Integer,Character>
并且如果您的整数键很密集,那么数组将是最有效的。但它会是 achar[]
而不是 anint[]
因为你想char
根据int
-key 来查找。然后我读了一些关于“基因组”的东西?!假设你想用char
Adenin、Gunin、Cytosin 和 Thymin 来表示(我不是这方面的专家)请记住,这char
需要你每个 16 位 - 远远超过你需要四个不同的东西。也许你可以做类似的事情
...
public static final byte UNDEF = (byte)-1;
public static final byte ADENIN = 0;
public static final byte GUANIN = 1;
public static final byte CYTOSIN = 2;
public static final byte THYMIN = 3;
...
private byte[] genome = new byte[ 26000000 ]; // or which size ever
...
如果这仍然会占用太多内存,那将变得很棘手:假设您不需要该UNDEF
值,您只需要 2 位来存储四个值,即一个可以存储您的序列,每个字节有四个值,最终需要大约 6.5 MB。但是对于这样的事情,你需要做一些摆弄......
如果我理解了这个问题,您需要一个保留键顺序的数据结构,即替换个人参考序列中的字符的位置。
我假设您通过增加仓位顺序来处理这些项目。
现在,由于 TreeMap 正在实现Red-Black Tree,它的基本操作具有对数复杂度。
如果您只需要按顺序迭代序列,那么每次插入都会严重影响性能。
如果我的假设是正确的,我会说您可以使用LinkedHashMap。
正如 javadoc 解释的那样:
此实现使其客户免于 HashMap(和 Hashtable)提供的未指定的、通常混乱的排序,而不会增加与 TreeMap 相关的成本。
这意味着您可以按照输入元素的相同顺序迭代元素,但基本操作与普通 HashMap 具有相同的复杂性,并且由于链表处理而导致性能下降。
你可以把它想象成一个 HashMap,它被一个按照插入顺序连接键的双链表遍历。
请注意,我没有解决您的序列是否适合记忆的事实。此外,请注意 LinkedHashMap 将比简单的 HashMap 占用更多内存。
正如史蒂夫所写,使用分析器检查 TreeMap 是罪魁祸首可能是值得的。
其他几个选项是:
使用HashMap
大initialCapacity
如果您的密钥集很密集,那么您可以使用int[]
. 那将是最快的。
你看过 PriorityQueue 了吗?它有一些有用的方法,并根据您定义的比较器对元素进行排序。
如果您知道这是您的性能瓶颈和/或内存问题 - 那么我会考虑使用 trove TIntCharHashMap
。过去,我使用 trove maps 非常成功地提高了性能并减少了内存消耗。
请注意,键不会被排序,但您可以int[]
非常便宜地获得键,然后您可以对其进行排序。因此,如果您只是偶尔需要排序遍历,您可以根据需要对其进行排序。
如果您发现丑陋(或性能障碍),您可以将TIntCharHashMap
and sorted包装int[]
到您自己的排序映射中 - 您只需要自己维护不变量。
我发现 trove 不直接基于树的顺序维护映射/设置类有点不幸,但我感谢它提供的工具。
值得尝试Max Bolingbroke的类似B-Tree的解决方案。
一种适用于非常大的排序映射的技术是结合使用 SortedSet 来按排序顺序管理键,并使用 Map 来管理实际的键到值的映射。通过这种方式,您可以使用 headSet() 和 tailSet() 对键进行快速迭代,然后使用从集合返回的键来查找实际映射。
我没有证据证明为什么会这样,但根据我的经验,使用非常大的排序地图要快 10 倍。