Use Arrays.copyOfRange:
public static <T> T[] copyOfRange(T[] original,
int from,
int to)
Copies the specified range of the specified array into a new array. The initial index of the range (
from) must lie between zero andoriginal.length, inclusive. The value atoriginal[from]is placed into the initial element of the copy (unlessfrom == original.lengthorfrom == to). Values from subsequent elements in the original array are placed into subsequent elements in the copy. The final index of the range (to), which must be greater than or equal to from, may be greater thanoriginal.length, in which case null is placed in all elements of the copy whose index is greater than or equal tooriginal.length - from. The length of the returned array will beto - from.The resulting array is of exactly the same class as the original array.
In your case:
String[] grp = Arrays.copyOfRange(elements, i, i + n);
Answer from NPE on Stack OverflowUse Arrays.copyOfRange:
public static <T> T[] copyOfRange(T[] original,
int from,
int to)
Copies the specified range of the specified array into a new array. The initial index of the range (
from) must lie between zero andoriginal.length, inclusive. The value atoriginal[from]is placed into the initial element of the copy (unlessfrom == original.lengthorfrom == to). Values from subsequent elements in the original array are placed into subsequent elements in the copy. The final index of the range (to), which must be greater than or equal to from, may be greater thanoriginal.length, in which case null is placed in all elements of the copy whose index is greater than or equal tooriginal.length - from. The length of the returned array will beto - from.The resulting array is of exactly the same class as the original array.
In your case:
String[] grp = Arrays.copyOfRange(elements, i, i + n);
You will use Arrays.copyOfRange().
Here is an example:
String[] original = some array;
String[] grp = Arrays.copyOfRange(original, i, i + n);
The Javadocs for the Arrays class has lots of information about the method:
Videos
As pointed out by Pete Kirkham, this is implementation specific. My answer is only correct for the Sun JRE, and only prior to Java 7 update 6.
You're right about a normal substring call just creating a new string referring to the same character array as the original string. That's what happens on line 5 too. The fact that the new string object reference happens to be assigned to a variable doesn't change the behaviour of the method.
Just to be clear, you say that in line 2 the new string will still point to "Monday" - the char array reference inside the string will be to the same char array as one used for "Monday". But "Monday" is a string in itself, not a char array. In other words, by the time line 2 has finished (and ignoring GC) there are two string objects, both referring to the same char array. One has a count of 6 and the other has a count of 3; both have an offset of 0.
You're wrong about line 4 using a "string pool" though - there's no pooling going on there. However, it is different to the other lines. When you call the String(String) constructor, the new string takes a copy of the character data of the original, so it's completely separate. This can be very useful if you only need a string which contains a small part of a very large original string; it allows the original large char array to be garbage collected (assuming nothing else needs it) while you hold onto the copy of the small portion. A good example of this in my own experience is reading lines from a line. By default, BufferedLineReader will read lines using an 80-character buffer, so every string returned will use a char array of at least 80 characters. If you're reading lots of very short lines (single words) the difference in terms of memory consumption just through the use of the odd-looking
line = new String(line);
can be very significant.
Does that help?
I know that line 2 will still point to "Monday" and have a new String object with the offset and count set to 0,3.
That is currently true of the Sun JRE implementation. I seem to recall that was not true of the Sun implementation in the past, and is not true of other implementations of the JVM. Do not rely on behaviour which is not specified. GNU classpath might copy the array (I can't remember off hand what ratio is uses to decide when to copy, but it does copy if the copy is a small enough fraction of the original, which turned one nice O(N) algorithm to O(N^2)).
The line 4 will create a new String "Mon" in string pool and point to it.
No, it creates a new string object in the heap, subject to the same garbage collection rules as any other object. Whether or not it shares the same underlying character array is implementation dependant. Do not rely on behaviour which is not specified.
The String(String) constructor says:
Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string.
The String(char[]) constructor says:
Allocates a new String so that it represents the sequence of characters currently contained in the character array argument. The contents of the character array are copied; subsequent modification of the character array does not affect the newly created string.
Following good OO principles, no method of String actually requires that it is implemented using a character array, so no part of the specification of String requires operations on an character array. Those operations which take an array as input specify that the contents of the array are copied to whatever internal storage is used in the String. A string could use UTF-8 or LZ compression internally and conform to the API.
However, if your JVM doesn't make the small-ratio sub-string optimisation, then there's a chance that it does copy only the relevant portion when you use new String(String), so it's a case of trying it a seeing if it improves the memory use. Not everything which effects Java runtimes is defined by Java.
To obtain a string in the string pool which is equal to a string, use the intern() method. This will either retrieve a string from the pool if one with the value already has been interned, or create a new string and put it in the pool. Note that pooled strings have different (again implementation dependent) garbage collection behaviour.
It's supposed to be an efficiency measure. i.e. when you're taking a substring you won't create a new char array, but merely create a window onto the existing char array.
Is this worthwhile ? Maybe. The downside is that it causes some confusion (e.g. see this SO question), plus each String object needs to carry the offset info into the array, even if it's not used.
EDIT: This behaviour has now changed as of Java 7. See the linked answer for more info
Turning it around, why allocate a new char[] when it is not necessary? This is a valid implementation since String is immutable. It saves allocations and memory in the aggregate.
To start you off on your assignment, String.split splits strings on a regular expression and this expression may be an empty string:
String[] ary = "abc".split("");
Yields the array:
(java.lang.String[]) [, a, b, c]
Getting rid of the empty 1st entry is left as an exercise for the reader :-)
Note: In Java 8, the empty first element is no longer included.
String strName = "name";
String[] strArray = new String[] {strName};
System.out.println(strArray[0]); //prints "name"
The second line allocates a String array with the length of 1. Note that you don't need to specify a length yourself, such as:
String[] strArray = new String[1];
instead, the length is determined by the number of elements in the initalizer. Using
String[] strArray = new String[] {strName, "name1", "name2"};
creates an array with a length of 3.