6

I am working on one project for performance enhancement. I had one doubt, while we are during a process, we tend to trace the current state of the DTO and entity used. So, for this we have included toString() method in all POJOs for the same. I have now implemented toString() in three different ways which are following :-

public String toString() {
    return "POJO :" + this.class.getName() + " RollNo :" + this.rollNo + " Name :" + this.name;
}

public String toString() {
    StringBuffer buff = new StringBuffer("POJO :").append(this.class.getName()).append(" RollNo :").append(this.rollNo).append(" Name :").append(this.name);
    return buff.toString();
}

public String toString() {
        StringBuilder builder = new StringBuilder("POJO :").append(this.class.getName()).append(" RollNo :").append(this.rollNo).append(" Name :").append(this.name);
        return builder .toString();
    }

can anyone please help me to find out which one is best and should be used for enhancing performance.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
M.J.
  • 16,266
  • 28
  • 75
  • 97
  • 1
    I'm sure you can write a benchmark in 2minutes. Why guess when you can measure? – Stephen Jun 16 '10 at 05:55
  • 6
    the benchmark would show results, yes, but it's good to know these things theoretically. – Bozho Jun 16 '10 at 05:57
  • possible duplicate of [StringBuilder vs String concatenation in toString() in Java](http://stackoverflow.com/questions/1532461/stringbuilder-vs-string-concatenation-in-tostring-in-java) – polygenelubricants Jun 16 '10 at 05:58
  • "I am working on one project for performance enhancement" - use a profiler, and identify which section of the code is actually worth looking at and optimizing. – polygenelubricants Jun 16 '10 at 06:26

4 Answers4

13

The one with the + is fine in this case. It's more readable, and it's just as performant compared to the StringBuilder/StringBuffer version, since it' doesn't happen inside a loop.

If you are building a String inside a loop, then more often than not you should use StringBuilder. Only use StringBuffer if you need its synchronized feature, which doesn't happen very often.

Simplistically speaking (not true always, but is a good rule of thumb), unless you're doing a += with a String, you don't really need a StringBuilder/StringBuffer.

Related questions


A String.format option

One option often not considered is to use String.format. It'll look something like this:

return String.format("POJO : %s RollNo %s : Name : %s",
   this.getClass().getName(),
   this.rollNo,
   this.name
);

I find that this is the most readable and maintainable version.

Is this faster? Maybe yes, maybe not. It usually doesn't matter for common use case scenarios for something like toString(). Strive for readability, only optimize if profiling says it's necessary.

API links


On Class Literals

I've corrected a syntax error in the original code from this.class (which doesn't compile) to this.getClass().

See also

Related questions

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • 4
    *"Is this faster?"* - almost certainly not because `format` has to parse the format string, and the caller has to allocate and fill a varargs array. But as you say, it probably doesn't matter. – Stephen C Jun 16 '10 at 06:23
  • @Stephen: yep, I'd be very surprised if `format` is faster, but I try not to develop even a basic instinct for these kinds of things, and to just trust a profiler instead. – polygenelubricants Jun 16 '10 at 06:25
  • 1
    Also, I think you can cache the class name in a `static final String`, but I doubt that it'd make too much of a difference. OP should use a profiler and find an actually worthy piece of code to optimize. – polygenelubricants Jun 16 '10 at 06:29
9

Use the 1st one, because it's more readable.

But otherwise, it doesn't matter.

  • Using StringBuilder and + in this case is equivalent, because the compiler translates the overloaded + operator to a StringBuilder.

  • the StringBuffer will be slower, due to its methods being synchronized, but since escape analysis (more specifically - synchronization elision) might used by the compiler (in newer versions), it will automatically remove the synchronized keyword. (See JDK 6u14 release notes to learn about escape analysis)

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Whoa! Which JVM runtime does synch elision? This is the first time I heard of such a (cool!) feature! – polygenelubricants Jun 16 '10 at 06:01
  • 2
    @polygenelubricants since JDK 6u14 it is available, but not on by default I think. See http://java.sun.com/javase/6/webnotes/6u14.html for how to turn it on. – Bozho Jun 16 '10 at 06:04
  • 3
    not so fast. *"Unfortunately escape analysis-based optimisation, which was enabled in update 14, has been disabled again in update 18 to be re-instated at some future date."* – Stephen C Jun 16 '10 at 06:18
  • 1
    Escapse analysis is there in 6u20, but I don't know what it does with this analysis because it doesn't appear to make it faster. ;) – Peter Lawrey Jun 16 '10 at 06:30
3

Use the first one. I'll explain why.

The naive view is to use the last one. There's no reason to use the second one. A StringBuffer is the same as a StringBuilder except it has a performance hit from synchronized locks. But don't put it on one line. This is much more readable:

public String toString() {
  StringBuilder out = new StringBuilder(("POJO :");
  out.append(this.getClass().getName());
  out.append(" RollNo :");
  out.append(this.rollNo);
  out.append(" Name :");
  out.append(this.name);
  return out.toString();
}

That being said, you have to be careful about this kind of micro-optimization. Why? Because the compiler will often do this for you. So write whatever is most readable and let the compiler optimize it.

So the major lesson here is: don't micro-optimize.

Ultimately though, it probably doesn't matter which one of 1 or 3 you use. toString() methods don't tend to be used a huge amount in an application. More commonly they're used in error messages, which are hopefully infrequent.

cletus
  • 616,129
  • 168
  • 910
  • 942
  • 6
    Why bother using a StringBuilder explicitly? The first form will use one implicitly anyway, and without the extra cruft. – Jon Skeet Jun 16 '10 at 05:55
  • I know the compiler will turn the first version into the third, but it's hell to debug this generated version because what happens is not what you see in your source code, so I tend to use the third version. – Sean Patrick Floyd Jun 16 '10 at 06:23
  • @Seanizer Do you often need to debug your toString() methods? Usually I place a breakpoint on the one line in my toString and look at the variable values in my debugger and it tells me what is likely to cause an Exception. – Peter Lawrey Jun 16 '10 at 06:32
  • 1
    @seanizer: you can take that logic further and argue that the only correct way to write code is in assembly, because that's what "actually happens", right? No, I disagree. Abstraction is good. _Ignorance_ of abstraction is bad, but abstraction itself is good. The more the better. – polygenelubricants Jun 16 '10 at 06:34
  • @Peter, @Poly no I don't often debug toString methods, but I often debug methods of third party libraries where string concatenation happens inside a method call and I have to do a lot of f5 / f7 in eclipse in order not to miss the actual statement I am interested in. Yes, abstraction is good, but in this case abstraction has a price that often bugs me. and the assembler point is irrelevant, because my debugger fortunately does not step through assembler calls. but "what happens" was a bad choice of wording, I agree – Sean Patrick Floyd Jun 16 '10 at 07:17
2

This is more readable IMO

public String toString() { 
    return String.Format("POJO : {0} RollNo : {1} Name : {2}",
                          this.getClass().getName(),
                          this.rollNo,
                          this.name);
} 
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
Raj Kaimal
  • 8,304
  • 27
  • 18
  • Maybe in C# it's like that, but not in Java. Also, `this.class` doesn't compile. – polygenelubricants Jun 16 '10 at 06:14
  • in java it's MessageFormat.format(...) with identical parameter syntax (actually I'd use this.getClass(), not getClass().getName(), no need to evaluate the toString before it's needed). btw, this.class doesn't compile as many have already mentioned – Sean Patrick Floyd Jun 16 '10 at 06:27