Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用收集器使用temp变量_Java_Stream_Garbage Collection - Fatal编程技术网

Java 使用收集器使用temp变量

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

我有以下代码。我想知道它是否会改变记忆

方法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));
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上看过你最近的所有视频。尽管如此,我发现这段代码还是可以改进的,为此我添加了一个答案:-)。我同意(正如你在回答中所说的)代码可以改进。