Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Strings are immutable. Stringbuilders are not, so you can append characters at the end. Strings are character arrays if i am not wrong, than why do we use character arrays separately and Strings separately, Do we really need to use character arrays?
Secondly, there are character arrays and then there are Arraylists. Array lists holds complete objects? I am a bit confused actually.
String cat = "c" + "a" + "t";
cat = cat + cat;
StringBuilder sb = new StringBuilder();
sb.append(city);
sb.append(", ");
sb.append(state);
sb.toString();
Char apple[5]={'a','p','p','l','e'};
Arraylist<MyCar>obj = new Arraylist<MyCar>();
Which should be used where?
This Explain the best: between string and stringBuilder
Ref:Correct way to use StringBuilder
Note that the aim (usually) is to reduce memory churn rather than total memory used, to make life a bit easier on the garbage collector.
Will that take memory equal to using String like below?
No, it'll cause more memory churn than just the straight concat you quoted. (Until/unless the JVM optimizer sees that the explicit StringBuilder in the code is unnecessary and optimizes it out, if it can.)
If the author of that code wants to use StringBuilder (there are arguments for, but also against; see note at the end of this answer), better to do it properly (here I'm assuming there aren't actually quotes around id2 and table):
StringBuilder sb = new StringBuilder(some_appropriate_size);
sb.append("select id1, ");
sb.append(id2);
sb.append(" from ");
sb.append(table);
return sb.toString();
Note that I've listed some_appropriate_size in the StringBuilder constructor, so that it starts out with enough capacity for the full content we're going to append. The default size used if you don't specify one is 16 characters, which is usually too small and results in the StringBuilder having to do reallocations to make itself bigger (IIRC, in the Sun/Oracle JDK, it doubles itself [or more, if it knows it needs more to satisfy a specific append] each time it runs out of room).
You may have heard that string concatenation will use a StringBuilder under the covers if compiled with the Sun/Oracle compiler. This is true, it will use one StringBuilder for the overall expression. But it will use the default constructor, which means in the majority of cases, it will have to do a reallocation. It's easier to read, though. Note that this is not true of a series of concatenations. So for instance, this uses one StringBuilder:
return "prefix " + variable1 + " middle " + variable2 + " end";
It roughly translates to:
StringBuilder tmp = new StringBuilder(); // Using default 16 character size
tmp.append("prefix ");
tmp.append(variable1);
tmp.append(" middle ");
tmp.append(variable2);
tmp.append(" end");
return tmp.toString();
So that's okay, although the default constructor and subsequent reallocation(s) isn't ideal, the odds are it's good enough — and the concatenation is a lot more readable.
But that's only for a single expression. Multiple StringBuilders are used for this:
String s;
s = "prefix ";
s += variable1;
s += " middle ";
s += variable2;
s += " end";
return s;
That ends up becoming something like this:
String s;
StringBuilder tmp;
s = "prefix ";
tmp = new StringBuilder();
tmp.append(s);
tmp.append(variable1);
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(" middle ");
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(variable2);
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(" end");
s = tmp.toString();
return s;
...which is pretty ugly.
It's important to remember, though, that in all but a very few cases it doesn't matter and going with readability (which enhances maintainability) is preferred barring a specific performance issue.
Normally String is used for normal string based requirement, and when a String can suffice it.
String Builder is used whenever you want to manipulate and play with the string.
Character Array is used when you want to easily iterate over each and every character
ArrayList is a collection. Use it for holding object of a particular type.
String is immutable object that includes underlying char array.
In your line 2 you discard your String that you created in line 1 and create a new String.
String builder avoids creating new String objects for every separate substring.
Both arrays and Arraylist can contain objects, the main difference is that Arraylist can grow, arrays can not. The second difference is that Arraylist is really a List...
A String uses a char[]. A String is not a char[], in the same way that an ArrayList<String> is not a String[].
ArrayList type is a dynamic data structure. This means that it can grow depending on need. Array is static, meaning it's dimensions do not change over its lifetime.
Related
I'm trying to create a string comprised of a single letter, followed by 4 digits e.g. b6789. I'm getting stuck when I try to convert a character, and integer to one String. I can't use toString() because I've overwritten it, and I assume that concatenation is not the best way to approach it? This was my solution, until I realised that valueof() only takes a single parameter. Any suggestions? FYI - I'm using Random, because I will be creating multiples at some point. The rest of my code seemed irrelevant, and hence has been omitted.
Random r = new Random();
Integer numbers = r.nextInt(9000) + 1000;
Character letter = (char)(r.nextInt(26) + 'a');
String strRep = String.valueOf(letter, numbers);
I think they mean for you not to use concatenation with + operator.
Rather than that, there's a class called StringBuilder which will do the trick for you. Just create an empty one, append anything you need on it (takes Objects or primitives as arguments and does all the work for you), and at the end, just call at its "toString()" method, and you'll have your concatenated String.
For example
StringBuilder sb = new StringBuilder();
sb.append("Foo");
sb.append(123);
return sb.toString();
would return the string Foo123
you can use:
Character.toString(char)
which is
String.valueOf(char)
in reality which also works.
or just use
String str = "" + 'a';
as already mentioned but not very efficient as it is
String str = new StringBuilder().append("").append('a').toString();
in reality.
same goes for integer + string or char + int to string. I think your simpliest way would be to use string concatenation
Looks like you want
String.valueOf(letter).concat(numbers.toString());
Short version: If you call string.substring(n,m).intern(), does the string table retain the substring or the original string?
...But I'm not sure that's the right question to ask, so here's the long version:
I'm working with legacy Java code (PCGen) that parses files by slurping each in as one big string and then using String.split, .trim, .substring, and StringTokenizer to decompose them into tokens. This is very efficient for parsing, because none of those methods copy the original string, but all point at parts of a shared char[].
After parsing is over, I want to reclaim some memory. Only a few small substrings of the original big string are needed, but the strong reference keeps the big string from being collected. And later I'm suffering OOM, I believe due in part to that huge heap impact of lots of parsed files.
I know I can trim the big string down via new String(String)(copy-on-write). And I know I can reduce string duplication via String.intern (which is important because there's a lot of redundancy in the parsed files). Do I need to use both to reclaim the greatest quantity of heap, or does .intern() do both? Reading the OpenJDK7 hotspot source code (hotspot/src/share/vm/classfile/symbolTable.cpp) it looks like the string table keeps the whole string and does not trim it for offset/length at all. So I think I need to make a new String and then intern that result. Right?
All that said, switching to a streaming parser would be a big win in terms of memory, but that's too big a change for the short term.
You can use new String(String) and the intern() method and this will take a copy as required for up to Java 7 update 4. From Java 7 update 5 substring will take a deeper copy, but you may still want to use intern(). Note: Java 7 uses the heap, not the perm gen to store String literals.
public static void main(String[] args) {
char[] chars = new char[128];
Arrays.fill(chars, 'A');
String a128 = new String(chars);
printValueFor("a128", a128);
String a16 = a128.substring(0, 16);
printValueFor("a16", a16);
}
public static void printValueFor(String desc, String s) {
try {
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
char[] valueArr = (char[]) value.get(s);
System.out.println(desc + ": " + Integer.toHexString(System.identityHashCode(valueArr)) + ", len=" + valueArr.length);
} catch (Exception e) {
throw new AssertionError(e);
}
}
on Java 7 update 4 prints
a128: 513e86ec, len=128
a16: 53281264, len=16
I would expect that Java 6 does not do this.
We can test it. String holds its character array in a field
private final char value[];
let's see what happens after substring(); intern();
Field f = String.class.getDeclaredField("value");
f.setAccessible(true);
String s1 = "12345";
String s2 = s1.substring(1, 2);
String s3 = s2.intern();
System.out.println(f.get(s2) == f.get(s1));
System.out.println(f.get(s3) == f.get(s2));
output
true
true
that is, all 3 strings share the same character array
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
when to use StringBuilder in java
If not which of these pieces of code is better and why
public String backAround(String str) {
int len = str.length();
StringBuilder sb = new StringBuilder(str);
char chEnd = sb.charAt(len-1);
if(len > 0){
sb = sb.append(chEnd);
sb= sb.insert(0,chEnd);
str= sb.toString();
return str;
}else{ return str;}
}
or
public String backAround(String str) {
// Get the last char
String back = str.substring(str.length()-1, str.length());
return back + str + back;
}
If you are just "sticking a few elements together" as in your backAround() method, you may as well just use the + notation. The compiler will convert this into appropriate StringBuilder.append()s for you, so why bother 'spelling things out'.
The idea of explicitly using StringBuilder is that in principle you can hand-optimise how exactly the elements are appended to the string, including setting the initial buffer capacity and ensuring that you don't accidentally create intermediate String objects that are unnecessary in cases where the compiler might not predict these things.
So essentially, explicitly use a StringBuilder when there is slightly more complex logic to deciding what to append to the string. For example, if you are appending things in a loop, or where what is appended depends on various conditions at different points. Another case where you might use StringBuilder is if the string needs to be built up from various methods, for example: you can then pass the StringBuilder into the different methods and ask them to append the various elements.
P.S. I should say that StringBuilder buys you a little more editing power as well (e.g. among other things, you can set its length) and, given the presence of the Appendable interface, you can actually create more generic methods that either append to a StringBuilder or to e.g. a StringWriter. But these are marginal cases, I would submit.
It really depends on what you are trying to do. In your case it seems like your trying to take a string and take the last letter and add it to the front and then add another to the end. For this i would probably do this:
public String manipulate(String string)
{
char c = string.charAt(string.length);
return c + string + c;
}
In this case you didn't have to use a StringBuilder. There are cases where the StringBuilder class is useful. Here are some things that are hard to do with a String that StringBuilder can do:
delete chars at an index
append chars at an index
get the index of a specific sequence
and much much more
if you want to see the documentation for StringBuilder:
String Builder
I hope this helped you out!
I have some 'heavy' string manipulation in my Java program, which often involves iterating through a String and replacing certain segments with filler characters, usually "#". These are characters are later removed but are used so that the length of the String and the current index are kept intact during the iteration.
This process usually involves replacing more than 1 character at a time.
e.g.
I might need to replace "cat" with "###" in the string "I love cats", giving "I love ###s",
So often I need to create strings of "#" with x length.
In python, this is easy.
NewString = "#" *x
In Java, I find my current method revolting.
String NewString = "";
for (int i=0; i< x; i++) {
NewString = NewString.concat("#"); }
Is there a proper, pre-established method for doing this?
Does anybody have a shorter, more 'golfed' method?
Thanks!
Specs:
Java SE (Jre7)
Windows 7 (32)
It's not clear to me what kind of regex the comments are suggesting, but creating a string filled with a particular character to the given length is pretty easy:
public static String createString(char character, int length) {
char[] chars = new char[length];
Arrays.fill(chars, character);
return new String(chars);
}
Guava has a nice little method Strings.repeat(String, int). Looking at the source of that method, it basically amounts to this:
StringBuilder builder = new StringBuilder(string.length() * count);
for (int i = 0; i < count; i++) {
builder.append(string);
}
return builder.toString();
Your way of building a string of length N is very inefficient. You should either use StringBuffer with its convenient append method, or build an array of N characters, and use the corresponding constructor of the String.
Can you always use the same characters in the "filler" String and do you know the maximum value of x? The you can create a constant upfront which can be cut to arbitrary length:
private static final FILLER = "##############################################";
// inside your method
String newString = FILLER.substring(0, x);
java.lang.String is immutable. So, concating strings would result in creation of temporary string objects and thus is slow. You should consider using a mutable buffer like StringBuffer or StringBuilder. Another best practice when working with strings in java is to prefer using CharSequence type wherever possible. This would avoid unnecessary calls to toString() and you can easily change the underlying implementation type.
If you are looking for a one liner to repeat strings and this justifies using an external library, have a look at StringUtils.repeat from Apache Commons library. But, I feel you can just write your own code than using another library for a trivial task of repeating strings.
I read a lot about using StringBuffer and String especially where concatenation is concerned in Java and whether one is thread safe or not.
So, in various Java methods, which should be used?
For example, in a PreparedStatement, should query be a StringBuffer:
String query = ("SELECT * " +
"FROM User " +
"WHERE userName = ?;");
try {
ps = connection.prepareStatement(query);
And then again, in a String utility methods like:
public static String prefixApostrophesWithBackslash(String stringIn) {
String stringOut = stringIn.replaceAll("'", "\\\\'");
return stringOut;
}
And:
// Removes a char from a String.
public static String removeChar(String stringIn, char c) {
String stringOut = ("");
for (int i = 0; i < stringIn.length(); i++) {
if (stringIn.charAt(i) != c) {
stringOut += stringIn.charAt(i);
}
}
return stringOut;
}
Should I be using StringBuffers? Especially where repalceAll is not available for such objects anyway.
Thanks
Mr Morgan.
Thanks for all the advice. StringBuffers have been replaced with StringBuilders and Strings replaced with StringBuilders where I've thought it best.
You almost never need to use StringBuffer.
Instead of StringBuffer you probably mean StringBuilder. A StringBuffer is like a StringBuilder except that it also offers thread safety. This thread safety is rarely needed in practice and will just cause your code to run more slowly.
Your question doesn't seem to be about String vs StringBuffer, but about using built-in methods or implementing the code yourself. If there is a built-in method that does exactly what you want, you should probably use it. The chances are it is much better optimized than the code you would write.
There is no simple answer (apart from repeating the mantra of StringBuilder versus StringBuffer ... ). You really have understand a fair bit about what goes on "under the hood" in order to pick the most efficient solution.
In your first example, String is the way to go. The Java compiler can generate pretty much optimal code (using a StringBuilder if necessary) for any expression consisting of a sequence of String concatenations. And, if the strings that are concatenated are all constants or literals, the compiler can actually do the concatenation at compile time.
In your second example, it is not entirely clear whether String or StringBuilder would be better ... or whether they would be roughly equivalent. One would need to look at the code of the java.util.regex.Matcher class to figure this out.
EDIT - I looked at the code, and actually it makes little difference whether you use a String or StringBuilder as the source. Internally the Matcher.replaceAll method creates a new StringBuilder and fills it by appending chunks from the source String and the replacement String.
In your third example, a StringBuilder would clearly be best. A current generation Java compiler is not able to optimize the code (as written) to avoid creating a new String as each character is added.
For the below segment of code
// Removes a char from a String.
public static String removeChar(String stringIn, char c) {
String stringOut = ("");
for (int i = 0; i < stringIn.length(); i++) {
if (stringIn.charAt(i) != c) {
stringOut += stringIn.charAt(i);
}
}
return stringOut;
}
You could just do stringIn.replaceAll(c+"","")
Even in MT code, it's unusual to have multiple threads append stuff to a string. StringBuilder is almost always preferred to StringBuffer.
Modern compilers optimize the code already. So some String additions will be optimized to use StringBuilder and we can keep the String additions if we think, it increases readibility.
Example 1:
String query = ("SELECT * " +
"FROM User " +
"WHERE userName = ?;");
will be optimized to somthing like:
StringBuiler sb = new StringBuilder();
sb.append("SELECT * ");
sb.append("FROM User ");
sb.append("WHERE userName = ?;");
String query = sb.toString();
Example 2:
String numbers = "";
for (int i = 0;i < 20; i++)
numbers = numbers + i;
This can't be optimized and we should use a StringBuilder in code.
I made this observation for SUN jdk1.5+. So for older Java versions or different jdks it can be different. There it could be save to always code StringBuilder (or StringBuffer for jdk 1.4.2 and older).
For cases which can be considered single threaded, the best would be StringBuilder. It does not add any synchronization overhead, while StringBuffer does.
String concatenation by '+' operator is "good" only when you're lazy to use StringBuilder or just want to keep the code easily readable and it is acceptable from performance point of view, like in startup log message "LOG.info("Starting instance " + inst_id + " of " + app_name);"