用于内存方面哪个更有效:char[]还是String?

6

我正在开发一款Android应用程序。该应用程序的主要要求是在内存方面效率高。那么,我应该选择哪一个呢?

String batterylevel;
batterylevel = Float.toString(batteryPct);

或者
char batterylevel[];
batterylevel = Float.toString(batteryPct).toCharArray();

你有多频繁地检查电池电量,以至于每次检查约16字节会产生明显的差异? - user253751
1
有一个刷新按钮可以刷新电池电量。因此,这完全取决于用户。尽管如此,没有明显的区别。 - Rajarshi Sarkar
Android系统可能会分配更多的内存,仅仅是为了在用户点击按钮时将其变成橙色。您对内存使用有多担忧?(当Android应用程序存在内存问题时,通常是由于加载数兆字节的图像所致) - user253751
嗯,我只关心20个字符串。我认为每当创建String类的对象时,实例变量也会被分配。这样的情况只有20个,会有很大的差别吗? - Rajarshi Sarkar
2
每个字符串需要3个额外的int字段(32位)和1个引用(64位),总共20个字节。20 * 20 = 400字节额外空间。你只能节省0.0004兆字节,这并不值得优化。此外,请注意toCharArray调用会创建原始字符串内部缓冲区的副本。这意味着只要垃圾收集器不释放内存,你实际上使用的内存就会增加(即:内存翻倍)。我建议你仍然使用String方法。 - Rolf ツ
3个回答

2
在Oracle的JDK中,一个字符串有四个实例级字段:
  • 字符数组
  • 整数偏移量
  • 整数字符计数
  • 整数哈希值
这意味着每个字符串都引入了额外的对象引用(字符串本身)和三个整数,除了字符数组本身。(偏移量和字符计数存在的目的是允许通过String#substring()方法在String实例之间共享字符数组,一些其他Java库实现者已经摒弃了这种设计选择。)除了额外的存储成本,还有更多的访问间接性,更不用说String保护其字符数组的边界检查。
字符串是不可变的。这意味着一旦创建了该字符串,如果另一个进程可以转储内存,则无法在GC启动之前(除了反射)摆脱数据,这意味着浪费内存。
使用数组时,您可以在使用完后显式清除数据:您可以将数组覆盖为任何您喜欢的内容。
因此,就我所知,在内存方面,char [] 更适合您的情况。

0

String是Java中的一个类,它将字符数组封装起来,正如您在代码中所看到的那样。

private final char value[];

每次创建一个字符串对象时,它都由字符数组支持。同时,由于String类具有三个不同的字段,因此它占用的内存比字符数组更多。
但是,如果你看到使用情况,那么String比char array更好,因为它是不可变的。对于String,你不需要进行任何内存管理。在性能方面,对于一些操作(如果你正在处理大量数据),char array[]更快。

0

CString除了字符数组(或宽字符数组)外,还包含字符串大小、分配缓冲区大小和引用计数(同时作为锁标志)。包含字符数组的缓冲区可能比它所包含的字符串要大得多——这允许减少时间成本昂贵的分配调用次数。此外,当CString被设置为零大小时,它仍然包含两个wchar字符。

当然,当您将CString的大小与相应的C风格数组的大小进行比较时,数组会更小。但是,如果您想像CString一样广泛地操作您的字符串,最终您将定义自己的变量来存储字符串大小、缓冲区大小以及有时的引用计数和/或保护标志。确实,您需要存储字符串大小以避免每次需要时都调用strlen。如果您允许缓冲区大于字符串长度,则需要单独存储缓冲区大小,并避免每次添加或减去字符串时调用reallocs。等等——您为一些小的大小增加交换了显著的速度、安全性和功能性的提高。

因此,答案取决于您打算如何使用字符串。假设您想要一个字符串来存储用于记录的类名 - 使用C样式的字符串(const和static)就可以了。如果您需要一个字符串来在MFC或ATL相关类中进行广泛操作和使用,请使用CString系列类型。如果您需要在应用程序的“引擎”部分中操作字符串,这些部分与其界面隔离,并且可能转换为其他平台,请使用std::string或编写自己的字符串类型以满足您特定的需要(当您编写介于界面和引擎之间的“粘合”代码时,这非常有用,否则std::string是首选)。

P.S. 将C++的String与char[]比较

来源


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接