Java 连接以构建字符串或格式

问题描述 投票:0回答:8

我现在正在使用java编写一个MUD(基于文本的游戏)。 MUD 的主要方面之一是格式化字符串并将其发送回用户。如何最好地实现这一点?

假设我想发送以下字符串:

你对某人说“你好!” - 其中“某人”、“说”和“你好!”都是变量。哪个性能最好?

"You " + verb + " to " + user + " \"" + text + "\""

String.format("You %1$s to %2$s \"%3$s\"", verb, user, text)

或者其他选择?

我不确定最终哪个会更容易使用(这很重要,因为它会无处不在),但我现在正在考虑它,因为与 + 连接有点令人困惑与一些较大的线路。我觉得在这种情况下使用 StringBuilder 只会使其可读性更差。

这里有什么建议吗?

java string-formatting string-concatenation mud
8个回答
30
投票

如果字符串是使用单个串联表达式构建的;例如

String s = "You " + verb + " to " + user + " \"" + text + "\"";

那么这或多或少相当于更冗长的内容:

StringBuilder sb = new StringBuilder();
sb.append("You");
sb.append(verb);
sb.append(" to ");
sb.append(user);
sb.append(" \"");
sb.append(text );
sb.append('"');
String s = sb.toString();

事实上,经典的 Java 编译器会将前者编译为后者......几乎。在 Java 9 中,他们实现了 JEP 280,它将字节码中的构造函数和方法调用序列替换为单个

invokedynamic
字节码。然后运行时系统会对此进行优化1

当您开始创建中间字符串或使用

+=
等构建字符串时,就会出现效率问题。在某些情况下,使用显式
StringBuilder
可以更有效地2,因为您可以减少复制量。

现在,当您使用

String.format()
时,它应该在引擎盖下使用
StringBuilder
。但是,
format
还必须在每次调用时解析格式字符串,如果您以最佳方式构建字符串,则不会有这种开销。


话虽如此,我的建议是以最具可读性的方式编写代码。如果 profiling 告诉您这是真正的性能问题,则只需担心构建字符串的最有效方法。 (现在,您正在花时间思考解决性能问题的方法,但结果可能是微不足道或无关紧要的。)

另一个答案提到使用格式字符串可以简化对多种语言的支持。这是事实,尽管您在复数、性别等方面可以做的事情是有限的。


1 - 因此,对于 Java 9 或更高版本,上面示例中的手动优化实际上可能会产生负面 后果。但这是每次进行微优化时都要冒的风险。
2 - 分析和预测何时发生这种情况一般来说很困难。


2
投票

我认为与

+
的串联比使用
String.format
更具可读性。

当您需要格式化数字和日期时,

String.format
非常有用。


1
投票

与 plus 连接,编译器可以以性能方式转换代码。对于字符串格式我不知道。

我更喜欢与 plus 并置,我认为这样更容易理解。


1
投票

保持简单的关键是永远不要看它。这就是我的意思:

Joiner join = Joiner.on(" ");

public void constructMessage(StringBuilder sb, Iterable<String> words) {
  join.appendTo(sb, words);
}

我使用 Guava Joiner 类来使可读性不再是问题。还有什么比“加入”更清楚的呢?所有与串联有关的令人讨厌的部分都被很好地隐藏起来。通过使用 Iterable,我可以将此方法用于各种数据结构,列表是最明显的。

这里是一个使用 Guava ImmutableList 的调用示例(它比常规列表更有效,因为任何修改列表的方法都会抛出异常,并且正确地表示了 constructMessage() 无法更改单词列表的事实,只是消耗它):

StringBuilder outputMessage = new StringBuilder();
constructMessage(outputMessage, 
         new ImmutableList.Builder<String>()
            .add("You", verb, "to", user, "\"", text, "\"")
            .build());

0
投票

老实说,如果您想要减少打字量,我建议您选择第一个,或者如果您正在寻找更 C 风格的方式来执行此操作,则选择后一个。

我坐在这里一两分钟思考可能出现问题的想法,但我认为这取决于你想输入多少内容。

还有人有想法吗?


0
投票

假设您要经常重用基本字符串 存储您的模板,如

String mystring = "你$1到$2\"$3\""

然后获取一份副本并将 $X 替换为您想要的内容。

这对于资源文件也非常有效。


0
投票

我认为 String.format 看起来更干净。 但是,您可以使用 StringBuilder 并使用追加函数来创建您想要的字符串


-3
投票

从性能角度来看,最好的可能是使用 StringBuffer。

© www.soinside.com 2019 - 2024. All rights reserved.