What does new ClassName[0] do? (Java 8) - java

What does this syntax do, with square brackets around the number?
new Integer[0];
I've found it in a codebase I'm maintaining but I can't find any documentation on it. It is used like this:
Set<Form> forms = getForms();
List<Form> formsList = Arrays.asList(forms.toArray(new Form[0]))

It allocates an array with length zero; e.g. new Integer[0] creates a zero length array of Integer objects.
Why would you do that?
Well look at the javadocs for the form.toArray(T[]) method. Assuming that form is some subtype of Collection they are here.
The purpose of the toArray method is to copy the elements of the target collection (e.g. your form) into an array:
If the argument array is large enough to hold all elements, they are copied into that array. The result will be the argument array.
If the argument array is too small, a new array is allocated with the same type as the argument array and a length that is (just) enough to hold the elements. The elements are then copied into the new array, and it is returned as the result.
So what the code is actually doing is copying the elements of form to an Integer[] of the right size, and then wrapping the array to give a (fixed sized) List<Integer>. This can then be passed to some other code without worrying that that code might alter the original form collection.

Unlike traditional array which store values like string, integer, Boolean, etc. array of objects stores objects. The array elements store the location of reference variables of the object
Syntax:
Class obj[]= new Class[array_length]

Related

Difference between toArray(T[] a) and toArray()

I've been learning how to program with java and I haven't got any clear explanation about the difference of LinkedList's toArray(T[] a) and toArray() method. The second one simply returns all of the elements within the LinkedList object as an array, right? But, what about the first one?
EDIT :
I mean, I read the documentation from oracle, it says :
Returns an array containing all of the elements in this list in proper
sequence (from first to last element); the runtime type of the
returned array is that of the specified array. If the list fits in
the specified array, it is returned therein. Otherwise, a new array is
allocated with the runtime type of the specified array and the size of
this list. If the list fits in the specified array with room to spare
(i.e., the array has more elements than the list), the element in the
array immediately following the end of the list is set to null. (This
is useful in determining the length of the list only if the caller
knows that the list does not contain any null elements.)
Like the toArray() method, this method acts as bridge between
array-based and collection-based APIs. Further, this method allows
precise control over the runtime type of the output array, and may,
under certain circumstances, be used to save allocation costs.
I don't understand the meaning of the sentences displayed in bold.
Suppose you've a List<String>, and you want to convert it to String[]. Let's see the working of two methods:
List<String> source = new LinkedList<String>();
// Fill in some data
Object[] array1 = source.toArray();
String[] array2 = source.toArray(new String[source.size()]);
See the difference? The first one simply creates an Object[], because it doesn't know the type of the type parameter <T>, while the second one just fills up the String[] you passed (which is what you want). You would almost always need to use the 2nd method.
There are two differences :
The first returns T[] while the second returns Object[]
The first accepts an array as an argument, and if this array is large enough, it uses this array to store the elements of the Collection, instead of creating a new one.

How can I get the size of an array, a Collection, or a String in Java?

What are the different ways that I can access the length of an array, a collection (List, Set, etc.), and a String object? Why is it different?
Abridged:
For an array: use .length.
For a Collection (or Map): use .size().
For a CharSequence (which includes CharBuffer, Segment, String, StringBuffer, and StringBuilder): use .length().
Arrays
One would use the .length property on an array to access it. Despite an array being a dynamically created Object, the mandate for the length property is defined by the Java Language Specification, §10.3:
An array is created by an array creation expression (§15.10) or an
array initializer (§10.6).
An array creation expression specifies the element type, the number of
levels of nested arrays, and the length of the array for at least one
of the levels of nesting. The array's length is available as a final
instance variable length.
An array initializer creates an array and provides initial values for
all its components.
Since the length of an array cannot change without the creation of a new array instance, repeated accesses of .length will not change the value, regardless of what is done to the array instance (unless its reference is replaced with a differently sized array).
As an example, to get the length of a declared one-dimensional array, one would write this:
double[] testScores = new double[] {100.0, 97.3, 88.3, 79.9};
System.out.println(testScores.length); // prints 4
To get lengths in an n-dimensional array, one needs to bear in mind that they are accessing one dimension of the array at a time.
Here's an example for a two-dimensional array.
int[][] matrix
= new int[][] {
{1, 2, 3, 4},
{-1, 2, -3, 4},
{1, -2, 3, -4}
};
System.out.println(matrix.length); // prints 3 (row length or the length of the array that holds the other arrays)
System.out.println(matrix[0].length); // prints 4 (column length or the length of the array at the index 0)
This is important to make use of, especially in the case of jagged arrays; the columns or rows may not always line up all the time.
Collections (Set, List, etc.)
For every object that implements the Collection interface, they will have a method called size() with which to access the overall size of the collection.
Unlike arrays, collections are not fixed length, and can have elements added or removed at any time. A call to size() will produce a nonzero result if and only if there has been anything added to the list itself.
Example:
List<String> shoppingList = new ArrayList<>();
shoppingList.add("Eggs");
System.out.println(shoppingList.size()); // prints 1
Certain collections may refuse to add an element, either because it's null, or it's a duplicate (in the case of a Set). In this case, repeated additions to the collection will not cause the size to increment.
Example:
Set<String> uniqueShoppingList = new HashSet<>();
uniqueShoppingList.add("Milk");
System.out.println(uniqueShoppingList.size()); // prints 1
uniqueShoppingList.add("Milk");
System.out.println(uniqueShoppingList.size()); // prints 1
Accessing the size of a List<List<Object>>* is done in a similar way to a jagged array:
List<List<Integer>> oddCollection = new ArrayList<>();
List<Integer> numbers = new ArrayList<Integer>() {{
add(1);
add(2);
add(3);
}};
oddCollection.add(numbers);
System.out.println(oddCollection.size()); // prints 1
System.out.println(oddCollection.get(0).size()); // prints 3
*: Collection doesn't have the get method defined in its interface.
As an aside, a Map is not a Collection, but it also has a size() method defined. This simply returns the number of key-value pairs contained in the Map.
String
A String has a method length() defined. What it does is print the number of characters present in that instance of the String.
Example:
System.out.println("alphabet".length()); // prints 8
Don't forget CollectionUtils.size() from the commons library, its null safe so you don't have to null check beforehand.
Why is it different?
I'll try to answer this part, since it doesn't seem to be covered in the other answers.
The method on a CharSequence (including String) is called .length() because a sequence has a length. "Length" is a sensible word to use for a sequence, because it has a start and an end, and you can measure how far apart they are; just like you can measure the distance between two ends of a stick to get the "length" of the stick.
The method on a Collection is called .size() because not every collection is a sequence with a start and an end. Imagine having a collection of two thousand different stamps; you would say that the "size" of your collection is 2,000, but you would not say that the "length" of your collection is 2,000. The word "size" is more natural for things that aren't measured from start to end. It happens that some collections like ArrayList do represent a sequence where it makes sense to talk about their length, but the method is still named .size() because that method name is inherited from the Collection interface; it would be strange to add another method named .length() for sequential collections, which would do the same thing as the inherited .size().
Arrays are sequences, so they have lengths. However, arrays are a low-level feature of the language; they aren't instances of an "array" class that could declare a .length() method, so therefore .length isn't a method. Syntactically it looks like accessing a field, but it isn't a field; an expression which gets the length of an array is compiled to the bytecode instruction arraylength. The distinct bytecode instruction for an array's length corresponds with the distinct syntax for it.

Why do you need to specify an array to Set.toArray, which returns an array?

I'm confused about the design and proper use of toArray(T[]) method in Set (and other collections). If I have a Set of String, why do I need to specify an array of String of size 0, if the method is going to allocate a new String array anyway?
Set<String> stringSet = new Set<String>();
// bla bla bla, insert Strings to set
String[] array = stringSet.toArray(new String[0]);
Is there a better way to just get the array without allocating extra arrays or the explicit type conversion?
The parameter is used to detect the type of the array that's going to be created.
You could argue, why doesn't the JVM use the generic type parameter of the stringSet to detect the type. The answer is that at runtime the generic type parameter is not known due to type erasure, i.e Set<String> becomes Set after compilation.
toArray(new Object[0]) is identical in function to toArray().
If the set fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this set.
If you are using a collection, you may not know the exact number of entries that your set (or any other collection) will have. If you know from the beginning the number of entries, why don't you use an array instead of a collection?
The way I see it, the toArray() method is a simple way to create arrays using a collection for which you don't know a priori how many entries it will have.

How is length implemented in Java Arrays?

I was wondering about the implementation of length of a Java Array. I know that using arrayName.length gives us the number of elements in the array, but was wondering if this is a method / function or it is just a data member of Array?
I guess it must be a data member as we do not use parenthesis() when invoking it. But if it is a data member how/when is the value of this length assigned/computed?
According to the Java Language Specification (specifically §10.7 Array Members) it is a field:
The public final field length, which contains the number of components of the array (length may be positive or zero).
Internally the value is probably stored somewhere in the object header, but that is an implementation detail and depends on the concrete JVM implementation.
The HotSpot VM (the one in the popular Oracle (formerly Sun) JRE/JDK) stores the size in the object-header:
[...] arrays have a third header field, for the array size.
You're correct, length is a data member, not a method.
From the Arrays tutorial:
The length of an array is established when the array is created. After creation, its length is fixed.
If you have an array of a known type or is a subclass of Object[] you can cast the array first.
Object array = new ????[n];
Object[] array2 = (Object[]) array;
System.out.println(array2.length);
or
Object array = new char[n];
char[] array2 = (char[]) array;
System.out.println(array2.length);
However if you have no idea what type of array it is you can use Array.getLength(Object);
System.out.println(Array.getLength(new boolean[4]);
System.out.println(Array.getLength(new int[5]);
System.out.println(Array.getLength(new String[6]);
Yes, it should be a field. And I think this value is assigned when you create your array (you have to choose the length of array while creating, for example: int[] a = new int[5];).
I believe its just a property as you access it as a property.
String[] s = new String[]{"abc","def","ghi"}
System.out.println(s.length)
returns 3
if it was a method then you would call s.length() right?
From the JLS:
The array's length is available as a
final instance variable length
And:
Once an array object is created, its
length never changes. To make an array
variable refer to an array of
different length, a reference to a
different array must be assigned to
the variable.
And arrays are implemented in the JVM. You may want to look at the VM Spec for more info.
It is a public final field for the array type. You can refer to the document below:
http://java.sun.com/docs/books/jls/third_edition/html/arrays.html#10.7
Every array in java is considered as an object. The public final length is the data member which contains the number of components of the array (length may be positive or zero)
Java arrays, like C++ arrays, have the fixed length that after initializing it, you cannot change it. But, like class template vector - vector <T> - in C++ you can use Java class ArrayList that has many more utilities than Java arrays have.

What would be the correct syntax for Collection.toArray()

Collection.toArray
We use the above method to convert a List<String> object to an equivalent String[].
List<String> foos = new ArrayList<String>();
// foos.toArray(new String[0]);
// foos.toArray(new String[foos.length]);
Which would be the right method to use in order to convert this into an Array.
This one:
foos.toArray(new String[foos.size()]);
Is the correct one to use. If you give toArray an array that is too short to fit the list into, toArray will allocate a new array instead of storing the elements in the array you supply. This means that Java will allocate two arrays instead of one and will waste a few clock cycles this way.
If you see the signature of the both functions you will clearly see whats the difference.
Object[] toArray();
The returned array will be "safe" in that no references to it are maintained by this collection. (In other words, this method must allocate a new array even if this collection is backed by an array). The caller is thus free to modify the returned array.
This method acts as bridge between array-based and collection-based APIs.
<T> T[] toArray(T[] a);
a the array into which the elements of this collection are to be stored, if it is big enough; otherwise, a new array of the same runtime type is allocated for this purpose.
String array[] = foos.toArray(new String[foos.size()]);
Note that it will also work with new String[0] but the array would need to be reallocated if foos.size() > 0.

Categories

Resources