Java 使用收集器使用temp变量
我有以下代码。我想知道它是否会改变记忆 方法1:使用收集器,我可以直接返回地图,如下所示:Java 使用收集器使用temp变量,java,stream,garbage-collection,Java,Stream,Garbage Collection,我有以下代码。我想知道它是否会改变记忆 方法1:使用收集器,我可以直接返回地图,如下所示: List<Customer> customerList = new ArrayList<>(); customerList.add(new Customer("1", "pavan")); customerList.add(new Customer("2", "kumar")); return customerList.stream().colle
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));
List customerList=new ArrayList();
添加(新客户(“1”、“pavan”);
添加(新客户(“2”,“kumar”));
返回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;
Map Map=newhashmap();
map=customerList.stream().collect(Collectors.toMap(t->t.getId(),t->t));
返回图;
与第一种方法相比,如果我迭代一百万次,第二种方法对内存/GC有什么影响吗?在第二种方法中,您实例化了一个映射,并将引用重新分配给调用stream.collect()返回的映射。 显然,“Map”引用的第一个Map对象丢失了 第一种方法没有这个问题
简言之,是的,这在内存使用方面有微小的差别,但考虑到要迭代的条目有一百万个,这一差别可能可以忽略不计。除了实例化第二个示例中不需要的映射实例之外,两段代码都是相同的。立即用流返回的映射引用替换创建的映射引用。编译器很可能会将其作为冗余代码消除 streams API的collect方法将为您实例化一个映射;代码已经得到了很好的优化,这是使用流API的优势之一 为了回答您的特定问题,您可以在代码的两个部分上迭代任意多次,这对GC的影响不会有任何影响。到目前为止,代码并不完全相同;特别是
Collectors.toMap
表示它将返回一个Map
:
对于返回的映射的类型、可变性、序列化性或线程安全性没有任何保证
绝对不能保证返回的Map
实际上是一个HashMap
。它可以是任何其他的东西-任何其他的地图
在这里;因此,将其分配给HashMap
是错误的
然后是构建收集器的方法。可以简化为:
customerList.stream().collect(Collectors.toMap(Customer::getId, Function.identity()));
与lambda表达式相反,方法引用Customer::getId
将少创建一个方法(因为lambda表达式被分解为方法,而方法引用则不被分解)
另外,如果在多个位置使用Function.identity()
而不是t->t
,将创建更少的对象。阅读
还有一个事实是,HashMap
如何在内部工作。如果未指定默认大小,则可能需要重新调整大小,这是一项昂贵的操作。默认情况下,collector.toMap
将以16个条目的默认Map
和load\u因子0.75
开始,这意味着您可以在下次调整大小之前将12个条目放入其中
使用Collectors.toMap
不能忽略它,因为它的供应商总是从HashMap::new
开始-使用默认的16个条目和0.75的加载系数
知道了这一点,您可以完全删除流:
Map<String, Customer> map = new HashMap<String, Customer>((int)Math.ceil(customerList.size() / 0.75));
customerList.forEach(x -> map.put(x.getId(), x));
Map Map=newhashmap((int)Math.ceil(customerList.size()/0.75));
customerList.forEach(x->map.put(x.getId(),x));
在第二个示例中,我想您可能想在映射中使用.forEach()和put()?(如果不是,那么您是在白白实例化一个map:))顺便说一句,Guava提供了Maps.uniqueIndex,这是一种编写相同代码的略短方法。我非常确定这些代码的开销实际上是相同的。是的,我可以这样做。但是我试图理解第二个代码是否与GC PerformanceEyeah有关——它们实际上是相同的。收集器也创建了一个HashMap,但是它在寻找重复项方面有点花哨。第二个代码段忽略重复的代码段。应该是几乎完全相同的GC开销。有相关来源。暂时搁置GC;这两个代码之间存在差异,而且据我所知,这段代码甚至可以改进……噢,该死!西蒙·里特:)真是个惊喜;我可能在youtube上看过你最近的所有视频。尽管如此,我发现这段代码还是可以改进的,为此我添加了一个答案:-)。我同意(正如你在回答中所说的)代码可以改进。