针对少量条目的Java Map的最快实现

针对少量条目的Java Map的最快实现,java,performance,collections,map,Java,Performance,Collections,Map,对于15个元素左右的极少量条目,最快的实现是什么?线程安全和非线程安全 HashMap=新的HashMap 将为您提供一个非常简单的映射,其中键类型为字符串,值类型为对象 编辑:这是一个非线程安全版本 您可以签出线程安全映射。如果所有条目都可以表示为枚举,请使用: 此实现结合了地图的丰富性和安全性 接口的速度接近阵列的速度。如果你想 将枚举映射到值时,应始终优先使用枚举映射 到一个数组 如果没有,这是一个很好的解决方案。它为基本操作(如get和put)提供恒定的时间: 此实现为基本的 操作get

对于15个元素左右的极少量条目,最快的实现是什么?线程安全和非线程安全

HashMap=新的HashMap

将为您提供一个非常简单的映射,其中键类型为字符串,值类型为对象

编辑:这是一个非线程安全版本


您可以签出线程安全映射。

如果所有条目都可以表示为枚举,请使用:

此实现结合了地图的丰富性和安全性 接口的速度接近阵列的速度。如果你想 将枚举映射到值时,应始终优先使用枚举映射 到一个数组

如果没有,这是一个很好的解决方案。它为基本操作(如get和put)提供恒定的时间:

此实现为基本的 操作get和put,假设散列函数将 在桶之间正确地放置元素

只需记住在HashMap中设置低容量值:

因此,不要将初始容量设置得过高或过低,这一点非常重要 如果迭代性能很重要,则负载系数太低

当然,上述实现不是线程安全的。在这种情况下,最好的线程安全实现是。它结合了HashMap的高性能和线程安全性

很好地比较了不同的Map实现

编辑:不同HashMap实现的有趣比较。看起来,至少对于基本类型,有比内置HashMap更快的替代方法

编辑2:由于Peter Lawrey的回答,我决定执行一些测试,比较ConcurrentHashMap和Collections.synchronizedMap:

我的结果是:

======ConcurrentHashMap=====

5000000普茨基,价值-0.99714195 s

5000000 getkey-0.452227427 s

====Collections.synchronizedMap=====

5000000普茨基,价值-0.586431367 s

5000000 getkey-0.376051088 s


因此,Peter可能是对的-对于小地图,Collections.synchronizedMap更快

如果您想要一张紧凑的地图,可以使用

Map Map=Collections.synchronizedMapnew HashMap

如果不需要线程安全,请删除Collections.synchronizedMap。如果希望集合使用尽可能少的内存,可以执行类似操作

Map Map=newhashmap4,1.0f

这将使用最小内存存储4个键/值或更多。它大约是一个空的标准HashMap的一半大小

使用ConcurrentHashMap的问题是,对于一个小集合来说,它的重量很重,即它使用许多对象,如果为空,则会占用大约1KB的内存

要获得准确的内存使用率,您需要在命令行上使用-XX UseTLAB

public static void main(String sdf[]) throws Exception {
    testCreateSize("ConcurrentHashMap", ConcurrentHashMap::new);
    testCreateSize("HashMap", HashMap::new);
    testCreateSize("synchronized HashMap", () -> {
        return Collections.synchronizedMap(new HashMap<>());
    });
    testCreateSize("small synchronized HashMap", () -> {
        return Collections.synchronizedMap(new HashMap<>(4, 2.f));
    });

}

public static void testCreateSize(String description, Supplier<Map<Integer, Integer>> supplier) {
    // warmup.
    supplier.get();
    long start = memoryUsed();
    Map<Integer, Integer> map = supplier.get();
    for (int i = 0; i < 4; i++) {
        map.put(i, i);
    }
    long used = memoryUsed() - start;
    System.out.printf("Memory used for %s, was %,d bytes%n", description, used);

}

public static long memoryUsed() {
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}

通过在使用映射的类中使用同步方法,可以再节省32个字节。

使用ConcurrentHashMap实现线程安全。映射到什么?i、 e.它是一个映射、一个映射等吗?+1唯一的问题是ConcurrentHashMap对于小映射有很高的开销。哈希映射。。。提供固定时间…-对于少量条目,与循环中的简单相等性测试相比,它可能会花费更多的时间来计算哈希。这就是问题所在。2.线程安全集合的单线程测试毫无意义。也可以查看Google Caliper的microbeanchmarks。但是ConcurrentHashMap比Collections更有效。synchronizedMap…@Kao对于大型集合,是的,对于许多小型集合,CHM是非常糟糕的。@Kao不是非常糟糕,但效率较低。这不是一个公平的实验。ConcurrentHashMap没有使用int-initialCapacity、float-loadFactor或ConcurrentyLevel。@true。您可以对HashMap执行同样的操作。
public static void main(String sdf[]) throws Exception {
    testCreateSize("ConcurrentHashMap", ConcurrentHashMap::new);
    testCreateSize("HashMap", HashMap::new);
    testCreateSize("synchronized HashMap", () -> {
        return Collections.synchronizedMap(new HashMap<>());
    });
    testCreateSize("small synchronized HashMap", () -> {
        return Collections.synchronizedMap(new HashMap<>(4, 2.f));
    });

}

public static void testCreateSize(String description, Supplier<Map<Integer, Integer>> supplier) {
    // warmup.
    supplier.get();
    long start = memoryUsed();
    Map<Integer, Integer> map = supplier.get();
    for (int i = 0; i < 4; i++) {
        map.put(i, i);
    }
    long used = memoryUsed() - start;
    System.out.printf("Memory used for %s, was %,d bytes%n", description, used);

}

public static long memoryUsed() {
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
Memory used for ConcurrentHashMap, was 272 bytes
Memory used for HashMap, was 256 bytes
Memory used for synchronized HashMap, was 288 bytes
Memory used for small synchronized HashMap, was 240 bytes