Optimize String += or Concat? [duplicate] - java

This question already has answers here:
String concatenation: concat() vs "+" operator
(12 answers)
Closed 9 years ago.
I am writing a file with possibly 1000 data points. I have classes for all of these and am currently writing all of the data at the end (the datapoints are taken at 1s intervals). What I am currently doing is written below, and it's very slow. Would I be better off changing how I am writing the string/bytes to the file? Or would I be better off writing this information to some file pointer as the application is running?
Btw, all of the things such as getAccuracy() and such are floats/ints (so it has to convert those also).
fileStr = "";
fileStr += "timestamp,Accuracy,Altitude,Latitude,Longitude,GPSSatelliteEntries\r\n";
for (Iterator<Entry> i = entries.iterator(); i.hasNext(); ) {
Entry item = i.next();
long ts = item.getTs();
DataEntry d = item.getD();
List<GPSSatelliteEntry> satellites = item.getG();
// write stuff
fileStr += ts + ",";
fileStr += d.getAccuracy() + "," + d.getAltitude() + "," + d.getLatittude() + "," + d.getLongitude() + ",";
fileStr += "[";
boolean entered = false;
for (Iterator<GPSSatelliteEntry> j = satellites.iterator(); j.hasNext(); ) {
GPSSatelliteEntry item2 = j.next();
entered = true;
fileStr += "(" + item2.getAzimuth() + "," + item2.getElevation() + "," + item2.getPrn() + "," + item2.getSnr() + "),";
}
// chop off extra ,
if (entered)
fileStr = fileStr.substring(0, fileStr.length() - 1);
fileStr += "]";
fileStr += "\r\n";
}

Everytime you have hard work with Strings, use StringBuilder or StringBuffer to achieve better performance .
Don't forget that String is immutable, and each time you modify String new instance will be created and it costs performance.

Most probably string buffer
A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified.
or go for string builder

StringBuilder stuff = new StringBuilder();
stuff.append("PUT YOUR STRINGS HERE");
stuff.append("PUT YOUR STRINGS HERE");
Then you can use 'stuff' to print the strings.
Put it in a loop and iterate over a large number with a timer to see the advantages, it's pretty interesting.

Related

Long string concatenation problem in java? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
When I am trying to concatenate strings in Java like so:
COsavedform = vtd + "," + stricode + "," + striname+ ","
+ striqty + "," + strirate + "," + striamt;
every variable containing some String Value and returns correct value of COsavedform but when I add something more to the same COsavedform like..
COsavedform = vtd+","+ccode.getText()+","+striqty
+ "," + strirate + "," + striamt+","+mode+",Customer";
mode is also a string variable. Then it returns only COsavedform=","+mode+",Customer", only not the entire things.
Problem part of that full code_--
System.out.println("striname:"+striname);
System.out.println("stricode:"+stricode);
System.out.println("striqty:"+striqty);
System.out.println("strirate:"+strirate);
System.out.println("striamt"+striamt);
System.out.println("ccode"+ccode.getText());
System.out.println("mode"+mode);
String Csavedform = vtd + "," + stricode + "," + striname+ "," + striqty + "," + strirate + "," + striamt;
System.out.println("CSaved::"+Csavedform);
//System.out.println("COSaved::"+COsavedform);
String Isavedform = vtd+","+ccode.getText()+","+striqty+","+strirate+","+striamt+","+mode+",Customer";
System.out.println("Item savedforitem::"+Isavedform);
```
Output Generated::
vdt:31/12/2019
striname:Kazu
stricode:kazu
striqty:1.0
strirate:1000.0
striamt1000.0
ccode0001
modePending
CSaved::31/12/2019,kazu,Kazu,1.0,1000.0,1000.0
,Pending,Customer
Output Expected::
vdt:31/12/2019
striname:Kazu
stricode:kazu
striqty:1.0
strirate:1000.0
striamt1000.0
ccode0001
modePending
CSaved::31/12/2019,kazu,Kazu,1.0,1000.0,1000.0
Item savedforitem::31/12/2019,0001,1.0,1000.0,1000.0,Pending,Customer
You can use +=
COsavedform += vtd+","+ccode.getText()+","+striqty + "," + strirate + "," + striamt+","+mode+",Customer";
But better to use StringBuilder
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("str1").append("str2")...
COsavedform = stringBuilder.toString();
because its better for memory
Use concat()
Java string concat() method concatenates multiple strings. This method appends the specified string at the end of the given string and returns the combined string. We can use concat() method to join more than one strings
Edited Answer after comment
There are 4 Ways to concatenate String in Java
Concatenation operator (+)
StringBuffer class
StringBuilder class
String.concat() function
Use + operator to concatenate
String stringA= "Stack";
String stringB = "overflow";
String result = stringA + "," + stringB;
System.out.println(result);
By using StringBuilder
StringBuilder result = new StringBuilder();
result.append(stringA).append(",").append(stringB);
System.out.println(result.toString());
By using StringBuffer
StringBuffer result = new StringBuffer();
sBuffer.append(stringA).append(",").append(stringB);
System.out.println(result.toString());

Better string manipulation code

I'm looking for an efficient (one line) string manipulation code to achieve this, regex probably.
I have a string, for example, "Calvin" and I need to convert this to "/C/a/l/Calvin".
i.e. take first three characters, separate them using '/' and later append the original string.
This is the code I've come up with and its working fine, just looking for a better one.
String first = StringUtils.substring(prodName, 0, 1);
String second = StringUtils.substring(prodName, 1, 2);
String third = StringUtils.substring(prodName, 2, 3);
String prodPath = path + "/" + first + "/" + second + "/" + third + "/" + prodName + "/" ;
prodName.replaceAll("^(.)(.)(.).*", "/$1/$2/$3/$0")
What is the point of StringUtils.substring(prodName, 0, 1) when the built-in prodName.substring(0, 1) will do the same thing??
Anyway, assuming prodName is always at least 3 characters long (since you didn't give rules for expected output if it is not), this is the fastest way to do it:
String prodPath = path + '/' +
prodName.charAt(0) + '/' +
prodName.charAt(1) + '/' +
prodName.charAt(2) + '/' +
prodName + '/';
Normally, char + char is integer addition, not string concatenation, but since the first value is a String, and the + operator is left-associative, all + operators are string concatenations, not numeric additions.
How about using String.charAt
StringBuilder b = new StringBuilder (path);
b.append ('/').append (prodName.charAt (0))
.append ('/').append(prodName.charAt (1))
.append ('/').append(prodName.charAt (2))
.append ('/').append (prodName).append ('/');
Don't use regex for simple stuff like this. You may save a couple lines, but you loose a lot in readability. Regex usually take some time to understand when reading them.
String s = path;
for (int i = 0; i < 3; i++)
s += prodName.substring(i,i+1) + "/";
s += prodName
You can use MessageFormat.format()
MessageFormat.format("{0}/{1}/{2}/{3}/{4}/", baseDir, name.charAt(0), name.charAt(1), name.charAt(2), name);
imho i would wrap it for readability,
private String getProductionDirectoryPath(String baseDir, String name) {
return MessageFormat.format("{0}/{1}/{2}/{3}/{4}/", baseDir, name.charAt(0), name.charAt(1), name.charAt(2), name);
}
Positive look ahead can be used
public static void main(String[] args) {
String s = "Calvin";
System.out.println(s.replaceAll("(?=^(\\w)(\\w)(\\w))", "/$1/$2/$3/"));
}
O/P:
/C/a/l/Calvin
No use of a regex, but a simple split over nothing =)
String[] firstThree = prodName.split("");
String prodPath = path + "/" + firstThree[0] + "/" + firstThree[1] + "/" + firstThree[2] + "/" + prodName + "/";
Another approach is using charAt():
String prodPath = path + "/" + prodName.charAt(0) + "/" + prodName.charAt(1) + "/"+ prodName.charAt(2) + "/" + prodName + "/";
You said efficient but you maybe meant terse. I doubt either should be an objective, so you have a different problem.
Why do you care that this string transformation requires four lines of code? Are you concerned that something that in your mind is one operation ("create transformed string") is spread over four Java operations? You should extract the four lines of Java into their own method. Then, when you read the code where the operation is needed you have one conceptual operation ("create transformed string") corresponding to one Java operation (call a method). You could call the methid createTransformedString to make the code even clearer.
You can use String Builder:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 3; i++) {
sb.append("/").append(prodName.charAt(i));
}
sb.append('/').append(prodName);
Or you can put all the code in loop:
int size = 2;
StringBuilder sb = new StringBuilder();
for (int i = 0; i <= size; i++) {
if (i == 0)
sb.append('/');
sb.append(prodName.charAt(i)).append("/");
if (i == size)
sb.append(prodName);
}

StringBuilder vs String (in exact situation) [duplicate]

This question already has answers here:
StringBuilder vs String concatenation in toString() in Java
(20 answers)
Closed 8 years ago.
I've read about StringBuilder class in Java and I'm wondering, what is more efficient way to do some task:
Using "+" concatenation:
String result = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:y=\"http://api.yandex.ru/yaru/\">"
+ "<title>" + (et_title.getText().toString()) + "</title>" +
"<y:access>"+ privacymode +"</y:access>" +
"<category scheme=\"urn:ya.ru:posttypes\" term=\"link\"/>"
+ "<y:meta>" + "<y:url>" + (et_link.getText().toString()) + "</y:url>" +
"</y:meta>" +
"<content>" + signature_select() + "</content>"
+ "</entry>";
or
StringBuilder sb = new StringBuilder();
sb.append( "<?xml version=\"1.0\" encoding=\"utf-8\"?>")
.append("<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:y=\"http://api.yandex.ru/yaru/\">")
.append("<title>")
.append(et_title.getText().toString())
.append("</title>")
.append("<y:access>"+ privacymode +"</y:access>")
.append( "<category scheme=\"urn:ya.ru:posttypes\" term=\"link\"/>")
.append("<y:meta>" + "<y:url>" + (et_link.getText().toString()) + "</y:url>" + "</y:meta>")
.append( "<content>" + signature_select() + "</content>")
.append("</entry>");
String result = sb.toString();
This looks to be worrying about premature optimization. If this is a one-off bit of code and not being called within a tight loop, why worry about optimizing?
Having said that, most often the xml text would be found in a text file and not hard-coded in the program, and then you'll use a loop and a StringBuilder, i.e.,
StringBuilder xmlSb = new StringBuilder();
Scanner xmlScanner = new Scanner(Foo.class.getResourceAsStream(RESOURCE));
while (xmlScanner.hasNextLine()) {
xmlSb.append(xmlScanner.nextLine());
}
if (xmlScanner != null) {
xmlScanner.close();
}
// parse and use your xml text here
Edit: Looks like the Java compiler will optimize the String concatenation (+) version, so both versions will have the same performance, with the advantage to the first one being more readable.
Leaving my previous answer for historic purposes.
Thanks for the comments!
The StringBuilder version is better.
I'd also break the other concatenations you have in the StringBuilder version, like for example:
.append("<y:access>"+ privacymode +"</y:access>")
as:
.append("<y:access>")
.append(privacymode)
.append("</y:access>")
The biggest advantage of using StringBuilder is that you avoid allocating new Strings for each concatenation, whereas StringBuilder will only allocate and resize its internal char array when necessary. It would be even better if you knew the size of the final string. Then you could initialize the StringBuilder with its final size and avoid any extra memory allocation.

java result set only writing one line instead of all selected into .csv

I have a java function that is meant to take strings from jlist called "readyList" and pulling data from mysql workbench tables with the intent to write a line for each string in a .csv file. With the current code it sucessfully pulls the data one at a time like i intended but it only writes the last line instead of all the lines. I want to have all the lines written in the .csv file. Please help!
int[] selectedIx = readyList.getSelectedIndices();
for (int i = 0; i < selectedIx.length; i++) {
// while (i < selectedIx.length) {
Object sel = readyList.getModel().getElementAt(selectedIx[i]);
Statement s1 = DBConnect.connection.createStatement();
String selTable01 = "SELECT Sku As s, Qty As q, Orig_Retail As prce, Orig_Sku As orgsk, Store As strcd "
+ "FROM completed_lines WHERE Form_Name = '" + sel + "' AND Warranty = 'true'";
s1.execute(selTable01);
try (ResultSet rs01 = s1.getResultSet()) {
fWriter = new FileWriter("Exports/Transfers/" + /* frmNm.replace(":", "_") */"EBW_" + GtDates.fdate + ".csv", false);
writer = new BufferedWriter(fWriter);
String header = "slip_number,slip_type,out_store,in_store,item_number,quantity,price,comment,to_num";
writer.write(header);
writer.newLine();
while (rs01.next()) {
String strcode = rs01.getString("strcd");
String sku = rs01.getString("s");
String qty = rs01.getString("q");
String price = rs01.getString("prce");
String orgsku = rs01.getString("orgsk");
//System.out.println(frmNm.split("_")[1] + qty + "," + sku + "," + vendor + "," + desc1 + "," + reas + "," + descdmg + "," + orgR + "," + nwsku + "," + desc2 + "," + qtyI);
String line = ""+","+"out"+","+strcode+","+"RTV"+","+sku+","+qty+","+price+","+"EBW"+","+orgsku;
writer.write(line);
writer.newLine();
}
}
// JOptionPane.showMessageDialog(frame, "All Data from Selected Forms has been Exported");
}
// FormCompelted();
writer.close();
}
}
A few issues with this code. The reason you're only getting the last result is because of this line:
fWriter = new FileWriter("Exports/Transfers/" + /* frmNm.replace(":", "_") */"EBW_" + GtDates.fdate + ".csv", false);
This line is inside your loop. The false as the last parameter tells FileWriter not to append. In other words, a false means overwrite the file if it exists. Since this is in your loop, each result overwrites the file that the last result created. You should create the FileWriter outside of your loop, probably in a try with resources. That will allow you to remove your writer.close() call, which should have been in a finally block anyway.
Not related to your original question but something you should be aware of: You're creating a new Statement with each loop iteration. This can be an expensive operation. You should use a PreparedStatement instead. Create it outside your loop and then just set the parameter and execute it inside the loop. It also implements AutoCloseable, so you can create it in a try with resources too, probably the same one you create your FileWriter in.

How to split String by taking space's in java

I know its very easy to split data in strings, but still i want guide to concate string,
my data is in the format. In my string the data is in the above format
104
inNetStandardGuest
windowsGuest
uestToolsTooOld
121
slesGuest
guestToolsTooOld
20569355609
Expected Output:
104,inNetStandardGuest,windowsGuest,uestToolsTooOld
121,slesGuest,guestToolsTooOld,20569355609
It's simply splitting and combining strings.
StringBuilder out = new StringBuilder();
for (String set : data.split("\n\n\n")) {
for (String line : set.split("\n")) {
out.append(line).append(',');
}
out.setCharAt(out.length(), '\n');
}
System.out.println(out);
With Guava's Splitter and Joiner:
final Iterable<String> lines = Splitter.on("\n\n\n").split(input);
for (final String line : lines) {
final Iterable<String> fields = Splitter.on("\n").split(line);
final String joined = Joiner.on(",").join(fields);
}
How about this?
String s = "104\n" +
"inNetStandardGuest\n" +
"windowsGuest\n" +
"uestToolsTooOld\n" +
"\n" +
"\n" +
"121\n" +
"slesGuest\n" +
"guestToolsTooOld\n" +
"20569355609\n";
System.out.println(s.replaceAll("(.)\\n","$1,")
.replaceAll(",,","\n")
.replaceAll(",\\n","\n"));
Probably not the most efficient way, though.
Buffered reader:
http://docs.oracle.com/javase/1.4.2/docs/api/java/io/BufferedReader.html
readLine() method:
http://docs.oracle.com/javase/1.4.2/docs/api/java/io/BufferedReader.html#readLine()
For example you read 4 lines
string outputLine = line1 + "," + line2 + "," + line3 + "," + line4;
Then read 2 lines and skip it.
If you don't know how to implement it using my advices, you should read
some basics tutorial.
Try this :
String str = "104\ninNetStandardGuest\nwindowsGuest\nuestToolsTooOld\n\n\n121\nslesGuest\nguestToolsTooOld\n20569355609";
str= str.replaceAll("\\s", ",").replaceAll(",,,", "\n");
System.out.println(str);
Output :
104,inNetStandardGuest,windowsGuest,uestToolsTooOld
121,slesGuest,guestToolsTooOld,20569355609

Categories