【问题标题】:Multiple StringBuilders inside StringBuilder. Does it worth?StringBuilder 中的多个 StringBuilder。值得吗?
【发布时间】:2019-11-08 14:51:07
【问题描述】:

我收到一份模型列表。模型的数量可能很大。这个模型有很多属性,其中任何一个都可能是null

我需要根据每个模型的属性为每个模型构建一个字符串。如果 property == null 然后我在结果字符串中添加一些静态部分,例如 "property1 is null"

If else property != null 然后我添加类似这样的内容 "property1 == 'valueOfThePropertyHere'"

结果字符串应如下所示: prop1 == 'value1' and prop2 is null and prop3 == 'value3' and prop4 == 'value4' and prop5 is null and ..... propN == 'valueN'

我为列表中的每个模型生成这样的字符串。

显然,我在 for 循环中执行此操作,并为此使用 StringBuilder。问题是,在 StringBuilder 的 append 方法中,我使用三元运算符检查模型的每个字段是否为空,并在此基础上将此检查的结果添加到结果字符串中。但是如果一个属性不为空,那么我需要添加一些静态部分 + 字段本身的值 + 一些更多静态的东西。这意味着我需要为我拥有的每个属性再添加一个 StringBuilder。或者我可以使用“+”,它无论如何都会被转换为 StringBuilder,据我所知,在 StringBuilder 中使用“+”是一种不好的做法(但无论如何我都必须使用它)。

例子:

List<Model> models = repository.getModels();

for (Model m: models) {
    StringBuilder stringBuilder = new StringBuilder();

    stringBuilder
    .append(m.getField1() == null ? "field1  is null" : "field1 == '" + new StringBuiler().append(m.getField1()).append("'").append(" and ").toString()))
    .append(m.getField2() == null ? "field2  is null" : "field2 == '" + new StringBuiler().append(m.getField2()).append("'").append(" and ").toString()))
    ...............
    .append(m.getFieldN() == null ? "fieldN  is null" : "fieldN == '" + new StringBuiler().append(m.getFieldN()).append("'").append(" and ").toString()));

    System.out.println(stringBuilder.toString());
    }

从性能的角度来看,我认为它看起来不太好,因为对于模型列表中的每个模型,我都会在堆中创建另一堆 StringBuilder 对象,只是为了获取结果字符串。

我错过了什么吗?从性能的角度来看,有没有更好的方法来做到这一点?或者没关系,因为我目前看不到其他选项。

【问题讨论】:

  • stackoverflow.com/questions/513600/… 有一些关于可用选项及其速度的信息。
  • “在我看来,从性能的角度来看,它看起来不太好” 我不同意,因为这里的性能角度非常微观,你甚至无法测量任何差异。让编译器 + JVM + 热点操心微优化,你只要写出好、干净的代码。
  • 创建一个新的 StringBuilder 只是为了立即附加 3 个东西并调用 toString() 违背了 StringBuilder 的目的
  • 只需使用if/else,并直接附加到主StringBuilder
  • 顺便说一句 new StringBuilder().append(a).append(b)...toString() 是编译器为 a+b+... 所做的(但后来更容易阅读)

标签: java string performance concatenation stringbuilder


【解决方案1】:

追求简单。

代替

stringBuilder
.append(m.getField1() == null ? "field1  is null" : "field1 == '" + new StringBuiler().append(m.getField1()).append("'").append(" and ").toString()))

使用:

if (m.getField1() == null) {
  stringBuilder.append("field1  is null");
} else {
  stringBuilder.append("field1 == '").append(m.getField1()).append("'").append(" and ");
}

除了在StringBuilder.append 调用中使用StringBuilder 的明显奇怪之处(以及为什么不直接使用+...),真的很难解析: 在条件表达式中的位置.把它分成几行要容易得多。


如果您发现自己不得不多次重复此 Code Pattern,请定义一个方法:

void append(StringBuilder stringBuilder, String name, Object value) {
  stringBuilder.append(name);
  if (value == null) {
    stringBuilder.append(" is null");
  } else {
    stringBuilder.append(" == '").append(value).append("'").append(" and ");
  }
}

然后像这样调用:

append(stringBuilder, "field1", m.getField1());
append(stringBuilder, "field2", m.getField2());
append(stringBuilder, "field3", m.getField3());

【讨论】:

  • 请注意 == null 情况下缺少的“和”。
  • @AndyMan 似乎是合理的。想要尽可能地使其紧凑(如果在这种情况下可以这么说的话)。
  • @Coffemanz 'compact' 和 'performance perspective' 有很大不同...
  • 如果你想要紧凑,那么只需删除第二个 StringBuilder 并使用像“==”+ value +“'和”这样的字符串。 Java 在内部使用 StringBuilder,所以它们是等价的。
【解决方案2】:

真是一团糟!仅仅因为你可以链接调用,并不意味着你应该:

List<Model> models = repository.getModels();

    for (Model m: models) {
        StringBuilder stringBuilder = new StringBuilder();

        String field = m.getField1();
        if(field==null) {
            stringBuilder.append("field1 is null");
        } else {
            stringBuilder.append("field1 == ").append(m.getField1()).append("'");
        }

        if(stringBuilder.length()>0) {
            stringBuilder.append(" and ");
        }

        field = m.getField2();
        if(field==null) {
            stringBuilder.append("field2 is null");
        } else {
            stringBuilder.append("field2 == ").append(m.getField1()).append("'");
        }

        if(stringBuilder.length()>0) {
            stringBuilder.append(" and ");
        }
        ...

        System.out.println(stringBuilder.toString());
    }

为了避免所有这些潜在的重复(取决于字段的数量):

void appendField(StringBuilder stringBuilder, String fieldName, String value) {
    if(stringBuilder.length()>0) {
        stringBuilder.append(" and ");
    }
    stringBuilder.append(fieldName);
    if(value==null) {
        stringBuilder.append(" is null");
    } else {
        stringBuilder.append(" == '").append(value).append("'");
    }
}
String toString(Model m) {
    StringBuilder stringBuilder = new StringBuilder();

    appendField(stringBuilder, "field1", m.getField1());
    appendField(stringBuilder, "field2", m.getField2());
    ...
    appendField(stringBuilder, "fieldN", m.getFieldN());

    return stringBuilder.toString();
}

List<Model> models = repository.getModels();

for (Model m: models) {
    System.out.println(toString(m));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    • 2018-09-22
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 2011-04-16
    相关资源
    最近更新 更多