我看过通常的地方(apache commons,google)而找不到...
它应该是开源的。
几乎在寻找基于链表的一个。用例是10'000的地图,不一定有很多值。它不需要按比例放大,因为我可以在它变得太大时进行转换。
使用一些计算的jvm值(8bytes / java.lang.Object,4bytes / ref)的一些数字,大小HashMap大约是100 + 32n字节,理论上最好是12 + 20 * n。 < - 我想要那个,小n。
答案 0 :(得分:3)
可以查看commons-collections Flat3Map,它已经过优化,可以在3个字段中存储3个值,并在4个字段中溢出到另一个地图。
我没有看过实施,但可能值得考虑。唯一的问题是,因为commons-collections与1.3兼容,所以没有通用的。
答案 1 :(得分:3)
使用Map接口包装ArrayList。 ArrayList本身只使用几个字节。每个节点都需要两个指针,一个用于键,一个用于值。使用顺序搜索查找值。只要只有很少的条目,性能就可以了[*]。这将为您提供使用真实地图的余地,为您拥有大量价值的几个花瓶。
*:假设您的平均地图大小为10.今天的计算机每秒可以比较大约1亿个密钥,因此平均每次查找的时间不会超过5微秒。
如果性能对于您的用例仍然太糟糕,您可以尝试按键对数组进行排序并使用二进制搜索。
答案 2 :(得分:3)
好的,最后自己实现了。我进行了速度比较,发现与HashMap相比,4个条目的速度稍快,但5个或更多的速度更慢。我用一长串的键进行了测试,我尝试给出类似的化妆作为随机英语单词列表。
import java.util.*;
// PUBLIC DOMAIN
public class SmallMap extends AbstractMap {
private Entry entry = null;
public void clear() { entry = null; }
public boolean isEmpty() { return entry==null; }
public int size() {
int r = 0;
for(Entry e = entry; e!=null; e = e.next) r++;
return r;
}
public boolean containsKey(Object key) {
for(Entry e = entry; e!=null; e = e.next){
if(e.key.equals(key)){
return true;
}
}
return false;
}
public boolean containsValue(Object value) {
for(Entry e = entry; e!=null; e = e.next){
if(e.value==null){
if(value==null) return true;
}else if(e.value.equals(value)){
return true;
}
}
return false;
}
public Object get(Object key) {
for(Entry e = entry; e!=null; e = e.next){
if(e.key.equals(key)){
return e.value;
}
}
return null;
}
public Object put(Object key, Object value) {
for(Entry e = entry; e!=null; e = e.next){
if(e.key.equals(key)){
Object r = e.value;
e.value = value;
return r;
}
}
entry = new Entry(key, value, entry);
return null;
}
public Object remove(Object key) {
if(entry!=null){
if(entry.key.equals(key)){
Object r = entry.value;
entry = entry.next;
return r;
}
for(Entry e = entry; e.next!=null; e = e.next){
if(key.equals(e.next.key)){
Object r = e.next.value;
e.next = e.next.next;
return r;
}
}
}
return null;
}
public Set entrySet() { return new EntrySet(); }
class EntrySet extends AbstractSet{
public Iterator iterator() {
return new Iterator(){
Entry last = null;
Entry e = entry;
public boolean hasNext() { return e!=null; }
public Object next() {
last = e;
e = e.next;
return last;
}
public void remove() {
if(last == null) throw new IllegalStateException();
SmallMap.this.remove(last.key);
}
};
}
public int size() { return SmallMap.this.size();}
}
static private class Entry implements java.util.Map.Entry {
final Object key;
Object value;
Entry next;
Entry(Object key, Object value, Entry next){
if(key==null) throw new NullPointerException();
this.key = key;
this.value = value;
this.next = next;
}
public Object getKey() { return key; }
public Object getValue() { return value; }
public Object setValue(Object value) {
Object r = this.value;
this.value = value;
return r;
}
public int hashCode() {
return (key == null ? 0 : key.hashCode()) ^
(value == null ? 0 : value.hashCode());
}
}
}
答案 3 :(得分:1)
简单地说,我建议根据同步或并发要求使用JDK的HashMap,Hashtable和ConcurrentHashMap之一。 如果您决定使用它们,在构造函数中适当地设置initialCapacity和loadFactor可能会有所帮助。
Google集合和apache commons集合提供了更多功能:LRUMap,ReferenceMap,MultikeyMap等。但我认为不会有那么小的尺寸。
答案 4 :(得分:1)
LinkedHashMap
使用链表,但我怀疑它是否针对低内存使用进行了优化。通常,地图的整个点是加快从键到值的查找速度,这就解释了为什么你在常见的地方找不到你需要的东西。编写自己的Map
实现可能最简单,也许你甚至可以发布代码以防其他人需要相同的东西。
答案 5 :(得分:1)
以隐藏地图使用的方式编写代码(无论如何你应该这样做,听起来你也是这样)。在重要的时候,因为你已经分析了代码,并且可以看到内存确实是一个问题,找一个: - )
如果您现在知道存在问题,那么,抱歉我不知道。然而,人们经常处理代码将会很慢/大量内存/等等的“想法”......并开始尝试预先优化它而不是使代码正确。
那就是说,如果你正在写一些你知道重要的东西,你应该随时测量。例如,我正在处理解析类文件的代码,我进行了一些小改动,然后看看它如何影响性能。例如,我知道一个事实,即我所做的改变(3行)使我的程序变慢了4倍......我花了一些时间来找不到更快的方法。
另外,如果“n”的值很小,你确定需要地图吗?也许列表足够快?您是否尝试调整现有Map以使其使用更少的内存?
答案 6 :(得分:0)
这很大程度上取决于你将如何使用这些地图,你可以一次性填充它们然后只进行查找(你需要那些查找快速)吗?
使用最少量内存的实现是将所有元素放在一个数组中并进行扫描以查找元素(但我想这不是 fast 足以满足您的需求)..
如果你知道开头的所有元素,你可以尝试选择一个好的哈希方法而不会有太多的冲突。
如果允许缓慢插入时间,也许你可以使用TreeMap ......
答案 7 :(得分:0)
也许这个答案有点晚,但看看Javolution项目。它包含许多数据结构的实现,用于嵌入式和实时环境。具体来说,有一个FastMap类可能就是你想要的。
答案 8 :(得分:0)
如果仅存储String
,请查看http://code.google.com/p/flatmap
编辑哦对不起,我看到你正在寻找小而不大的地图,忘了我的建议。
答案 9 :(得分:0)
我知道这是一个老问题,但也许有人可以添加更多想法。
注意:以下内容仅对特定的用例子集有意义:
如果要求包含高度重叠的组密钥(在极端情况下是所有映射的同一组密钥),那么非常有效的解决方案可能是“外部化” “关于地图的关键并且地图只包含数组中的值。
实现不应该在结构上依赖于重叠因子,但是当密钥重叠越多时,我的表现越好。正如你所料。
我无法详细说明我的实现,但重要的是要有一个合适的机制将键(存储在地图对象之外)转换为values数组中的索引,同时还允许values数组保持紧凑,即如果你的地图包含五个映射,则长度为五。
假设所有此类地图的键位于单独的地图中,映射到数字。然后是一个关联数字和数组索引的方法。
很抱歉,如果这不够具体,但我认为这个想法同时又有趣又简单,可以作为开发内存效率Map的替代方向。
同样,它本身适用于高“密钥重叠”用例,但它本身就是通用的。如果重叠太低,可能会遇到性能问题,具体取决于实现细节。