I am very new to lambda. Can someone please help in converting following nested loops in lambda -
for (Question question : questionList) {
formattedText += NEW_LINE + localizeString(QUESTION_STRING_ID) + question.getQuestionText();
formattedText += NEW_LINE + localizeString(ANSWER_STRING_ID);
for (Answer answer : question.getAnswers()) {
formattedText += answer.getAnswerText() + NEW_LINE;
}
}
Solution I tried
for (Question question : questionList) {
formattedText += NEW_LINE + localizeString(QUESTION_STRING_ID) + question.getQuestionText();
formattedText += NEW_LINE + localizeString(ANSWER_STRING_ID);
question.getAnswers().forEach(answer -> {formattedText += answer.getAnswerText() + NEW_LINE;});
}
Not sure how can I convert both loops into single lambda expression? Also, this solution is not working since it needs formattedText to be declared as final.
It may be implemented using Collectors.joining collector of Stream API:
String prefixQ = NEW_LINE + localizeString(QUESTION_STRING_ID);
String suffixQ = NEW_LINE + localizeString(ANSWER_STRING_ID);
String result = questionList.stream()
.map(q ->
prefixQ + q.getQuestionText() + suffixQ
+ q.getAnswers().stream()
.map(Answer::getAnswerText)
.collect(Collectors.joining(NEW_LINE))
)
.collect(Collectors.joining(NEW_LINE));
You're looking for a Collector. For example,
for (Question question : questionList) {
formattedText += NEW_LINE + localizeString(QUESTION_STRING_ID) + question.getQuestionText();
formattedText += NEW_LINE + localizeString(ANSWER_STRING_ID);
formattedText +=
question.getAnswers()
.stream()
.map(Answer::getAnswerText)
.collect(Collectors.joining(NEW_LINE));
formattedText += NEW_LINE;
}
That supposes that NEW_LINE represents a String. If instead it is a character then you could use String.valueOf(NEWLINE) as the argument to Collectors.joining().
Do note, however, that there is not actually any lambda in that at all. The one place where one might have been used, I use a method reference instead.
Related
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());
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);
}
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.
I have a string that is built out of three parts. The word I want the string to be (changes), a seperating part (doesn't change) and the last part which changes. I want to delete the seperating part and the ending part. The seperating part is " - " so what I'm wondering is if theres a way to delete everything after a certaint part of the string.
An example of this scenario would be if I wanted to turn this: "Stack Overflow - A place to ask stuff" into this: "Stack Overflow". Any help is appreciated!
For example, you could do:
String result = input.split("-")[0];
or
String result = input.substring(0, input.indexOf("-"));
(and add relevant error handling)
The apache commons StringUtils provide a substringBefore method
StringUtils.substringBefore("Stack Overflow - A place to ask stuff", " - ")
Kotlin Solution
Use the built-in Kotlin substringBefore function (Documentation):
var string = "So much text - no - more"
string = string.substringBefore(" - ") // "So much text"
It also has an optional second param, which is the return value if the delimiter is not found. The default value is the original string
string.substringBefore(" - ", "fail") // "So much text"
string.substringBefore(" -- ", "fail") // "fail"
string.substringBefore(" -- ") // "So much text - no - more"
You can use this
String mysourcestring = "developer is - development";
String substring = mysourcestring.substring(0,mysourcestring.indexOf("-"));
it would be written "developer is -"
Perhaps thats what you are looking for:
String str="Stack Overflow - A place to ask stuff";
String newStr = str.substring(0, str.indexOf("-"));
I created Sample program for all the approches and SubString seems to be fastest one.
Using builder : 54
Using Split : 252
Using Substring : 10
Below is the sample program code
for (int count = 0; count < 1000; count++) {
// For JIT
}
long start = System.nanoTime();
//Builder
StringBuilder builder = new StringBuilder(
"Stack Overflow - A place to ask stuff");
builder.delete(builder.indexOf("-"), builder.length());
System.out.println("Using builder : " + (System.nanoTime() - start)
/ 1000);
start = System.nanoTime();
//Split
String string = "Stack Overflow - A place to ask stuff";
string.split("-");
System.out.println("Using Split : " + (System.nanoTime() - start)
/ 1000);
//SubString
start = System.nanoTime();
String string1 = "Stack Overflow - A place to ask stuff";
string1.substring(0, string1.indexOf("-"));
System.out.println("Using Substring : " + (System.nanoTime() - start)
/ 1000);
return null;
Clean way to safely remove until a string, and keep the searched part if token may or may not exist.
String input = "Stack Overflow - A place to ask stuff";
String token = " - ";
String result = input.contains(token)
? token + StringUtils.substringBefore(string, token)
: input;
// Returns "Stack Overflow - "
Apache StringUtils functions are null-, empty-, and no match- safe
This will do what you need:
newValue = oldValue.substring(0, oldValue.indexOf("-");
String line = "deltaasm:/u01/app/oracle/product/11.2.0/dbhome_1:N # line addred by agent";
String rep = "deltaasm:";
String after = "";
String pre = ":N";
String aft = "";
String result = line.replaceAll(rep, after);
String finalresult = result.replaceAll(pre, aft);
System.out.println("Result***************" + finalresult);
String str = "deltaasm:/u01/app/oracle/product/11.2.0/dbhome_1:N # line addred by agent";
String newStr = str.substring(0, str.indexOf("#"));
System.out.println("======" + newStr);
you can my utils method this action..
public static String makeTwoPart(String data, String cutAfterThisWord){
String result = "";
String val1 = data.substring(0, data.indexOf(cutAfterThisWord));
String va12 = data.substring(val1.length(), data.length());
String secondWord = va12.replace(cutAfterThisWord, "");
Log.d("VAL_2", secondWord);
String firstWord = data.replace(secondWord, "");
Log.d("VAL_1", firstWord);
result = firstWord + "\n" + secondWord;
return result;
}`
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