2017-03-09 14 views
0

这就是我所做的。我有一个要转换的对象的列表,用key作为对象id和value作为对象映射。我在列表中有成千上万的对象,并导致性能问题。有没有简单的方法来做到这一点,而不使用循环或使用其他数据集?我们可以在使用Java的Map中一次放置多个键和值吗?

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); 
} 
+1

号循环将一直存在于显式或隐形式的代码。没有其他方式来迭代集合。 – Zefick

+1

checky check out this then https://www.mkyong.com/java8/java-8-convert-list-to-map/ –

+0

您是否尝试过建议的优化? – Teg

回答

1

你可以尝试在列表上调用并行流:

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

否则看到更多的Java在Parallelism Java tutorial

+0

如果您使用并发HashMap收集器,将会获得更好的性能。即:toConcurrentMap而不是toMap – mrida

1

使用了Java 8的流荣获” 8种并行能力不必重复列表上的迭代,但可能比重复投入更优化一些:

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

尝试使用流将List转换为Map。但无论如何使用内部循环。

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

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

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

能力的最佳值是n/lf因此添加元素将不会触发翻版其中n是最大元件计数和lf负载因子。默认加载因子是0.75,但您可以在构造函数中设置它以满足您的需要。

设置其初始容量时应考虑映射中的条目数量及其加载因子,以便尽量减少重新操作的次数。如果初始容量大于最大入口数除以负载因子,则不会发生重新刷新操作。

的默认值可以在地图老调重弹的元素很多次有这么多的放置操作,这影响了演出

环路是强制性的,由您或收集制成。

+0

最后不是一些“omg java 8 performance!”那种回答 – Zeromus

+0

@Teg这是一个没有受过教育的猜测,我承认我不应该发布没有事实核查的事情。对此我很抱歉。 –

1

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

for循环:26.191±0.567毫秒/ OP

java8并行:42.693±1.784毫秒/ OP

Guava.uniqueIndex:38.097±3.521毫秒/ OP

看来,for循环最快的!

这里为基准:(为MyObject延伸对象和具有ID整数字段)

@BenchmarkMode(Mode.AverageTime) 
 
@OutputTimeUnit(TimeUnit.MILLISECONDS) 
 
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) 
 
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) 
 
@Fork(5) 
 
@State(Scope.Benchmark) 
 
public class ZipIteratorBenchmark { 
 

 
    static ArrayList<MyObject> objects; 
 

 
    @Setup(Level.Trial) 
 
    public void setup() { 
 
     objects = new ArrayList<>(); 
 
     for (int i = 0; i < 1000000; i++) { 
 
     objects.add(new MyObject(i)); 
 
     } 
 
    } 
 

 
    @Benchmark 
 
    public static Map<Integer, MyObject> forloop() { 
 
     final Map<Integer, MyObject> objectMap = new HashMap<>(); 
 

 
     for (final MyObject object : objects) { 
 
     objectMap.put(object.getId(), object); 
 
     } 
 
     return objectMap; 
 
    } 
 

 
    @Benchmark 
 
    public static Map<Integer, MyObject> toMap() { 
 
     return FluentIterable.from(objects).uniqueIndex(MyObject::getId); 
 
    } 
 

 
    @Benchmark 
 
    public static Map<Integer, MyObject> java8Parallel() { 
 
    return objects.parallelStream().collect(Collectors.toConcurrentMap(MyObject::getId, object -> object)); 
 
    } 
 
}

+0

您可以尝试将HashMap容量放在for循环测试中吗? – Teg

+0

当我设置HashMap容量时,我得到24.056±0.973 ms/op – mrida

+0

总时间更短但ms/op更多? – Teg

相关问题