【问题标题】:How to simplify String concat in java?如何在java中简化String concat?
【发布时间】:2021-10-27 18:10:47
【问题描述】:

给定以下代码:

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);

【问题讨论】:

  • Objects.requireNonNullElse?

标签: java string trim simplify


【解决方案1】:

由于您有重复的代码来转换vornamenachnameuserId,您可能希望将逻辑提取到FunctionUnaryOperator,因为它是一个字符串到字符串的转换和一个附加的转换对于电子邮件。示例

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);
}

【讨论】:

  • 很好的解决方案,谢谢
  • @DerBenniAusA 欢迎您。乐于助人。
【解决方案2】:

Java 普通串联和 StringBuilder/StringBuffer 之间存在巨大的性能差异。

在进行字符串连接时观察您的方法 createCompactInfo:compactInfo = ... 将导致性能不佳。

我建议你试试 StringBuilder 或 StringBuffer。

String 是一个不可变的对象,这意味着它的值不能被改变,所以每次你连接 strA + strB 都会产生一个新的 Object。

比较普通串联与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 Kernel Version 20.6.0:Mon Aug 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-08
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 2021-11-19
    相关资源
    最近更新 更多