I want write to console tree in java in recusive function, one of parameter is depth of tree and I wanna use it for number of tabulators before node names.
public void print(TreeNode node, int depth)
//something ...
String prefix = "";
for(int i = 0; i <depth; i++) {
prefix += "\t";
}
//....
List<TreeNode> subnodes = node.getNodes();
for(int i = 0; i < subnodes.size(); i++) {
System.out.println(prefix+ subnodes.get(i).getTitle()); //title is name of node;
}
}
Is any better solution for string concatenation for prefix then do it by for?
For example I wanna do 2x "\t" which mean "\t\t" if 2 = depth. If depth is variable I wanna do depth x "\t";
My solution is use for but is there any better for this simple thing?
You may want to change your program in order to use StringBuilder class:
StringBuilder prefix = new StringBuilder();
for (int i = 0; i < depth, ++i) {
prefix.append("\t");
}
....
System.out.println(prefix.toString() + subnodes.get(i).getTitle());
String in Java is immutable and that's why when you modify it, acually new copy of String is created. If your tree is really big and deep (or tall :) - StringBuilder should work faster and consume less memory.
If for loop is a problem, you may consider such solutions as storing map of depth level -> pre-calculated prefix like this:
Map<Integer, String> prefixes = new HashMap<Integer, String>();
private void fillPrefixes(int maxTreeDepth) {
StringBuilder prefix = new StringBuilder();
for (int i = 0; i < maxTreeDepth; ++i) {
prefixes.put(i, prefix.toString());
prefix.append("\t");
}
}
This may be useful for the cases of huge trees, when you really recalculate that prefix over 9000 times. Technically, for loop is still there, but you do not recalculate prefix each time you need it. Another side of the coin is increased memory consumption. So, to make a right decision you need to avoid premature optimizations and do it only when you really need it, and also decide what is more critical - memory or execution time.
You may use Apache Commons Lang for that.
Maven dependency for it:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
And sample usage:
import org.apache.commons.lang.StringUtils
...
prefix = StringUtils.repeat("\t", depth);
Related
//I tried this one but output was wrong for tenth term
import java.io.*;
public class series
{
public static void main(String args[])throws IOException
{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int n,i,i1=0,s=0,c=0;
System.out.println("Enter the term of the series you want to get");
n=Integer.parseInt(in.readLine());
for (i=1;i<=n;i++)
{
i1=i;
while (i1!=0)
{
c+=1;
i1=i1/10;
}
s=(int)(s*(Math.pow(10,c))+i);
c=0;
System.out.print(s+" ");
}
}
}
I don't know why you are using your current approach. I would go about this by keeping track of the previous term which was printed.
StringBuilder term = new StringBuilder("");
final int N = 20;
for (int i=1; i <= N; ++i) {
term.append(i);
if (i > 1) System.out.print(",");
System.out.print(term.toString());
}
Demo
Edit: The reason I suggest using a string to display each term is that your requirement appears to mainly be one of presentation. That is, you're not actually doing any math with each term, so why not just avoid a numeric type completely, which also avoids things like overflow and potential loss of precision.
Whilst Tim's answer is neat, I think that the exercise is sufficiently basic that StringBuilder is beyond its scope (*).
Instead, you can use a nested for loop:
final int N = 20;
for (int i=1; i <= N; ++i) {
if (i > 1) System.out.print(",");
for (int a = 1; a <= i; ++a) {
System.out.print(a);
}
}
(This is also going to be more memory efficient, since there is no need to keep reallocating the StringBuffer's internal buffer as i increases. But this is really of secondary (or even lesser) concern).
(*) Yes, you could do the same without StringBuilder, just using String concatenation; but that would be inefficient in ways that beginners may not "get", and so it is something that is best just steered around. Nested loops are far more generally useful than string concatenation in whatever form as a concept to get your head around.
The main reason you are getting wrong output after 10th term is Integer Overflow. You can use long to get rid of that to certain more terms but a definitely better solution is as answered using Strings
I'm learning Java and am wondering what's the best way to modify strings here (both for performance and to learn the preferred method in Java). Assume you're looping through a string and checking each character/performing some action on that index in the string.
Do I use the StringBuilder class, or convert the string into a char array, make my modifications, and then convert the char array back to a string?
Example for StringBuilder:
StringBuilder newString = new StringBuilder(oldString);
for (int i = 0; i < oldString.length() ; i++) {
newString.setCharAt(i, 'X');
}
Example for char array conversion:
char[] newStringArray = oldString.toCharArray();
for (int i = 0; i < oldString.length() ; i++) {
myNameChars[i] = 'X';
}
myString = String.valueOf(newStringArray);
What are the pros/cons to each different way?
I take it that StringBuilder is going to be more efficient since the converting to a char array makes copies of the array each time you update an index.
I say do whatever is most readable/maintainable until you you know that String "modification" is slowing you down. To me, this is the most readable:
Sting s = "foo";
s += "bar";
s += "baz";
If that's too slow, I'd use a StringBuilder. You may want to compare this to StringBuffer. If performance matters and synchronization does not, StringBuilder should be faster. If sychronization is needed, then you should use StringBuffer.
Also it's important to know that these strings are not being modified. In java, Strings are immutable.
This is all context specific. If you optimize this code and it doesn't make a noticeable difference (and this is usually the case), then you just thought longer than you had to and you probably made your code more difficult to understand. Optimize when you need to, not because you can. And before you do that, make sure the code you're optimizing is the cause of your performance issue.
What are the pros/cons to each different way. I take it that StringBuilder is going to be more efficient since the convering to a char array makes copies of the array each time you update an index.
As written, the code in your second example will create just two arrays: one when you call toCharArray(), and another when you call String.valueOf() (String stores data in a char[] array). The element manipulations you are performing should not trigger any object allocations. There are no copies being made of the array when you read or write an element.
If you are going to be doing any sort of String manipulation, the recommended practice is to use a StringBuilder. If you are writing very performance-sensitive code, and your transformation does not alter the length of the string, then it might be worthwhile to manipulate the array directly. But since you are learning Java as a new language, I am going to guess that you are not working in high frequency trading or any other environment where latency is critical. Therefore, you are probably better off using a StringBuilder.
If you are performing any transformations that might yield a string of a different length than the original, you should almost certainly use a StringBuilder; it will resize its internal buffer as necessary.
On a related note, if you are doing simple string concatenation (e.g, s = "a" + someObject + "c"), the compiler will actually transform those operations into a chain of StringBuilder.append() calls, so you are free to use whichever you find more aesthetically pleasing. I personally prefer the + operator. However, if you are building up a string across multiple statements, you should create a single StringBuilder.
For example:
public String toString() {
return "{field1 =" + this.field1 +
", field2 =" + this.field2 +
...
", field50 =" + this.field50 + "}";
}
Here, we have a single, long expression involving many concatenations. You don't need to worry about hand-optimizing this, because the compiler will use a single StringBuilder and just call append() on it repeatedly.
String s = ...;
if (someCondition) {
s += someValue;
}
s += additionalValue;
return s;
Here, you'll end up with two StringBuilders being created under the covers, but unless this is an extremely hot code path in a latency-critical application, it's really not worth fretting about. Given similar code, but with many more separate concatenations, it might be worth optimizing. Same goes if you know the strings might be very large. But don't just guess--measure! Demonstrate that there's a performance problem before you try to fix it. (Note: this is just a general rule for "micro optimizations"; there's rarely a downside to explicitly using a StringBuilder. But don't assume it will make a measurable difference: if you're concerned about it, you should actually measure.)
String s = "";
for (final Object item : items) {
s += item + "\n";
}
Here, we're performing a separate concatenation operation on each loop iteration, which means a new StringBuilder will be allocated on each pass. In this case, it's probably worth using a single StringBuilder since you may not know how large the collection will be. I would consider this an exception to the "prove there's a performance problem before optimizing rule": if the operation has the potential to explode in complexity based on input, err on the side of caution.
Which option will perform the best is not an easy question.
I did a benchmark using Caliper:
RUNTIME (NS)
array 88
builder 126
builderTillEnd 76
concat 3435
Benchmarked methods:
public static String array(String input)
{
char[] result = input.toCharArray(); // COPYING
for (int i = 0; i < input.length(); i++)
{
result[i] = 'X';
}
return String.valueOf(result); // COPYING
}
public static String builder(String input)
{
StringBuilder result = new StringBuilder(input); // COPYING
for (int i = 0; i < input.length(); i++)
{
result.setCharAt(i, 'X');
}
return result.toString(); // COPYING
}
public static StringBuilder builderTillEnd(String input)
{
StringBuilder result = new StringBuilder(input); // COPYING
for (int i = 0; i < input.length(); i++)
{
result.setCharAt(i, 'X');
}
return result;
}
public static String concat(String input)
{
String result = "";
for (int i = 0; i < input.length(); i++)
{
result += 'X'; // terrible COPYING, COPYING, COPYING... same as:
// result = new StringBuilder(result).append('X').toString();
}
return result;
}
Remarks
If we want to modify a String, we have to do at least 1 copy of that input String, because Strings in Java are immutable.
java.lang.StringBuilder extends java.lang.AbstractStringBuilder. StringBuilder.setCharAt() is inherited from AbstractStringBuilder and looks like this:
public void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
value[index] = ch;
}
AbstractStringBuilder internally uses the simplest char array: char value[]. So, result[i] = 'X' is very similar to result.setCharAt(i, 'X'), however the second will call a polymorphic method (which probably gets inlined by JVM) and check bounds in if, so it will be a bit slower.
Conclusions
If you can operate on StringBuilder until the end (you don't need String back) - do it. It's the preferred way and also the fastest. Simply the best.
If you want String in the end and this is the bottleneck of your program, then you might consider using char array. In benchmark char array was ~25% faster than StringBuilder. Be sure to properly measure execution time of your program before and after optimization, because there is no guarantee about this 25%.
Never concatenate Strings in the loop with + or +=, unless you really know what you do. Usally it's better to use explicit StringBuilder and append().
I'd prefer to use StringBuilder class where original string is modified.
For String manipulation, I like StringUtil class. You'll need to get Apache commons dependency to use it
The question is about while-loops in which I need some code to be executed N times and some other code N+1 times. NOT about concatening Strings, I just use this as bad-coded yet short example.
Let me explain my question by providing an example.
Say I want to concatenate N+1 Strings, by glueing them with "\n", for example. I will have N+1 lines of text then, but I only need to add N times "\n".
Is there any boilerplate solution for this type of loop in which you have to execute some code N times and other code N+1 times? I'm NOT asking for solution to concatenate Strings! That is just a (bad) example. I'm looking for the general solution.
The problem I have with this is code duplication, so to code my example I'll do this (bad pseudo code, I know I have to use StringBuilder etc.):
String[] lines = <some array of dimension N+1>;
String total = lines[0];
for (int i = 1; i < N + 1; i++){
total += "\n" + lines[i];
}
The problem becomes worse if the code that has to be executed N+1 times, becomes larger, of course. Then I would do something like
codeA(); // adding the line of text
for (int i = 1; i < N + 1; i++){
codeB(); // adding the "\n"
codeA();
}
To remove the duplication, you can do this different by checking inside the loop, too, but then I find this quite stupid as I know beforehand that the check is pre-determined, as it will only be false the first iteration:
for (int i = 0; i < N + 1; i++){
if (i > 0){
codeB(); // adding the "\n"
}
codeA();
}
Is there any solution for this, a sort of while-loop that initializes once with codeA() en then keeps looping over codeB() and codeA()?
People must have run into this before, I guess. Just wondering if there are any beautiful solutions for this.
To my dissapointment, I believe that there is no such construct that satisfies the conditions as you have stated them and I will attempt to explain why (though I can't prove it in a strictly mathematical way).
The requirements of the problem are:
We have two parts of code: codeA() and codeB()
The two parts are executed a different number of times, N and N+1
We want to avoid adding a condition inside the loop
We want to execute each part only as many times as strictly necessary
2) is a direct consequence of 1). If we didn't have two parts of code we would not need a different number of executions. We would have a single loop body.
4) is again a consequence of 1). There is no redundant execution if we have a single loop body. We can control its execution through the loop's condition
So the restrictions are basically 1) and 3).
Now inside the loop we need to answer two questions on each iteration: a) do we execute codeA()? and b) do we execute codeB()? We simply do not have enough information to decide since we only have a single condition (the condition of the loop) and that condition will be used to decide if both of the code parts would be executed or not.
So we need to break 1) and/or 3) Either we add the extra condition inside the loop or we delegate the decision to some other code (thus not having two parts anymore).
Apparently an example of delegation could be (I am using the string concatenation example):
String [] lines = ...
for (int i = 0; i < N; i++){
// delegate to a utility class LineBuilder (perhaps an extension of StringBuilder) to concatenate lines
// this class would still need to check a condition e.g. for the first line to skip the "\n"
// since we have delegated the decisions we do not have two code parts inside the loop
lineBuilder.addLine( lines[i] );
}
Now a more interesting case of delegation would be if we could delegate the decision to the data itself (this might worth keeping in mind). Example:
List<Line> lines = Arrays.asList(
new FirstLine("Every"), // note this class is different
new Line("word"),
new Line("on"),
new Line("separate"),
new Line("line") );
StringBuffer sb = new StringBuffer();
for (Line l : lines) {
// Again the decision is delegated. Data knows how to print itself
// Line would return: "\n" + s
// FirstLine would return: s
sb.append( l.getPrintVersion() );
}
Of course all of the above does not mean that you couldn't implement a class that tries to solve the problem. I believe though this is beyond the scope of your original question not to mention that would be an overkill for simple loops
Concatenating Strings like this is a bad idea and a much bigger issue IMHO.
However to answer your question I would do
String sep = "";
StringBuilder sb= new StringBuilder();
for(String s: lines) {
sb.append(sep).append(s);
sep = "\n";
}
String all = sb.toString();
Note: there is usually a good way to avoid needing to create this String at all such a processing the lines as you get them. It is hard to say without more context.
This kind of thing is fairly common, like when you build sql. This is the pattern that I follow:
String[] lines ...//init somehow;
String total = lines[0];
boolean firstTime = true;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++){
if(firstTime) firstTime = false;
else sb.append('\n');
sb.append(lines[i]);
}
Note that this is not the same, as the first example and here is why:
String[] lines = <some array of dimension N+1>;
String total = lines[0];
for (int i = 1; i < N + 1; i++){
total += "\n" + lines[i];
}
Assuming you have an array of [0] = 'line1' and [1] = 'line2'
Here you end up with line1line2\n, when the desired output is:
line1\nline2.
The example I provided is clear, and does not perform poorly. In fact a much bigger performance gain is made by utilizing StringBuilder/Buffer. Having clear code is essential for the pro.
Personally i have most of the time the same problem, on the String example i use the StringBuilder as you said, and just delete the characters added to much:
StringBuilder sb = new StringBuilder();
for(int i=0; i<N; i++) {
sb.append(array[i]).append("\n");
}
sb.delete(sb.length-1, sb.length); // maybe check if sb contains something
In the common case i suppose there is no other way than adding the if you suggested. To make the code more clear i would check at the end of the for loop:
StringBuilder sb = new StringBuilder();
for(int i=0; i<N; i++) {
sb.append(array[i]);
if(i < N) {
sb.append("\n");
}
}
But i totally agree this is sad to have this double logic
I need to convert a string vector in a simple string. I do not know how to proceed.
I tried various solutions such as
for(int i=1; i < easy.length; i++){
easyPuzzle = easy[i].toString();
}
System.out.println(" " + easyPuzzle);
but this solution prints only the ith element and not the entire string vector.
Use toString in Arrays class
Arrays.toString(easy);
You keep reassign a new value to easyPuzzle when you really want to concatenate:
easyPuzzle += easy[i].toString();
If easy.length is large, it might make sense to use a StringBuilder which is more efficient at concatenating than String:
StringBuilder builder = new StringBuilder();
for(int i=1; i < easy.length; i++){
builder.append(easy[i].toString());
}
easyPuzzle = builder.toString();
Also by starting your for loop at i=1 you exclude the first item. Not sure if it is on purpose or not. If not, start at i = 0.
Alternatively, to save the pain of writing the loop yourself, you can use #Manoj's answer which replaces your code by one line.
I recommend to you use StringBuilder with append(<data>) method and then convert it to String.
StringBuilder data = new StringBuilder();
for(int i = 1; i < easy.length; i++){
data.append(easy[i].toString());
}
easyPuzzle = data.toString();
String is immutable so work with it is much more consume. When you work with String, i recommend to you use StringBuilder, is more effective and faster.
Update: #Manoj answer is very usefull.
I want to implement a high speed in memory implementation of Trie to create backend to auto suggestion / spell checker.
Is there already some good implementation based on in memory implementations like hazlecast.
Also which java open source tool is best suggested for these kind of usage
I would use a plain NavigableSet like TreeSet. Its built in and supports range searches.
NavigableSet<String> words = new TreeSet<String>();
// add words.
String startsWith = ...
SortedSet<String> matching = words.subSet(startsWith, startsWith + '\uFFFF');
If you want something more memory efficient you can use an array.
List<String> words = new ArrayList<String>();
words.add("aa");
words.add("ab");
words.add("ac");
words.add("ba");
Collections.sort(words);
String startsWith = "a";
int first = Collections.binarySearch(words, startsWith);
int last = Collections.binarySearch(words, startsWith.concat("\uFFFF"));
if (first < 0) first = ~first;
if (last < 0) last = ~last - 1;
for (int i = first; i <= last; i++) {
System.out.println(words.get(i));
}