如何简化 java 中的 String concat?
How to simplify String concat in java?
给定以下代码:
private static final String DELIMITER = " ";
@AfterMapping
protected void createCompactInfo(@MappingTarget User user) {
String vorname = Optional.ofNullable(user.getVorname()).orElse(Strings.EMPTY);
String nachname = Optional.ofNullable(user.getNachname()).orElse(Strings.EMPTY);
String email = Optional.ofNullable(user.getEmail()).orElse(Strings.EMPTY);
String compactInfo =
(vorname
+ DELIMITER
+ nachname
+ DELIMITER
+ (email.isEmpty() ? Strings.EMPTY : "(" + email + ")"))
.trim();
if (compactInfo.isEmpty()) {
user.setCompakt(
Optional.ofNullable(user.getId()).orElse(Strings.EMPTY));
} else {
user.setCompakt(compactInfo);
}
我正在团队中尝试和讨论最简单的代码看起来如何,同时也可以使用如下结构:
- org.apache.commons.lang3.StringUtils: defaultString()
- MoreObjects.firstNonNull(user.getVorname(), Strings.EMPTY)
一个可能的测试可能是这样的(预期结果也在这里可见):
private static Stream<Arguments> arguments() {
return Stream.of(
Arguments.of("Peter", "Silie", "peter@silie.org", "BOND", "Peter Silie (peter@silie.org)"),
Arguments.of(null, "Silie", "peter@silie.org", "BOND", "Silie (peter@silie.org)"),
Arguments.of("Peter", null, "peter@silie.org", "BOND", "Peter (peter@silie.org)"),
Arguments.of("Peter", "Silie", null, "BOND", "Peter Silie"),
Arguments.of(null, "Silie", null, "BOND", "Silie"),
Arguments.of(null, null, "peter@silie.org", "BOND", "(peter@silie.org)"),
Arguments.of("Peter", null, null, "BOND", "Peter"),
Arguments.of(null, null, null, "BOND", "BOND"));
}
@ParameterizedTest(
name = "{index}" + ". Test: vorname={0}, nachname={1}, email={2}; expected: {3}")
@MethodSource(value = "arguments")
void verifyUserKompakt(
String vorname, String nachname, String email, String kuerzel, String expectedResult) {
// arrange
Base base =
Base.builder()
.vorname(vorname)
.nachname(nachname)
.email(email)
.kuerzel(kuerzel)
.build();
// act
User userResult =
userMapperImpl.doIt(base);
// assert
assertThat(userResult.getUserKompakt()).isEqualTo(expectedResult);
}
欢迎提出任何想法...我可以尝试什么?
顺便说一句:java 17 是允许的:-)
以下代码似乎非常接近,但不处理电子邮件的大括号(如果存在):
String compactInfo =
(Stream.of(
user.getVorname(),
user.getNachname(),
user.getEmail())
.map(s -> s != null ? s : "")
.collect(Collectors.joining(" ")))
.trim();
user.setUserKompakt(
compactInfo.isEmpty()
? Optional.ofNullable(user.getKuerzel()).orElse("")
: compactInfo);
由于您有重复的代码来转换 vorname
、nachname
和 userId
,您可能希望将逻辑提取到 Function or an UnaryOperator,因为它是一个字符串到字符串转换和电子邮件的附加转换。例子
import java.util.function.UnaryOperator;
....
private static final String EMPTY = "";
private static final String DELIMITER = " ";
UnaryOperator<String> nameOp = o -> Optional.ofNullable(o).orElse(EMPTY);
UnaryOperator<String> mailOp = o -> Optional.ofNullable(o).map(s -> String.format("(%s)", s)).orElse(EMPTY);
@AfterMapping
protected void createCompactInfo(@MappingTarget User user) {
String compactInfo = Stream.of(nameOp.apply(user.getVorname()),
nameOp.apply(user.getNachname()),
mailOp.apply(user.getEmail()))
.filter(Predicate.not(String::isEmpty))
.collect(Collectors.joining(DELIMITER));
user.setCompakt(compactInfo.isEmpty() ? nameOp.apply(user.getId()) : compactInfo);
}
Java 普通连接和 StringBuilder/StringBuffer 之间存在巨大的性能差异。
在进行字符串连接时观察您的方法 createCompactInfo: compactInfo = ... 将导致性能不佳。
我建议您尝试使用 StringBuilder 或 StringBuffer。
字符串是不可变对象,这意味着值无法更改,因此每次执行串联 strA + strB 都会产生一个新对象。
比较普通连接与 StringBuilder 的性能结果:
public class ConcatenateString {
public static void main (String[] args){
String strFinal = "";
long tStart = System.currentTimeMillis();
for(int i = 0; i < 100000; i ++){
strFinal += "a";
}
long tEnd = System.currentTimeMillis();
long tResult = tEnd - tStart;
System.out.println("Runtime with operator + = "+tResult+" ms");
StringBuilder strBuilder = new StringBuilder();
tStart = System.currentTimeMillis();
for(int i = 0; i < 100000; i ++){
strBuilder.append("a");
}
tEnd = System.currentTimeMillis();
tResult = tEnd - tStart;
System.out.println("Runtime with StringBuilder= "+tResult+" ms");
}
}
结果(位于:Darwin Macs-iMac Darwin 内核版本 20.6.0:8 月 30 日星期一 06:12:21 PDT 2021;RELEASE_X86_64 x86_64 - Intel I5 处理器 2.5ghz):
Runtime with operator + = 1469 ms
Runtime with StringBuilder= 2 ms
给定以下代码:
private static final String DELIMITER = " ";
@AfterMapping
protected void createCompactInfo(@MappingTarget User user) {
String vorname = Optional.ofNullable(user.getVorname()).orElse(Strings.EMPTY);
String nachname = Optional.ofNullable(user.getNachname()).orElse(Strings.EMPTY);
String email = Optional.ofNullable(user.getEmail()).orElse(Strings.EMPTY);
String compactInfo =
(vorname
+ DELIMITER
+ nachname
+ DELIMITER
+ (email.isEmpty() ? Strings.EMPTY : "(" + email + ")"))
.trim();
if (compactInfo.isEmpty()) {
user.setCompakt(
Optional.ofNullable(user.getId()).orElse(Strings.EMPTY));
} else {
user.setCompakt(compactInfo);
}
我正在团队中尝试和讨论最简单的代码看起来如何,同时也可以使用如下结构:
- org.apache.commons.lang3.StringUtils: defaultString()
- MoreObjects.firstNonNull(user.getVorname(), Strings.EMPTY)
一个可能的测试可能是这样的(预期结果也在这里可见):
private static Stream<Arguments> arguments() {
return Stream.of(
Arguments.of("Peter", "Silie", "peter@silie.org", "BOND", "Peter Silie (peter@silie.org)"),
Arguments.of(null, "Silie", "peter@silie.org", "BOND", "Silie (peter@silie.org)"),
Arguments.of("Peter", null, "peter@silie.org", "BOND", "Peter (peter@silie.org)"),
Arguments.of("Peter", "Silie", null, "BOND", "Peter Silie"),
Arguments.of(null, "Silie", null, "BOND", "Silie"),
Arguments.of(null, null, "peter@silie.org", "BOND", "(peter@silie.org)"),
Arguments.of("Peter", null, null, "BOND", "Peter"),
Arguments.of(null, null, null, "BOND", "BOND"));
}
@ParameterizedTest(
name = "{index}" + ". Test: vorname={0}, nachname={1}, email={2}; expected: {3}")
@MethodSource(value = "arguments")
void verifyUserKompakt(
String vorname, String nachname, String email, String kuerzel, String expectedResult) {
// arrange
Base base =
Base.builder()
.vorname(vorname)
.nachname(nachname)
.email(email)
.kuerzel(kuerzel)
.build();
// act
User userResult =
userMapperImpl.doIt(base);
// assert
assertThat(userResult.getUserKompakt()).isEqualTo(expectedResult);
}
欢迎提出任何想法...我可以尝试什么?
顺便说一句:java 17 是允许的:-)
以下代码似乎非常接近,但不处理电子邮件的大括号(如果存在):
String compactInfo =
(Stream.of(
user.getVorname(),
user.getNachname(),
user.getEmail())
.map(s -> s != null ? s : "")
.collect(Collectors.joining(" ")))
.trim();
user.setUserKompakt(
compactInfo.isEmpty()
? Optional.ofNullable(user.getKuerzel()).orElse("")
: compactInfo);
由于您有重复的代码来转换 vorname
、nachname
和 userId
,您可能希望将逻辑提取到 Function or an UnaryOperator,因为它是一个字符串到字符串转换和电子邮件的附加转换。例子
import java.util.function.UnaryOperator;
....
private static final String EMPTY = "";
private static final String DELIMITER = " ";
UnaryOperator<String> nameOp = o -> Optional.ofNullable(o).orElse(EMPTY);
UnaryOperator<String> mailOp = o -> Optional.ofNullable(o).map(s -> String.format("(%s)", s)).orElse(EMPTY);
@AfterMapping
protected void createCompactInfo(@MappingTarget User user) {
String compactInfo = Stream.of(nameOp.apply(user.getVorname()),
nameOp.apply(user.getNachname()),
mailOp.apply(user.getEmail()))
.filter(Predicate.not(String::isEmpty))
.collect(Collectors.joining(DELIMITER));
user.setCompakt(compactInfo.isEmpty() ? nameOp.apply(user.getId()) : compactInfo);
}
Java 普通连接和 StringBuilder/StringBuffer 之间存在巨大的性能差异。
在进行字符串连接时观察您的方法 createCompactInfo: compactInfo = ... 将导致性能不佳。
我建议您尝试使用 StringBuilder 或 StringBuffer。
字符串是不可变对象,这意味着值无法更改,因此每次执行串联 strA + strB 都会产生一个新对象。
比较普通连接与 StringBuilder 的性能结果:
public class ConcatenateString {
public static void main (String[] args){
String strFinal = "";
long tStart = System.currentTimeMillis();
for(int i = 0; i < 100000; i ++){
strFinal += "a";
}
long tEnd = System.currentTimeMillis();
long tResult = tEnd - tStart;
System.out.println("Runtime with operator + = "+tResult+" ms");
StringBuilder strBuilder = new StringBuilder();
tStart = System.currentTimeMillis();
for(int i = 0; i < 100000; i ++){
strBuilder.append("a");
}
tEnd = System.currentTimeMillis();
tResult = tEnd - tStart;
System.out.println("Runtime with StringBuilder= "+tResult+" ms");
}
}
结果(位于:Darwin Macs-iMac Darwin 内核版本 20.6.0:8 月 30 日星期一 06:12:21 PDT 2021;RELEASE_X86_64 x86_64 - Intel I5 处理器 2.5ghz):
Runtime with operator + = 1469 ms
Runtime with StringBuilder= 2 ms