java - 如何减少以下代码中的内存使用量?
问题描述
import java.util.List;
class Solution {
public List<Boolean> kidsWithCandies(int[] candies, int extraCandies) {
List<Boolean> result = new ArrayList<>();
int highest = 1;
for(int i = 0 ; i < candies.length ; i++){
if(candies[i] > highest)
highest = candies[i];
}
for(int i = 0 ; i < candies.length ; i++){
result.add((candies[i] + extraCandies) >= highest);
}
return result;
}
}
我必须尝试解决糖果最高的孩子的问题。上面的代码显示了 38.9 MB 的内存使用情况。我怎样才能进一步减少它。请帮助我了解这个过程是如何工作的。
解决方案
你的代码已经足够紧凑了。你只能做两件事:
- 使用位集
- 使用 Array 代替 List,因为您知道数组的大小。
解释:
boolean
对比BitSet
boolean
为了存储和操作位数组,有人可能会争辩说我们应该使用boolean[]
它作为我们的数据结构。乍一看,这似乎是一个合理的建议。
为了使事情更具体,让我们看看具有 1024 个元素的 boolean[] 消耗了多少空间:
boolean[] bits = new boolean[1024];
System.out.println(ClassLayout.parseInstance(bits).toPrintable());
理想情况下,我们期望该阵列占用 1024 位内存。然而,Java 对象布局 (JOL) 揭示了一个完全不同的现实:
[Z object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 7b 12 07 00 (01111011 00010010 00000111 00000000) (463483)
12 4 (object header) 00 04 00 00 (00000000 00000100 00000000 00000000) (1024)
16 1024 boolean [Z. N/A
Instance size: 1040 bytes
如果我们忽略对象头的开销,数组元素会消耗 1024 字节,而不是预期的 1024 位。这比我们预期的多 700% 的内存。
BitSet
让我们将 1024 位的 BitSet 实例的内存占用与我们之前看到的 boolean[] 进行比较:
BitSet bitSet = new BitSet(1024);
System.out.println(GraphLayout.parseInstance(bitSet).toPrintable());
这将打印 BitSet 实例的浅大小及其内部数组的大小:
java.util.BitSet@75412c2fd object externals:
ADDRESS SIZE TYPE PATH VALUE
70f97d208 24 java.util.BitSet (object)
70f97d220 144 [J .words [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
如上所示,它在内部使用具有 16 个元素(16 * 64 位 = 1024 位)的 long[]。无论如何,这个实例总共使用了 168 个字节,而 boolean[] 使用了 1024 个字节。
更多详情请点击这里。
ArrayList
对比Array
数组内存在创建时分配。当我们初始化一个数组时,它会根据数组的大小和类型来分配内存。它使用引用类型的空值和原始类型的默认值初始化所有元素。
ArrayList 会随着它的增长而改变内存分配。当我们在初始化 ArrayList 时指定容量时,它会分配enough memory
存储对象到该容量。逻辑大小保持为 0。当需要扩展容量时,会创建一个新的更大的数组,并将值复制到其中。
因此,ArrayList(List) 比简单的数组需要更多的内存消耗。
更多详情请点击这里。
修改后的内存优化版本:
public BitSet kidsWithCandies(int[] candies, int extraCandies) {
BitSet bitSet = new BitSet(candies.length);
int highest = Integer.MIN_VALUE;
for(int i = 0 ; i < candies.length ; i++){
if(candies[i] > highest)
highest = candies[i];
}
for(int i = 0 ; i < candies.length ; i++){
bitSet.set(i,(candies[i] + extraCandies) >= highest );
}
return bitSet;
}
推荐阅读
- angular - Angular Kendo UI 数据网格从服务中填充
- asp.net-mvc - 升级到 bootstrap 4 CSS minifier 在 asp.net mvc 中中断
- r - 使用 R 更改土耳其语文本中的特定字母
- python - 当从猴子修补的 gevent 线程调用时,socketio.emit() 没有发送给用户
- c# - Base-64 字符数组或字符串的长度无效:C#
- android - Android studio 3.1.4 卡在 gradle build running
- react-native - 完全无法在真实设备上运行 react native 应用程序
- javascript - Javascript 音频不播放(音板?)
- python-3.x - 绘制具有可变频率的数据与经过的时间
- python-3.x - 块大小或超时异步python