views:

194

answers:

4

hi, 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.

+3  A: 

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
Why bother using a StringBuilder explicitly? The first form will use one implicitly anyway, and without the extra cruft.
Jon Skeet
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.
seanizer
@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
@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
@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
seanizer
+8  A: 

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

polygenelubricants
*"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
@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
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
+5  A: 

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
Whoa! Which JVM runtime does synch elision? This is the first time I heard of such a (cool!) feature!
polygenelubricants
@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
@Bozho - 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
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
good to know :)
Bozho
+2  A: 

This is more readable IMO

public String toString() { 
    return String.Format("POJO : {0} RollNo : {1} Name : {2}",
                          this.getClass().getName(),
                          this.rollNo,
                          this.name);
} 
Raj Kaimal
Maybe in C# it's like that, but not in Java. Also, `this.class` doesn't compile.
polygenelubricants
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
seanizer