views:

218

answers:

8

So I essentially need to do this:

String text = "line1\n";
text += "line2\n";
text += "line3\n";
useString( text );

There is more involved, but that's the basic idea. Is there anything out there that might let me do something more along the lines of this though?

DesiredStringThinger text = new DesiredStringThinger();
text.append( "line1" );
text.append( "line2" );
text.append( "line3" );
useString( text.toString() );

Obviously, it does not need to work exactly like that, but I think I get the basic point across. There is always the option of writing a loop which processes the text myself, but it would be nice if there is a standard Java class out there that already does something like this rather than me needing to carry a class around between applications just so I can do something so trivial.

Thanks!

+8  A: 

AFAIK there's no library class that allows you to do so.

The following does the work though:

class DesiredStringThinger {
  StringBuilder text = new StringBuilder();

  public void append(String s) { text.append(s).append("\n"); }

  @Override
  public String toString() { return text.toString(); }
}
missingfaktor
While correct, this will cause performance problems with relatively small numbers of lines: Roman's solution is in that respect much better.
Tomislav Nakic-Alfirevic
Just a recommendation: use @Roman's 'String lsp = System.getProperty("line.separator");' but declare it as a private static member
Yaneeve
@Tomislav: How?
missingfaktor
StringBuffer is synchronized, but I "performance problems"? Nah. Uncontended lock acquisition is fast. In fact, in later JVM, unnecessary locks are optimized away anyway. But I guess you don't have reason to prefer StringBuffer, either...
Enno Shioji
This solution is elegant. I like the use of delegation to create a wrapper.
Steve McLeod
@Zwei: Thanks. I'll change that to `StringBuilder`.
missingfaktor
@Tomislav: I don't see why performance should be particularly worse in this solution.
Steve McLeod
There's a fairly good explanation e.g. here: http://www.javapractices.com/topic/TopicAction.do?Id=4"Compilers often implement concatenation operations by creating intermediate objects in the background. Such intermediate objects are not needed by StringBuilder."I ran into this when trying to concatenate whole files (<30kb) and the difference in efficiency between the "+" operator and using a StringBuffer was extreme.
Tomislav Nakic-Alfirevic
@Tomislav the same article also says "then the difference in relative performance is very small, and possibly not even measurable (the great majority of use cases of the concatenation operator fall into this category)"
matt b
@Matt: True, but I _did_ specify in my 1st comment that I _am_ in fact talking about a specific case. In retrospect, my wording was a bit unfortunate, but on my own project I saw performance problems when concatenating a couple of hundred lines of text, which is what I consider a "relatively small number of lines". Of course, it depends on how often you invoke such a routine (all of the time, in my case).
Tomislav Nakic-Alfirevic
@Tomislav I don't see a significant difference between this answer and Roman's, both make use of StringBuilder and append() under the covers. Neither use literal concatenation.
matt b
I was convinced that Rahul's initial concatenation code was something along the lines of `text += line;`, but looking at the answer history, it seems I was mistaken. My apologies, Rahul.
Tomislav Nakic-Alfirevic
@Tomislav: You were right. First I had posted a quick and dirty `text += line;` solution and changed it to the `StringBuffer` alternative within another 2-3 minutes (before I saw your comment). Perhaps that's why the original post doesn't show up in edit history. Then I changed it to `StringBuilder` on Zwei's suggestion. My apologies for all the confusion that I caused. :(
missingfaktor
+4  A: 
public String createString () {
   StringBuilder sb = new StringBuilder ();
   String txt = appendLine("firstline", sb).appendLine("2ndLine", sb).toString();
}

private StringBuilder appendLine (String line, StringBuilder sb) {
   String lsp = System.getProperty("line.separator");
   return sb.append (line).append (lsp);
}
Roman
+1  A: 

You can use a StringBuffer

StringBuffer text = new StringBuffer();
text.append("line1");  
text.append("line2");  
...  
useString(text.toString());   

This will not append the new line character, but you can certainly append that as well for each line.

rayd09
I think Marshmellow1328 wants a new line between each token when append() is called
matt b
This is actually where I started. Then I got tired of adding the newline character for every line. While I could have easily created a small helper function to do it, I was hoping there might be something that already exists out there rather than having to expand my basic java library.
Marshmellow1328
+9  A: 

You can use a StringWriter wrapped in a PrintWriter:

StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter, true);
writer.println("line1");
writer.println("line2");
writer.println("line3");
useString(stringWriter.toString());
Joachim Sauer
+1, didn't know about `StringWriter`
missingfaktor
A: 

Perhaps the lowest impact method is to add a static method to append with a new line to a StringBuilder.

 public static StringBuilder appendln(StringBuilder buff, String str) {
     return buff.append(str).append('\n');
 }

But @Joachim Sauer beats me to my preferred solution. For more complex examples you might want to use your own Writer decorator, as @Rahul G (only use private fields).

Tom Hawtin - tackline
A: 

If you are not crazy about performance, I think this is clean and neat.

class DesiredStringThinger {
  StringBuilder sb = new StringBuilder();

  public void concat(String... s) { 
      for(String str : s){
         sb.append(s).append("\n");
      }
  }

  @Override
  public String toString() { 
      return sb.toString();
  }
}
Enno Shioji
A: 

You can use from Apache Commons the StringUtils.join helper. Which allows to build a String from a list. You can add the 'delimiter' character/string.

GandalfIX
+1  A: 

If you are willing to use external libraries, check out the Joiner in Guava.

Your code would go to something like

String result = Joiner.on("\n").join(parts);

where parts is an Iterable<String>.

Carl