Java字符串拼接和静态字符串的区别

6

我希望更好地理解字符串。我正在编写一个需要大量字符串的程序。但是,很多字符串非常相似,只需在字符串结尾处更换不同的单词即可。

例如:

String one = "I went to the store and bought milk"
String two = "I went to the store and bought eggs"
String three = "I went to the store and bought cheese"

我的问题是,在处理字符串时,哪种方法最适合?将两个字符串连接起来是否比仅使用静态字符串更具有性能或内存管理方面的优势?
例如:
String one = "I went to the store and bought "
String two = "milk" 
String three = "cheese"
String four = one + two
String five = one + three

我只是想找出处理所有这些字符串的最佳方法。(如果需要知道我使用的字符串数量,我目前有50个,但数量可能会超过很多)


14
可读性更重要。我认为这两者之间没有真正的性能差异。 - Spooky
static final字符串,在这里很好地解释了。对于常量部分使用字符串是一个不错的主意。 - pietv8x
2
本地化有时使用字面字符串比生成的字符串更容易。 - Andy Thomas
2
你能定义一下“巨大”和“很多”的具体含义吗?因为你提供的唯一数字(50)对于计算机来说远远不足以被称作“很多”。50个40个字符的字符串就已经占用了4KB的内存。你想要达到什么目的?这些硬编码的字符串都是用来做什么的?在我看来,这似乎是一个X/Y问题。 - JB Nizet
2
代码应该易读且易于维护。如果字符串在多个地方使用或可能更改,则将它们放入变量中可能是更合适的选项。无论如何,这个问题主要基于观点,真正取决于开发人员对采取哪种选项进行判断。 - ug_
显示剩余3条评论
7个回答

2
如spooky所说,代码的主要问题是可读性。除非你正在为手机编写程序,否则不需要管理资源。话虽如此,无论你创建很多独立的字符串还是将基本字符串与变化的小片段连接起来,都无关紧要。你不会真正注意到任何一种方式的性能提升。

没有评论权限。这是我唯一能够表达问题的方式。 - Matt Quick
我知道...这就是为什么我没有点踩的原因...我们都是从那里开始的...所以我们只能接受它。 - TheLostMind

0
在Java中,如果你连接两个字符串(例如使用'+'),会创建一个新的字符串,因此旧的内存需要进行垃圾回收。如果你想要连接字符串,正确的方法是使用StringBuilder或StringBuffer。
考虑到你关于这些字符串实际上是URL的评论,你可能希望有一个StringBuilder/StringBuffer作为URL基础,然后根据需要添加后缀。

感谢您的回复。然而,我并不一定想采取连接方法。我只是在询问处理这样的字符串时的好方法。无论是连接比静态字符串更优的方法。 - Awesomasaurus
从性能的角度来看,连接实际上不太理想。如上所述,它会创建多个字符串,然后Java需要对其进行垃圾回收。@Awesomasaurus 来回答那个问题。 - Julie

0

在你提供的示例中,无论你声明每个可能的字符串还是分开字符串进行连接,都不会对内存或性能产生任何可衡量的影响。在声明真正大量的字符串文字的极端情况下,如果你声明每个可能的字符串,Java的本地哈希表interned Strings将使用更多的内存,因为缓存的值将更长。

如果你使用+运算符连接超过2个字符串,你将创建额外的字符串对象以进行垃圾回收。例如,如果你有字符串a = "1"b = "2",并执行String s = "s" + a + b;,Java将首先创建字符串"s1",然后将其连接形成第二个字符串"s12"。通过使用类似于StringBuilder的东西来避免中间字符串。(这不适用于编译时声明,但适用于运行时连接。)

如果你需要对字符串进行格式化而不是简单地拼接,请使用MessageFormatString.format()。这样更美观,避免了使用+运算符时创建中间字符串的问题。因此,可以像这样编写代码:String urlBase = "http://host/res?a=%s&b=%s"; String url = String.format(urlBase, a, b);其中ab是查询参数字符串值。


0

你可以像这样将开头的句子设置为字符串

String openingSentence = "I went to the store and bought";

并交替定义每个单词,通过定义以下字符串数组之一来定义:

String[] thingsToBeBought = { "milk", "water", "cheese" .... };

然后你可以使用foreach循环,将数组中的每个元素与开头的句子连接起来。

最好将openingSentence设为静态不变的字符串。 - pietv8x

0
从性能角度来看,final static字符串总是更好的选择,因为它们是在编译时生成的。就像这样:
final static String s = "static string";

非静态字符串和如其他示例中所示的连接字符串是在运行时生成的。因此,即使对于这样一个小事情,性能几乎不会有影响,但第二个示例在性能方面不如第一个,就像您的代码一样:

// not as good performance wise since they are generated at runtime
String four = one + two
String five = one + three

1
static final 使字符串成为编译时常量。final 关键字非常重要 :) - TheLostMind
@VinodMadyalkar 是的。添加了一个小例子。谢谢你指出来 :) - Pritam Banerjee

0

由于您将使用此字符串作为URL,我建议使用StringJoiner(如果您正在使用JAVA 8)。它与StringBuilder一样高效(每次执行连接时不会创建新字符串),并且会自动在字符串之间添加“/”。

StringJoiner myJoiner = new StringJoiner("/")

0

性能上没有明显的差别,因此你采取的方式更多是出于个人喜好。我很可能会将句子的前半部分声明为字符串,并将单独的购买物品存储在数组中。

例如:

String action = "I went to the store and bought ";
String [] items = {"milk", "eggs", "cheese"};

for (int x = 0; x< items.length; x++){
     System.out.println(action + items[x]);
}

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