Java StringBuffer questions - java

class MyStringBuffer {
//TODO explain: why you would need these data members.
private char[] chars; //character storage.
private int length; //number of characters used
public String toString(){
//TODO
//Hint: just construct a new String from the ‘chars’ data member
//and return this new String – See API online for how create
//new String from char[]
This is only part of the code, I didn't want to post the whole thing. I just to focus on this and then then move on when I fully understand it.
1) What does he mean when he said construct a new String from the 'chars' data member? I'm confused as to what he wants me to do. Am I suppose to do something with char charAt(int index)? or something like this: StringBuffer sb = new StringBuffer("test");?
2) Does construct and create mean the same thing in Java?

What does he mean when he said construct a new String from the 'chars' data member? I'm confused as to what he wants me to do. Am I suppose to do something with char charAt(int index)? or something like this: StringBuffer sb = new StringBuffer("test");?
Do either of those things create a String? (Hint: no)
How do you create an instance of a particular class in Java? (Hint: review your notes on new. Hint 2: look at the javadocs for the java.lang.String class.).
Does construct and create mean the same thing in Java?
Java objects are created by a constructor, so it is reasonable to use "construct" and "create" interchangeably.
(Technically they don't mean exactly the same thing. An object is created by allocating its memory and calling a class constructor. So if you are being pedantic, constructing is part of the process of creating an object. But there's no need to be pedantic.)

1) The easy way to create a string from chars:
String result = new String(chars, 0, length);
Note, you probably can't just use the String(char[]) constructor, because the existence of the length member implies that some elements of chars may not be used. If you don't specify what elements to use, you could end up with extra chars (maybe NULs, maybe garbage) at the end of the string.
2) Not exactly. While the object is created (the memory for the object itself allocated) at the time the constructor's called, at that time it's just a blob of memory. The object is not fully constructed (read: any class invariants may not necessarily hold) until the constructor returns. This means the difference between the two only applies in the constructor, though, so it's common for people to use "create" and "construct" almost interchangeably.

You need an array of chars because, well, you have to store the characters somewhere. You could store them in a String but then you would have little need of a StringBuffer, whose raison d'etre is to be more efficient than a String (you generaly use the more efficient StringBuffer to construct a string, then use .toString() to get a real String object).
The length would be used to specify the length of the StringBuffer. You may thing you could just use the length of the character array but it's actually more efficient, when reducing the size of the StringBuffer, to not re-allocate a smaller array, especially if you may just end up needing more anyway.
The String constructor you would need for this scheme would be String (char[] value, int offset, int count) using an offset of zero and a count of length. This would allow you to use only the desired subset of the char array.

As he says, have a look at the API, where you will find a String constructor that takes an array of characters: http://download.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#String%28char[]%29 .

Related

Why do I need to redefine a String if I use the method replace?

Why do I need to redefine the variable theString if I use the method replace in this code :
String theString = "I w#nt to h#ve the regul#r \"A\"!";
theString = theString.replace("#", "a");
System.out.println(theString);
Why can't I do :
theString.replace("#", "a");
and that's it?
Strings are immutable -- you cannot change them once they have been created. There are exceptions of course, if you use reflective magic, but for the most part, they should be treated as invariants. So therefore the method replace(...) does not change the String, it can't, but rather it creates and returns a new String. So to be able to use that new String, you have to get access to its reference, and that can be done by assigning it to a String variable or even to the original String variable. This discussion gets to the heart of what is the difference between an object and a reference variable.
Because String objects are, by design, immutable, so you need to create a new String to contain your changes
The posted answers mention the technical reason (strings are immutable) but neglect to mention why it is that way. See this: Why are strings immutable in many programming languages?
Taken from this link
In Java, String is not implemented as character arrays as in other programming languages. Instead string is implemented as instance of String class.
Strings are constants/ immutable and their values cannot be changed after they are created. If any operations that results in the string being altered are performed a new instance of String object is created and returned. This approach is done for implementation efficiency by Java.
It is recommended to use StringBuffer or StringBuilder when many changes need to be performed on the String. StringBuffer is like a String but can be modified. StringBuffer is thread safe and all the methods are synchronized. StringBuilder is equivalent to StringBuffer and is for use by single thread. Since the methods are not synchronized it is faster.

How to get character array which is inside StringBuilder to avoid array copy

Is there any way by which I can get character array stored inside StringBuilder to avoid creating copy of it when I do toString(). Since, it is a primitive array so it is like deep copy and I would like to avoid generating this garbage.
Avoid doing stringbuilder.toString().toCharArray() as it will allocate the memory twice.
Use something like :
char[] charArray = new char[stringbuilder.length()];
stringbuilder.getChars(0, stringbuilder.length(), charArray, 0);
Using reflection is also a bad idea as it may not be compatible with future java version and you'll have to resize the array as its size is probably bigger than the StringBuilder length see StringBuilder#capacity()
You can treat the StringBuilder as a char[], the bridge is supported by the interface CharSequnce
Calling the method charAt(int index) is "equal to" array[index]
The array is a private field that is not exposed to the public customer, due to encapsulation.
No, you can't.
Check the source of StringBuilder.
char value[] is the character array stored inside StringBuilder, and it's reference can be accessed only through getValue method, which is NOT public.
Therefore, either use toString or getChars
You can do this using reflection:
Field stringbuilderCharField = StringBuilder.class.getSuperclass().getDeclaredField("value");
stringbuilderCharField.setAccessible(true);
char[] charArray = (char[]) stringbuilderCharField.get(pString);
And as StringBuilder is mutable, this is actually a nice way to use it.
You can do the same for String, but not advisable, as String is immutable.
Let us suppose 'str' is an instance of StringBuilder class that holds some string.
The simplest way to convert str to char array is as follows:
'str.toString().toCharArray(); '

Explaining some details about String

Hi y'all I have a very simple question. I am studying different websites that talk about arrays and I see this part which I don't understand very well.
In the (1) Why does the 'myString.length()' has a '()', why not just myString.length as in the example (2)??
In the (1) Why does the 'System.out.println(myString.substring(i,i+1))' has 'myString.substring(i,i+1)' why not just 'myString(i,i+1)' ??
In the (1) Why does the 'System.out.println(myString.substring(i,i+1))' has two values '(i,i+1)' why not just 'System.out.println(myString.substring(i))' as in example (2)??
1. String myString="abcedaslkhldfag";
for(int i=0; i<myString.length(); i++)
System.out.println(myString.substring(i,i+1));
2. for(int i=0; i<anArrayOfints.length; i++){
System.out.println(anArrayOfints[i]);
}
Thank you
I found it in this website http://www.javaclass.info/classes/java-array/array-examples-demonstration-and-code-snippets.php
First, about Arrays and Strings.
You are comparing totally different classes.
Array types are special objects that are dynamically created. Even array of primitives are objects (unlike in C) so it might have certain member variables/methods.
Have a look here: Array members
String is a class which encapsulates behavior suitable for strings, such as substring, trim etc. The actual data is stored internally as a character array, so there is a close connection between them, but the class itself represents more than just the characters.
Secondly, about subString method.
Methods called on a string object follow the syntax as specified by the API.
public String substring(int beginIndex)
public String substring(int beginIndex,int endIndex)
Have a look at the String API here. You will find there a length() method that returns the length of the String.
A note about "Arrays" class.
There is a class called "Arrays" that became available as part of the collections framework. The purpose of this class was to include behaviors that where commonly used on all types of arrays(such as sorting and searching).
The Array class extends java.lang.Object. Therefore array is an instance of Object. Arrays have one instance variable called length. It's a variable so you dont need the ().
And the string class has a member function called length, which is why you need the ().
The first one, myString is a string, which is an object. You are calling a method called length() of type String to know the length of the string. This method calculates the number of chars in the string and returns that number. And subString() is also a method that takes two parameters, begin and end index. This is just standard that is created by Java. To know more about the string methods, here.
The second one is continuous memory of data, an array. The length of the array is also stored in the array and is accessed using '.length'
This is because length() is a method on the String class, while length is an instance variable on the Array class.
As for myString.substring(i, i + 1), this is a method being called on an instance of the String class, which will return a new String instance containing the substring. In fact, myString.substring(i) does exist in the API, and would return the substring that starts at i and ends with the last character in myString.
Note that anArrayOfints[i] returns the int stored at element i in the array.
1, myString has a method named length. When use a method, you must specific the arguments which should be included in "()". In the (2), length means an attribute. Just use it as a variable.
2, substring is method. When use a method of some object, you can imagine you are sending command to this object. myString can not understand "myString(i,i+1)". You should specific the method or the command "subString"
3, anArrayOfints is an array object. Just like a list of something. You should specific a number to pick a element up.

No reverse method in String class in Java?

Why there is no reverse method in String class in Java? Instead, the reverse() method is provided in StringBuilder? Is there a reason for this? But String has split(), regionMatches(), etc., which are more complex than the reverse() method.
When they added these methods, why not add reverse()?
Since you have it in StringBuilder, there's no need for it in String, right? :-)
Seriously, when designing an API there's lots of things you could include. The interfaces are however intentionally kept small for simplicity and clarity. Google on "API design" and you'll find tons of pages agreeing on this.
Here's how you do it if you actually need it:
str = new StringBuilder(str).reverse().toString();
Theoretically, String could offer it and just return the correct result as a new String. It's just a design choice, when you get down to it, on the part of the Java base libraries.
If you want an historical reason, String are immutable in Java, that is you cannot change a given String if not creating another String.
While this is not bad "per se", initial versions of Java missed classes like StringBuilder. Instead, String itself contained (and still contains) a lot of methods to "alter" the String but since String is immutable, each of these methods actually creates and return a NEW String object.
This caused simple expressions like :
String s = "a" + anotherString.substr(10,5).trim().toLowerCase();
To actually create in ram something like 5 strings, 4 of which are absolutely useless, with obvious performance problems (despite after there has been some optimizations regarding underlying char[] arrays).
To solve this, Sun introduced StringBuilder and other classes that ARE NOT immutable. These classes freely modify a single char[] array, so that calling methods does not need to produce many intermediate String instances.
They added "reverse" quite lately, so they added it to StringBuilder instead of String, cause that's now the preferred way to manipulate strings.
As a side-note, in Scala you use the same java.lang.String class and you do get a reverse method (along with all kinds of other handy stuff). The way it does it is with implicit conversions, so that your String gets automatically converted into a class that does have a reverse method. It's really quite clever, and removes the need to bloat the base class with hundred of methods.
String is immutable, meaning it can't be changed.
When you reverse a String, what's happening is that each letter is switched on it's own, means it will always create the new object each times.
Let us see with example:
This means that for instance Hello becomes as below
elloH lloeH loleH olleH
and you end up with 4 new String objects on the heap.
So think if you have thousands latter of string or more then how much object will be created.... it will be really a very expensive. So too much memory will be occupied.
So because of this String class not having reverse() method.
Well I think it could be because it is an immutable class so if we had a reverse method it would actually create a new object.
reverse() acts on this, modifying the current object, and String objects are immutable - they can't be modified.
It's peculiarly efficient to do reverse() in situ - the size is known to be the same, so no allocation is necessary, there are half as many loop iterations as there would be in a copy, and, for large strings, memory locality is optimal. From looking at the code, one can see that a lot of care was taken to make it fast. I suspect the author(s) had a particular use case in mind that demanded high performance.

Why isn't String() constructor private?

Is using a String() constructor as against string literal beneficial in any scenario?
Using string literals enable reuse of existing objects, so why do we need the public constructor? Is there any real world use?
For eg., both the literals point to the same object.
String name1 = "name";//new String("name") creates a new object.
String name2 = "name";
One example where the constructor has a useful purpose: Strings created by String.substring() share the underlying char[] of the String they're created by. So if you have a String of length 10.000.000 (taking up 20MB of memory) and take its first 5 characters as substring then discard the original String, that substring will still keep the 20MB object from being eligible for garbage collection. Using the String constructor on it will avoid that, as it makes a copy of only the part of the underlying char array that's actually used by the String instance.
Of course, if you create and use a lot of substrings of the same String, especially if they overlap, then you'd very much want them to share the underlying char[], and using the constructor would be counterproductive.
Since string is immutable, operations like substring keep the original string that might be long. Using the constructor to create new string from the substring will create a new string and will allow dropping the old string (to GC). This way might free up needed memory.
Example:
String longS = "very long";
String shortS = new String(longS.substring(4));
Because sometimes you might want to create a copy and not just have a new reference to the same string.
All good answers here, but I think it's worth pointing out that the Java treats literals quite different than Strings constructed the traditional way.
This is a good Q/A about it.

Categories