2017-08-17 26 views
1

我有以下代码。我想了解它是否会对内存进行任何更改。使用临时变量使用收集器

方法1:使用收藏家,我可以直接返回地图像这样:

List<Customer> customerList = new ArrayList<>(); 
    customerList.add(new Customer("1", "pavan")); 
    customerList.add(new Customer("2", "kumar")); 

    return customerList.stream().collect(Collectors.toMap(t->t.getId(), t->t)); 

方法2:使用一个明确的地图,收集结果,就像这样:

Map<String,Customer> map = new HashMap<String, Customer>(); 
    map = customerList.stream().collect(Collectors.toMap(t->t.getId(), t->t));  
    return map; 

相比第一,如果我迭代了一百万次,第二种方法对内存/ GC有什么影响?

+0

在你的第二个例子,我想你可能意味着使用.forEach()和put()在地图上? (如果没有,你实例化一个没有任何东西的地图:))顺便说一下,Guava提供了Maps.uniqueIndex,这是写这个相同代码的稍微短一些的方法。我很确定这些开销几乎相同。 – EvanM

+0

是的,我可以做到这一点。但我想了解第二个代码是否与GC性能有关 – pppavan

+0

是的 - 它们几乎完全相同。收集器也创建了一个HashMap,但是对于寻找重复数据有点奇怪。你的第二个片段忽略重复。应该几乎完全相同的GC开销。 – EvanM

回答

0

在第二种方法中,您正在实例化一个Map,并将该引用重新分配给由stream.collect()调用返回的引用。 显然,由“map”引用的第一个Map对象会丢失。

第一种方法没有这个问题。

总而言之,这在内存使用情况方面略有差异,但考虑到您有一百万个条目需要迭代,这可能忽略不计。

1

除了在第二个示例中实例化一个不需要的Map实例之外,这两段代码都是相同的。您立即将您创建的Map引用替换为由流返回的引用。编译器很可能会将其作为冗余代码来消除。

streams API的collect方法将为您实例化Map;代码已经很好的优化了,这是你自己使用Stream API的好处之一。

要回答您的具体问题,您可以根据需要多次迭代代码的两部分,并且不会对GC影响产生任何影响。

+0

将GC搁置一会儿;有差异和*潜在*这个代码甚至可以改善,据我所知... – Eugene

+0

噢该死! Simon Ritter :)多么惊喜;我可能在YouTube上观看了您最近的所有视频。尽管如此,我发现这个代码可以改进,我已经为该 – Eugene

+0

添加了一个答案:-)。我同意(正如您在答复中发布的那样)可以改进代码。 – Speakjava

1

有代码是到目前为止不完全相同;特别Collectors.toMap说,它会返回一个Map

上有型,可变性,串行化,或者地图的线程安全没有保证退换。

有绝对没有保证什么那么以往任何时候都返回Map实际上是一个HashMap。它可以是其他任何东西 - 任何其他Map在这里;所以将它分配给HashMap就错了。

然后就是你建立Collector的方式。它可以被简化为:

customerList.stream().collect(Collectors.toMap(Customer::getId, Function.identity())); 

的方法参考Customer::getId,而不是lambda表达式,将创建少一个方法(因为lambda表达式被去糖的方法和方法的引用都没有)。

此外,如果在多个地方使用Function.identity()代替t -> t将创建对象。阅读this

然后有一个事实如何HashMap内部工作。如果您未指定default size,则可能需要重新调整大小 - 这是一项昂贵的操作。这意味着你可以把12项进入它的下一个大小调整之前 - 默认Collectors.toMap将与默认16项Map0.75一个load_factor开始。

您不能省略使用Collectors.toMap,因为供应商始终从HashMap::new开始 - 使用默认的16个条目和0.75的load_factor。

知道了这一点,你可以将整个流:

Map<String, Customer> map = new HashMap<String, Customer>((int)Math.ceil(customerList.size()/0.75)); 
customerList.forEach(x -> map.put(x.getId(), x));