1

Is there any way of appending StringBuilders just "temporarily"? Basically what I want is the same functionality and behaviour of String.concat(), but we're not allowed to use String.concat() or concat Strings with +. I've turned to StringBuilder, but it's mutable.

For instance:

StringBuilder aliasA = new StringBuilder("a");
StringBuilder dot = new StringBuilder(".");
Clausula clause1 = new Clausula(aliasA.append(dot).append("id").toString());
Clausula clause2 = new Clausula(aliasA.append(dot).append("name").toString());

My problem is that when I build clause2, aliasA is no longer "a", but "a.id".

PS: I can't use StringBuffer either.

Luis Sep
  • 2,384
  • 5
  • 27
  • 33
  • If you really want immutability, use String class. StringBuilder should be used if you require to change your string objects value frequently. – roger_that Jul 26 '13 at 10:14
  • You could use a third `StringBuilder` as the data buffer and append stuff to that instead of the initial data set. And btw is StringBuilder really a requirement? – Powerslave Jul 26 '13 at 10:14
  • @Powerslave: No, StringBuilder is not a requirement. The requirement is not to use concat or +. – Luis Sep Jul 26 '13 at 10:31
  • @LuisSep Well, than if a god-damn-awful hack is allowed, you could `String.format("%s%s%s", "a", ".", "id");` :D But that's really nasty, so I'm basically more like kidding. – Powerslave Jul 26 '13 at 11:02

6 Answers6

2

The whole point of StringBuilder is that it is mutable. The reason why you are not allowed to use String concatenation is that it creates new objects because Strings are properly immutable. Actually this is commonly optimized away by the jvm and a complete non-issue from optimization point of view. So, what you are asking for is the worst of both worlds. You want to basically create new objects with a class that is designed to make it possible to not do that.

So, short answer: don't do that and do something else. In your case, the Formatter class might do the trick since it gives you a reusable template that you can pass your values into. And it's a lot more readable.

Formatter f = new Formatter("%s.%s");
String formatted = f.format("a","id");

Actually, just writing "a" + "." + "id" is perfectly fine as well. StringBuilders are nice for the more complex cases where you have loops and conditional logic. However, simple expressions like this are really low hanging fruit for optimization by the compiler. I'd advice you to optimize your code for readability and optimize on a need to have basis rather than prematurely.

Jilles van Gurp
  • 7,927
  • 4
  • 38
  • 46
  • I'm not sure how to use Formatter and if it'll produce a readable code, but thanks to your idea I found `String.format`, which proved very useful. Thanks a lot. – Luis Sep Jul 26 '13 at 12:23
2

How about using StringUtils from Apache Commons?


You could do somthing like:

String a = "a";
String dot = ".";

String clause1 = StringUtils.join(a, dot, "id");
String clause2 = StringUtils.join(a, dot, "name");

OR

String clause1 = StringUtils.join("a", ".", "id");
String clause2 = StringUtils.join("a", ".", "name");

OR EVEN

String clause1 = buildPropertyNotation("id");
String clause2 = buildPropertyNotation("name");

// ...

private buildPropertyNotation(String propName) {
    return StringUtils.join("a", ".", propName);
}

I really think that it is sufficiently readable for any purpose.

Powerslave
  • 1,408
  • 15
  • 16
  • Thanks for the suggestion, but I'm a bit concern about readability – Luis Sep Jul 26 '13 at 12:24
  • @LuisSep And you're pretty much right. Glad to see you care too. Tough I think it's still slightly more readable than the same thing with several lines of `StringBuilder` related code. Maybe the array-part could be improved, but I didn't attempt to give a full solution since I have my own stuff to do at the same time (yup, slacking during worktime :D) – Powerslave Jul 26 '13 at 15:34
  • @LuisSep Found a better, more readable solution, so I've updated my answer for you. – Powerslave Jul 29 '13 at 07:56
  • Looks pretty good, thanks. I'll keep it in mind for next time, now I'll use the one I posted down. It works nicely. – Luis Sep Jul 29 '13 at 08:18
1

Did you try: aliasA.toString().concat(...)

(Sorry, i can not comment)

See also: StringBuilder vs String concatenation in toString() in Java

Community
  • 1
  • 1
1

Wouldn't something like this work ?

StringBuilder aliasA = new StringBuilder("a");
StringBuilder dot = new StringBuilder(".");
Clausula clause1 = new Clausula(new StringBuilder(aliasA).append(dot).append("id").toString());
Clausula clause2 = new Clausula(new StringBuilder(aliasA).append(dot).append("name").toString());
roger_that
  • 9,493
  • 18
  • 66
  • 102
  • I'm sorry, I forgot to say that besides concat, we cannot use + either. – Luis Sep Jul 26 '13 at 10:25
  • Yes, that's my option right now, but I want to avoid that because it looks bad, specially when nesting several of them. – Luis Sep Jul 26 '13 at 10:33
  • If you require to nest several strings, i would suggest to create a utility StringBuilder function which appends the string you pass and return you a stringBuilder.toString() for you to use in Clausula constructor. – roger_that Jul 26 '13 at 10:37
  • In other words, a third StringBuilder – roger_that Jul 26 '13 at 10:38
1

String is immutable, so take advantage of that. StringBuilder was created to, well, build strings, because String concatenation is expensive (creates too many objects). So you can use both to achieve your desired behavior:

String aliasA = "a";
String dot = "."
StringBuilder sb= new StringBuilder(aliasA);
Clausula clause1 = new Clausula(sb.append(dot).append("id").toString());
// This empties the SB, another option could be another new SB
sb.delete(0,sb.length()).append(aliasA);
Clausula clause2 = new Clausula(sb.append(dot).append("name").toString());
Pablo Lozano
  • 10,122
  • 2
  • 38
  • 59
0

Ok, so what I've done, using format as suggested by Jilles van Gurp in his answer, is define my own linking method:

private static String link(String... strings) {
        String f = "";
        String linked;
        String amp = "%s";
        String vAmp = "";
        for (String st : strings) {
            vAmp = new StringBuilder(vAmp).append(amp).toString();
        }

        linked = f.format(vAmp, strings);

        return linked;
}

I don't know if it's optimal in terms of performance, but it's simple to use and read and allowed by my techninal team.

Community
  • 1
  • 1
Luis Sep
  • 2,384
  • 5
  • 27
  • 33