使用 intelliJ 将字符串串联重构为 StringBuilder

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

我被指定负责一个项目的重构,我就遇到了这样的情况

 this.path = DESTINY + deploy.name() + FILE_SEPARATOR + delivery.getSystem().getCode()
      + FILE_SEPARATOR + delivery.getName() + FILE_SEPARATOR + delivery.getEnviroment().getName();

我想将其重构为这样的:

StringBuilder tmpPath = new StringBuilder();
tmpPath.append(DESTINY);
tmpPath.append(deploy.name());
tmpPath.append(FILE_SEPARATOR);
tmpPath.append(delivery.getSystem().getCode());
tmpPath.append(FILE_SEPARATOR);
tmpPath.append(delivery.getName());
tmpPath.append(FILE_SEPARATOR);
tmpPath.append(delivery.getEnviroment().getName());
this.path = tmpPath.toString();

或者

StringBuilder path = new StringBuilder();

...

this.path.append(DESTINY);
this.path.append(deploy.name());
this.path.append(FILE_SEPARATOR);
this.path.append(delivery.getSystem().getCode());
this.path.append(FILE_SEPARATOR);
this.path.append(delivery.getName());
this.path.append(FILE_SEPARATOR);
this.path.append(delivery.getEnviroment().getName());

最快的方法是什么?

string intellij-idea refactoring stringbuilder
2个回答
9
投票

当光标位于原始代码上时,只需按 Alt + Enter

enter image description here

然后您可以选择您最喜欢的变体,例如将其替换为 String Builder。 IDEA 将为您完成所有工作。

enter image description here


0
投票

接受的答案已经解释了如何做到这一点。我想添加一些关于“何时和何时不”的细微差别。不可能用评论中的示例来解释这一点。我怀疑很多人将来可能会因为与OP问题相同的原因而发现这个问题。 我认为在问题中的情况下重构为 StringBuilder 是出于错误的原因。这是

货物崇拜编程

的常见案例。 有一个常见的误解,认为像这样的字符串表达式

"It is " + LocalTime.now() + " o'clock";

会导致每个“+”的字符串串联,因此时间和空间复杂度为 O(n^2)。

但是,如果所有段在编译时都是已知的,Java 会在幕后使用 StringBuilder,即使其中一些段是动态计算或格式化的,如本例中的 

LocalTime.now()

。它隐式使用 StringBuilder 的事实实际上是一个无趣的实现细节;重要的是它可以将字符串的总长度确定为各个字符串长度的总和,然后分配单个字符串并填充一次。

那么什么时候应该使用 StringBuilder 呢?如果您将字符串生成器传递给方法,然后追加到它,或者如果您有条件地追加 (

if (example) { stringBuilder.append("...") }

),尤其是在循环中。

在您的特定示例中,使用普通连接语法与 StringBuilder 相比不会造成性能损失,因此在可读性和性能之间没有权衡。我认为,通过对原始版本进行更好的格式化,您的字符串将比使用字符串生成器更容易阅读。这有点主观,但在我的专业圈子里,这通常被认为是正确的。我将把这两个例子放在一起,让你判断。重要的是要知道

为什么

我们做出决定。

原代码

this.path = DESTINY + deploy.name() + FILE_SEPARATOR + delivery.getSystem().getCode() + FILE_SEPARATOR + delivery.getName() + FILE_SEPARATOR + delivery.getEnviroment().getName();

使用 StringBuilder

StringBuilder tmpPath = new StringBuilder(); tmpPath.append(DESTINY); tmpPath.append(deploy.name()); tmpPath.append(FILE_SEPARATOR); tmpPath.append(delivery.getSystem().getCode()); tmpPath.append(FILE_SEPARATOR); tmpPath.append(delivery.getName()); tmpPath.append(FILE_SEPARATOR); tmpPath.append(delivery.getEnviroment().getName()); this.path = tmpPath.toString();

改进格式的原始代码(推荐)

this.path = DESTINY + deploy.name() + FILE_SEPARATOR + delivery.getSystem().getCode() + FILE_SEPARATOR + delivery.getName() + FILE_SEPARATOR + delivery.getEnviroment().getName();

另一种选择(推荐)

在使用分隔符连接字符串段时,我建议使用此选项。

this.path = String.join(FILE_SEPARATOR, DESTINY + deploy.name(), delivery.getSystem().getCode(), delivery.getName(), delivery.getEnviroment().getName());

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