我有一个ArrayList我想完全输出为String.基本上我想按顺序输出它,使用toString由制表符分隔的每个元素.有没有快速的方法来做到这一点?你可以循环它(或删除每个元素)并将它连接到一个字符串,但我认为这将是非常缓慢的.
假设我们的最大内存为256M,为什么这段代码有效:
public static void main(String... args) {
for (int i = 0; i < 2; i++)
{
byte[] a1 = new byte[150000000];
}
byte[] a2 = new byte[150000000];
}
Run Code Online (Sandbox Code Playgroud)
但是这个扔了一个OOME?
public static void main(String... args) {
//for (int i = 0; i < 2; i++)
{
byte[] a1 = new byte[150000000];
}
byte[] a2 = new byte[150000000];
}
Run Code Online (Sandbox Code Playgroud) 我正在使用Play构建一个Java Web应用程序!框架.我在playapps.net上托管它.在提供的内存消耗图表上,我一直困惑不已.这是一个示例:

该图表来自一致但名义上的活动期.我没有做任何事情来触发内存的衰减,所以我认为这是因为垃圾收集器运行,因为它几乎达到了允许的内存消耗.
我的问题:
System.gc(),范围从中性("它只是运行GC的请求,所以JVM可能只是忽略你")完全反对("依赖的代码System.gc()从根本上被打破") .或者我不在这里,我应该在我自己的代码中寻找导致此行为和间歇性性能损失的缺陷? 更新
我已经在PlayApps.net上开启了一个关于这个问题的讨论,并在这里提到了一些观点; 特别是@Affe关于完整GC设置非常保守的评论,以及@ G_H关于初始和最大堆大小设置的评论.
这是讨论的链接,但遗憾的是您需要一个playapps帐户才能查看.
当我得到它时,我会在这里报告反馈; 非常感谢大家的回答,我已经从中学到了很多东西!
解决方案
Playapps支持,这仍然很好,对我没有很多建议,他们唯一的想法是,如果我广泛使用缓存,这可能会使对象保持活动的时间超过需要,但事实并非如此.我还是学到了很多东西(呜呜!),我给了@Ryan Amos绿色支票,因为我提出了他System.gc()每半天打电话的建议,现在工作正常.
在阅读了这篇测量几种对象类型的内存消耗的旧文章后,我惊讶地发现String在Java中使用了多少内存:
length: 0, {class java.lang.String} size = 40 bytes
length: 7, {class java.lang.String} size = 56 bytes
Run Code Online (Sandbox Code Playgroud)
虽然文章有一些提示,以尽量减少这种情况,但我发现它们并不完全令人满意.char[]用于存储数据似乎是浪费的.大多数西方语言的明显改进是使用byte[]和编码类似UTF-8,因为你只需要一个字节来存储最频繁的字符,而不是两个字节.
当然可以使用String.getBytes("UTF-8")和new String(bytes, "UTF-8").甚至String实例本身的开销也会消失.但后来有你失去像非常方便的方法equals(),hashCode(),length(),...
Sun有一个专利的byte[]字符串表示,据我可以告诉.
用于在Java编程环境中高效表示字符串对象的框架
......可以实现这些技术,以便在适当时将Java字符串对象创建为单字节字符的数组...
但是我找不到该专利的API.
我为什么在意?
在大多数情况下,我没有.但我使用包含大量字符串的巨大缓存来处理应用程序,这些字符串可以从更有效地使用内存中受益.
有人知道这样的API吗?或者是否有另一种方法可以保持Strings的内存占用空间小,即使以CPU性能或更丑陋的API为代价?
请不要重复上述文章中的建议:
String.intern()(可能与SoftReferences)char[]并利用当前String.subString(.)实现来避免数据复制(讨厌)更新
我从Sun目前的JVM(1.6.0_10)上的文章中运行了代码.它产生了与2002年相同的结果.
我有一个"为什么这样做?" 关于垃圾收集的问题(任何/所有实现:Java,Python,CLR等).当垃圾收集器不再处于任何范围内时,它会释放该对象; 指向它的引用数为零.在我看来,一旦引用数量达到零,框架就可以解除分配,但我遇到的所有实现都会等待一段时间,然后一次解除分配许多对象.我的问题是,为什么?
我假设框架为每个对象保留一个整数(我认为Python会这样做,因为你必须调用PyINCREF并PyDECREF在C中为它编写扩展模块时;可能这些函数在某处修改了一个真正的计数器).如果是这样,那么它不应该花费更多的CPU时间来消除对象超出范围的时刻.如果现在每个对象需要x纳秒,那么以后每个对象需要x纳秒,对吗?
如果我的假设是错误的并且没有与每个对象关联的整数,那么我理解为什么垃圾收集等待:它必须走引用图以确定每个对象的状态,并且该计算需要时间.这样的方法比显式引用计数方法消耗更少的内存,但我很惊讶它更快或者是其他原因的首选方法.这听起来像是很多工作.
从编程的角度来看,如果对象在超出范围后立即释放,那将会很好.我们不仅可以依赖于在我们希望它们执行时执行的析构函数(其中一个Python陷阱是__del__在可预测的时间没有调用),但是对程序进行内存配置会变得更加容易. 这是一个由此引起的混淆的例子.在我看来,在deallocate-right-away框架中编程的好处是如此之大,以至于为什么我所听到的所有实现在解除分配之前都要等待.这有什么好处?
注意:如果遍历引用图只需要识别循环引用(纯引用计数不能),那么为什么不采用混合方法呢?一旦引用计数达到零,就释放对象,然后进行定期扫描以查找循环引用.在这样的框架中工作的程序员将有一个性能/决定论理由,尽可能地坚持非循环引用.它通常是可行的(例如,所有数据都是JSON对象的形式,没有父指针).这是流行垃圾收集器的工作原理吗?