【发布时间】:2018-05-07 13:22:22
【问题描述】:
Java 代码示例 1:
ArrayList<ArrayList<Integer>> outerList = new ArrayList<ArrayList<Integer>>();
for(i=0; i<5000; i++){
outerList.add(new ArrayList<Integer>());
for(j=0; j<5000; j++){
outerList.get(i).add(1);
}
}
Java 代码示例 2:
ArrayList<ArrayList<Integer>> outerList_n = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> innerList_n = new ArrayList<Integer>();
for(j=0; j<5000; j++){
innerList_n.add(1);
}
for(i=0; i<5000; i++){
outerList_n.add(innerList_n);
}
说明:
代码示例 1 每次都创建一个新的 arrayList 以添加到外部列表,尽管内部列表的每个条目始终为 1。
代码示例 2 创建一个所有条目为 1 的数组,然后在 for 循环中将其添加到 outerList。
问题:
1) 它们的内存占用不同还是相同? 我用 jdk.nashorn.internal.ir.debug.ObjectSizeCalculator 来计算,结果如下:
outerList的大小:514907072
outerList_n的大小:130048
2) 我不明白为什么上面的内存不同。两种情况下的数据结构不一样吗?
3) javascript 中的情况是否相同?当我为上述两种情况尝试各自的 javascript 代码时,我在两种情况下都得到了相同的内存占用。
Javascript 代码:
function sizeof(object){
// initialise the list of objects and size
var objects = [object];
var size = 0;
// loop over the objects
for (var index = 0; index < objects.length; index ++){
// determine the type of the object
switch (typeof objects[index]){
// the object is a boolean
case 'boolean': size += 4; break;
// the object is a number
case 'number': size += 8; break;
// the object is a string
case 'string': size += 2 * objects[index].length; break;
// the object is a generic object
case 'object':
// if the object is not an array, add the sizes of the keys
if (Object.prototype.toString.call(objects[index]) != '[object Array]'){
for (var key in objects[index]) size += 2 * key.length;
}
// loop over the keys
for (var key in objects[index]){
// determine whether the value has already been processed
var processed = false;
for (var search = 0; search < objects.length; search ++){
if (objects[search] === objects[index][key]){
processed = true;
break;
}
}
// queue the value to be processed if appropriate
if (!processed) objects.push(objects[index][key]);
}
}
}
// return the calculated size
return size;
}
// TWO SEPARATE FOR LOOPS
var start = new Date().getTime();
var i,j ;
var inner_arr1 = [];
var outer_arr1 = [];
for (i = 0; i < 100; i++) {
inner_arr1.push("abcdefghijklmnopqrstuvwxyz");
}
for (j = 0; j < 100; j++) {
outer_arr1.push(inner_arr1);
}
var end = new Date().getTime();
print("size of outer_arr1: "+sizeof(outer_arr1));
print("time of outer_arr1 (in ms): "+(end-start))
// NESTED FOR LOOPS
var start = new Date().getTime();
var outer_arr2 = [];
for (j = 0; j < 100; j++) {
var inner_arr2 = [];
for (i = 0; i < 100; i++) {
inner_arr2.push("abcdefghijklmnopqrstuvwxyz");
}
outer_arr2.push(inner_arr1);
}
var end = new Date().getTime();
print("size of outer_arr2: "+sizeof(outer_arr2));
print("time of outer_arr2 (in ms): "+(end-start))
/*
COMMAND:
jjs findingSize.js
OUTPUT:
size of outer_arr1: 52
time of outer_arr1 (in ms): 45
size of outer_arr2: 52
time of outer_arr2 (in ms): 58
*/
【问题讨论】:
-
两者都不同,代码示例 1 将运行 25000 次并添加 5000 个不必要的列表
-
第一个样本会运行 5000^2 次,而第二个样本只会运行 10000 次
-
我知道迭代次数。但这里的问题是关于记忆的。
-
提示:在第二种情况下,您可以看到两个
new运算符。第一个有几个?
标签: javascript java memory