我们可以使用Java在映射中一次放置多个键和值吗

我们可以使用Java在映射中一次放置多个键和值吗,java,hashmap,guava,Java,Hashmap,Guava,这就是我要做的。我有一个要转换为map的对象列表,其中key作为对象id,value作为对象。列表中有数千个对象,这会导致性能问题。有没有简单的方法不用循环或使用其他数据集就可以做到这一点 final List<Object> objects = new ArrayList<Object>(); final Map<Id, Object> objectMap = new HashMap<Id, Object>(); for (final Obje

这就是我要做的。我有一个要转换为map的对象列表,其中key作为对象id,value作为对象。列表中有数千个对象,这会导致性能问题。有没有简单的方法不用循环或使用其他数据集就可以做到这一点

final List<Object> objects = new ArrayList<Object>();
final Map<Id, Object> objectMap = new HashMap<Id, Object>();

for (final Object object : objects)
{
    objectMap.put(object.getId(), object);
}
final List objects=new ArrayList();
final Map objectMap=新HashMap();
用于(最终对象:对象)
{
objectMap.put(object.getId(),object);
}

您可以尝试调用列表中的并行流:

objects.parallelStream().collect(Collectors.toMap(object -> object.getId(), object -> object));

或者在

中看到更多Java 8并行功能使用Java 8的流不会让您在列表上重复,但可能比重复PUT稍微优化:

final List<Object> objects = new ArrayList<Object>();
final Map<Id, Object> objectMap = objects.stream().collect(Collectors.toMap(e -> e.getId(), e -> e));
final List objects=new ArrayList();
最终映射objectMap=objects.stream().collect(Collectors.toMap(e->e.getId(),e->e));

尝试使用流将列表转换为地图。但无论如何,还是使用了内部循环

Map<Id, Object> objectMap = objects.stream().collect(
                Collectors.toMap(Object ::getId, Object));
Map objectMap=objects.stream().collect(
toMap(对象::getId,Object));

您可以尝试使用正确的容量和负载系数优化
HashMap

HashMap实例有两个影响其性能的参数:初始容量和负载因子。容量是哈希表中的存储桶数,初始容量只是创建哈希表时的容量。负载因子是在自动增加哈希表容量之前允许哈希表达到的满度的度量。当哈希表中的条目数超过加载因子和当前容量的乘积时,哈希表将被重新格式化(即,重建内部数据结构),以便哈希表的存储桶数大约是存储桶数的两倍

容量的最佳值为
n/lf
,因此添加元件不会触发再灰化,其中
n
为最大元件计数,
lf
为负载系数。默认负载系数为0.75,但您可以在构造函数中设置它以满足您的需要

在设置初始容量时,应考虑map中的预期条目数及其负载系数,以尽量减少再灰化操作次数。如果初始容量大于最大入口数除以负载系数,则不会发生再灰化操作

默认值使您的映射使用如此多的put操作多次重新刷新元素,这会影响性能


循环是强制性的,由您或收集器创建。

我已经运行了一个jmh基准测试,测试了一百万个对象,以比较什么是最好的

forloop:26.191±0.567 ms/op

java8并行:42.693±1.784 ms/op

番石榴独特指数:38.097±3.521 ms/op

看来for循环是最快的

以下是基准:(MyObject扩展了Object,并有一个ID整型字段)

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(时间单位毫秒)
@预热(迭代次数=5,时间=1,时间单位=timeUnit.s)
@测量(迭代次数=5,时间=1,时间单位=时间单位。秒)
@叉子(5)
@国家(范围、基准)
公共类ZipIteratorBenchmark{
静态数组列表对象;
@设置(水平试验)
公共作废设置(){
objects=newarraylist();
对于(int i=0;i<1000000;i++){
添加(新的MyObject(i));
}
}
@基准
公共静态映射forloop(){
final Map objectMap=新HashMap();
用于(最终MyObject对象:对象){
objectMap.put(object.getId(),object);
}
返回objectMap;
}
@基准
公共静态映射toMap(){
返回fluenterable.from(objects).uniqueIndex(MyObject::getId);
}
@基准
公共静态映射java8Parallel(){
返回objects.parallelStream().collect(Collectors.toConcurrentMap(MyObject::getId,object->object));
}

}
否。循环将始终以显式或隐式形式出现在代码中。没有其他方法可以对集合进行迭代。请检查这一点,然后您尝试过建议的优化吗?您可以尝试将HashMap容量放入for循环测试中吗?当我设置HashMap容量时,我得到的总时间为24.056±0.973 ms/op,但更多ms/op?不太可能,24.056±0.973 ms/op意味着24.056 ms/op,误差为0.973 ms/op。因此,为hashmap设置容量可以提高性能。谢谢,在我的测试中,容量=1.000.000,负载系数=1,我得到了50%的降低time@Teg这是一个没有受过教育的猜测,我承认我不应该在没有事实检查的情况下发布东西。很抱歉。如果使用并发HashMap收集器,您将获得更好的性能。i、 e:toConcurrentMap而不是toMap