I'm using StringBuffer in Java to concat strings together, like so:
StringBuffer str = new StringBuffer();
str.append("string value");
I would like to know if there's a method (although I didn't find anything from a quick glance at the documentation) or some other way to add "padding".
Let me explain; every time I append something to the string, I want to add a space in the end, like so:
String foo = "string value";
str.append(foo + " ");
and I have several calls to append.. and every time, I want to add a space. Is there a way to set the object so that it will add a space automatically after each append?
EDIT --
String input
StringBuffer query = new StringBuffer();
Scanner scanner = new Scanner(System.in);
scanner.UseDelimiter("\n");
do {
System.out.println("sql> ");
input = scanner.next();
if (!empty(input)) query.append(input);
if (query.toString().trim().endsWith(";")) {
//run query
}
}
while (!input.equalsIgnoreCase("exit");
I'll use StringBuilder though as grom suggested, but that's how the code looks right now
I think this is handled easier either with a helper method (untested code):
public String myMethod() {
StringBuilder sb = new StringBuilder();
addToBuffer(sb, "Hello").addToBuffer("there,");
addToBuffer(sb, "it").addToBuffer(sb, "works");
}
private StringBuilder addToBuffer(StringBuilder sb, String what) {
return sb.append(what).append(' '); // char is even faster here! ;)
}
Or even using a Builder pattern with a fluent interface (also untested code):
public String myMethod() {
SBBuilder builder = new SBBuilder()
.add("Hello").add("there")
.add("it", "works", "just", "fine!");
for (int i = 0; i < 10; i++) {
builder.add("adding").add(String.valueOf(i));
}
System.out.println(builder.build());
}
public static class SBBuilder {
private StringBuilder sb = new StringBuilder();
public SBBuilder add(String... parts) {
for (String p : parts) {
sb.append(p).append(' '); // char is even faster here! ;)
}
return this;
}
public String build() {
return sb.toString();
}
}
Here's an article on the subject.
Hope it helps! :)
You should be using StringBuilder.
Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.
StringBuffer is final. You cannot derive from it.
The Best solution really is to add the padding for yourself. Write a method for it and use a PADDING-Constant so that you can easily change it, or better put it in a parameter.
Can you not create a new class which wraps around StringBuffer and add an appendWithTrailingSpace() method?
CustomStringBuffer str = new CustomStringBuffer();
str.appendWithTrailingSpace("string value");
(Although you may want to call your method something a little shorter.)
Just add the space yourself, it's easy enough, as per your own example.
Another possibility is that StringBuilder objects return themselves when you call append, meaning you can do:
str.append("string value").append(" ");
Not quite as slick, but it is probably an easier solution than the + " " method.
Another possibility is to build a wrapper class, like PaddedStringBuilder, that provides the same methods but applies the padding you want, since you can't inherit.
Related
public class Main
{
public static void main(String[] args) {
StringBuilder string = new StringBuilder("abb");
StringBuilder stringReverse = string.reverse();
if(string.toString().equals(stringReverse.toString())){
System.out.println(true);
return;
}
System.out.println(false);
}
}
See this code run live at IdeOne.com.
I get the output of the above code as 'true'. But the reversed string is 'bba'. How is 'bba' equal to 'abb'? Please could someone help me with this?
StringBuilder#reverse() reverses the text in the StringBuilder itself (and returns the same). Print out the values held by string and stringReverse to see for yourself:
System.out.println("string: " + string);
System.out.println("stringReverse: " + stringReverse);
returns
string: bba
stringReverse: bba
Even more importantly, the API for StringBuilder tells you this:
Causes this character sequence to be replaced by the reverse of the sequence.
Also, the string and stringReverse are one and the same object, in other words, this:
System.out.println("stringReverse == string: " + (stringReverse == string));
will print out true
reverse() returns the same object (not a new StringBuilder).
Your code:
StringBuilder string = new StringBuilder("abb");
StringBuilder stringReverse = string.reverse();
is identical to:
StringBuilder string = new StringBuilder("abb");
string.reverse();
StringBuilder stringReverse = string; // Same object!
As StringBuilder is mutable, when you are calling reverse you are actually reversing the original StringBuilder.
Try
StringBuilder string = new StringBuilder("abb");
StringBuilder stringReverse = new StringBuilder(string).reverse();
System.out.println(string.toString());
System.out.println(stringReverse.toString());
The first three Answers are correct. One of them should be accepted. I will add one small thought about the importance of naming.
Naming can confuse or clarify
This Question is an example of how poor naming can lead you astray.
Naming your first StringBuilder with the word string leads one to think of that var as referencing a mutable String object when in fact it references a mutable StringBuilder. Naming something like firstStringBuilder would avoid this problem of being easy to misread.
StringBuilder string = new StringBuilder("abb");
// ^^^^^^ No, this is not an immutable `String` object reference.
Alternate naming clarifies.
StringBuilder firstStringBuilder = new StringBuilder( "abb" );
StringBuilder reversedStringBuilder = firstStringBuilder.reverse(); // Both vars ( `firstStringBuilder` & `reversedStringBuilder` ) reference the very same single `StringBuilder` object.
if( firstStringBuilder.toString().equals( reversedStringBuilder.toString() ) ){
System.out.println( "firstStringBuilder & reversedStringBuilder are equal because they both point to the very same single StringBuilder object. So the result of calling `.toString` twice on the same object is the same." );
return;
}
System.out.println( "Not equal" );
See this code run live at IdeOne.com.
firstStringBuilder & reversedStringBuilder are equal because they both point to the very same single StringBuilder object. So the result of calling .toString twice on the same object is the same.
I was wondering the execution speed changes if a programmer concatenates inside a Stringbuilder append() statement, or just uses two append statements instead of one.
I am asking this question to help me figure out why we use the StringBuilder class at all when we can just concatenate.
Concatenation Example:
public class MCVE {
public static void main(String[] args) {
String[] myArray = {"Some", "stuff", "to", "append", "using", "the",
"StringBuilder", "class's", "append()", "method"};
StringBuilder stringBuild = new StringBuilder();
for(String s: myArray) {
stringBuild.append(s + " ");
}
}
}
Double-Append() Example:
public class MCVE {
public static void main(String[] args) {
String[] myArray = {"Some", "stuff", "to", "append", "using", "the",
"StringBuilder", "class's", "append()", "method"};
StringBuilder stringBuild = new StringBuilder();
for(String s: myArray) {
stringBuild.append(s);
stringBuild.append(" ");
}
}
}
In theory, yes, the concatenation version will take longer, because under the covers it creates a whole new StringBuilder, appends s, appends " ", and then uses toString to create(!) a string for that to pass to the append you coded. (That's what the compiler does. To know about your specific situation, you'd need to test a benchmark representative of your actual code. After all, the JIT will get involved if it's a hotspot at runtime.)
Of course, you probably won't notice. But still, if you're already using StringBuilder, use it (by doing append twice instead). :-)
(The first paragraph above wouldn't be true if they were both string literals, e.g. "foo" + "bar". The compiler does that concatenation.)
System throws error builder cannot be resolved in the java program:- in the lines String result = builder.toString(); and builder.append("abc");
package newprojectstring;
import java.lang.StringBuilder;
public class MyOwnClass {
public static void main(String[] args) {
// Loop and append values.
for (int i = 0; i < 5; i++) {
MyOwnClass Builder = new MyOwnClass();
builder.append("abc");
}
// Convert to string.
String result = builder.toString();
System.out.println(result);
}
}
First of all, never name your own classes with names similar to the names of the classes from the standard Java libraries. If you do this, you will always get tons of errors and everyone who reads your code will curse you.
Next, you want to use the standard StringBuilder from the java.lang package, but actually you try to use an instance of your own Stringbuilder class that does not contain append() method. StringBuilder and Stringbuilder are different things, from the Java's point of view. If you would not name your class Stringbuilder, you would see your mistake while you was writing it in your IDE.
Rewrite your code as follows:
public class MyOwnClass { // *** Not 'Stringbuilder'!!!
public static void main(String[] args) {
// Create a new StringBuilder
StringBuilder builder = new StringBuilder(); // *** Not 'Stringbuilder' !!!
// Loop and append values.
for (int i = 0; i < 5; i++) { // Use spaces properly
builder.append("abc");
}
// Convert to string.
String result = builder.toString();
System.out.println(result);
}
}
When you write builder.append("abc");, java is going to look for the class represented by reference named builder which in this case is your custom class Stringbuilder. Then it will look for a method append with a String argument, which it won't find, because you haven't defined a method like that.
Now there is a predefined StringBuilder which is having a method named append. I think you are confused with it. If you want to call the append method of StringBuilder you have to make a reference of StringBuilder.
Stringbuilder builder = new Stringbuilder();
builder.append("abc");
I need a advice (both in java & .net) for the following piece of code.
public void method(bool value)
{
String someString;
//some code
if (value)
{
//some code
...
someString = "one" + value;
}
else
{
//some code
...
someString = "two" + value;
}
}
Which one is advisable and why? either code like above or code like
someString = "onetrue";
someString = "twofalse";
After compilation and optimization by JDK, method will look like:
public static String method(boolean value) {
String someString;
if (value) {
StringBuilder sb = new StringBuilder();
sb.append("one");
sb.append(value);
someString = sb.toString();
} else {
StringBuilder sb = new StringBuilder();
sb.append("two");
sb.append(value);
someString = sb.toString();
}
return someString;
}
If this code is invoked very frequently, it could bring a performance impact, compared to the second version. In each case a new StringBuilder is constructed and three methods are invoked on it. And boolean should be converted to an object before calling append. While in the second version we just return constant. Everything depends on how often this code is called.
Neither will make any difference it's purely style.
Since you have // some other code I'd just stick with the first. If you only had one line in each branch then either is ok.
At a high level they both are the same but if you look down at lower levels, I would advise to using the method:
someString = "onetrue";
someString = "twofalse";
This is because when you do "one" + value, the value is actually a bool and the toString() method of the bool object will be called to add to the string. Basically just adding another step opposed to just specifying what to add to the string.
This is the piece of code.
List<BDDObject> childlist = savingObject.getChildren("TherapyAreaReference");
if (childlist.size() > 1) {
for (int i = 0; i < childlist.size() - 1; i++) {
String newMedcondRefChild = ((String) childlist
.get(i)
.getValue( IDDConstants.IDD_THERAPY_AREA_REF_VALUE))
.toLowerCase()
.trim()
.concat(((String) childlist
.get(i)
.getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME))
.toLowerCase().trim());
}
}
IDDConstants has public static final strings defined in it. As StringBuffer is more effective, how can it be incorporated for the concat operations?
I'm guessing that the intention is to generate a list of 'reports', one for each BDDObject record found. Based on that idea, your code should look more like this:
public List<String> getReport(List<BDDObject> records) {
List<String> reports = new ArrayList<String>(record.size());
for (BDDObject record:records) {
String newMedcondRefChild = String.valueOf(record.getValue( IDDConstants.IDD_THERAPY_AREA_REF_VALUE))
.toLowerCase()
.trim() + String.valueOf(record.getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME)))
.toLowerCase().trim());
reports.add(newMedcondRefChild);
}
return reports;
}
Regarding the question on whether toString() would be helpful, the only place where I see it fitting, would be on the BDDObject itself. It would look something like this:
class BDDObject {
...
#Override
public String toString() {
return String.valueOf(getValue(IDDConstants.IDD_THERAPY_AREA_REF_VALUE)).toLowerCase().trim() +
String.valueOf(getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME)).toLowerCase().trim());
}
In which case, the function to create the report becomes trivial:
public List<String> getReport(List<BDDObject> records) {
List<String> reports = new ArrayList<String>(record.size());
for (BDDObject record:records) {
reports.add(record.toString());
}
return reports;
}
In case that what you want is a looooong string with all the values concatenated to it, you can use StringBuilder, like this:
public String getReport(List<BDDObject> records) {
StringBuilder sb = new StringBuilder();
for (BDDObject record:records) {
sb.append(String.valueOf(record.getValue( IDDConstants.IDD_THERAPY_AREA_REF_VALUE))
.toLowerCase()
.trim());
sb.append(String.valueOf(record.getValue(IDDConstants.IDD_THERAPY_AREA_REF_TYPE_NAME))
.toLowerCase().trim()));
}
return sb.toString();
}
This will return all the records appended after each other. I doubt its readability, but you I hope you get the idea. StringBuilder is helpful when you need to build a string iteratively (like in the previous example). StringBuilder should not be used to replace single String operations like : String a = b.get() + c.get(); given that the compiler implicitly creates a StringBuilder in these cases and therefore there's no actual performance improvement to be achieved.
In the code in your question, StringBuffer/StringBuilder will not give you any performance gains, because you concatenate only two strings. However, the question does not state what you are doing with the string in newMedconfRefChild. If your actual goal is to concatenate the strings of each loop iteration, then you should use a StringBuilder (use StringBuffer only when it is really necessary, prefer StringBuilder).