我有以下代码。我试图了解它是否会对内存进行任何更改。
方法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 :(得分:1)
除了在第二个示例中实例化您不需要的Map实例之外,两段代码都是相同的。您立即将您创建的Map引用替换为流返回的Map引用。编译器很可能会将其作为冗余代码消除。
streams API的collect方法将为您实例化Map;代码已经过很好的优化,这是使用Stream API而不是自己做的优势之一。
要回答您的具体问题,您可以根据需要多次迭代这两段代码,这对GC的影响不会产生任何影响。
答案 1 :(得分:1)
到目前为止代码并不完全相同;具体而言Collectors.toMap
表示会返回Map
:
无法保证返回的地图的类型,可变性,可串行性或线程安全性。
绝对不能保证返回的Map
实际上是HashMap
。它可能是其他任何东西 - 任何其他Map
在这里;所以将它分配给HashMap
是错误的。
然后就是构建Collector
的方式。它可以简化为:
customerList.stream().collect(Collectors.toMap(Customer::getId, Function.identity()));
与lambda表达式相反,方法引用Customer::getId
将创建一个较少的方法(因为lambda表达式不依赖于方法和方法引用)。
如果在多个地方使用,Function.identity()
而非t -> t
也会创建 less 对象。阅读this。
然后有HashMap
内部如何运作的事实。如果您没有指定default size
,则可能需要重新调整大小 - 这是一项昂贵的操作。 默认情况下 Collectors.toMap
将以16个条目的默认 Map
和load_factor
的{{1}}开头 - 这意味着你可以在下一次调整大小之前输入12个条目。
您不能使用0.75
省略它,因为它的供应商总是从Collectors.toMap
开始 - 使用默认的16个条目和0.75的load_factor。
知道这一点,你可以完全放弃流:
HashMap::new
答案 2 :(得分:0)
在第二种方法中,您将实例化Map,并将引用重新分配给对stream.collect()调用返回的引用。 显然,&#34; map&#34;引用的第一个Map对象;失去了。
第一种方法没有这个问题。
简而言之,是的,这在内存使用方面略有不同,但考虑到你有一百万个条目可以迭代,它可能是微不足道的。