When I implement a Collection using generics that holds primitive arrays within Java what is actually stored within the array? Using generics to define collections means that I can only store an Object and if I were to do ArrayList<Integer> I can add an int but this is autoboxed into Integer.
If I were to define ArrayList<int[]> its perfectly legal as arrays are objects. I'm unsure though if what I actually end up with stored in the collection is Integer[] as the compiler performs some transformations and will use autoboxing to add to the array or if I can store int[] and the collection will store the primitive array as the array itself is an object.
ArrayList<int[]> will store arrays of primitives. There will be no autoboxing involved.
In Java, an array of any type -- primitive or not -- is an object and is therefore compatible with generics.
It is even possible to inadvertently end up with a container of int[], as illustrated by this fun question from yesterday: Java containsAll does not return true when given lists
int[] never be boxed to Integer[].Arrays are always reference types, so no boxing is required.
Java always tackle Arrays as a object either it is a primitive array or Object array.Here is a little detail about arrays of primitives and objects.For further detail please see Arrays of Primitive Values and objects.I also suggest you to see this question Java: Array of primitive data types does not autobox
Related
Can I dynamically allocate a primitive type variable, say int? I can't see how this could be done other than to wrap it into an object Integer or into a single-element array int[1].
I tried:
int i = new int(5);
Is it forbidden? If so, why?
EDIT
Possible (theoretical) application - creating a collection-like data structure for storing primitive types.
Is there no any short cut to do this nicely?
That ugly two loops (One loop to read the pmList and second loop to add to the markupArray) is the only option (Instead of ArrayUtils).
ArrayList<Double> pmList = new ArrayList<Double>();
pmList.add(0.1); // adding through a loop in real time.
pmList.add(0.1);
pmList.add(0.1);
pmList.add(0.1);
double[] markupArray = new double[pmList.size()];
arkupArray = pmList.toArray(markupArray); // This says The method toArray(T[]) in the type ArrayList<Double> is not applicable for the arguments (double[])
Simply use a Double[] array, instead of double[] then everything works fine. If you know the size of the list ahead of time, you can also skip the list and insert directly into the array. It might even be worth to traverse the input two times: Once for retrieving its size and once for insertion.
Auto boxing only works for primitive types, not for arrays of primitive types. A double[] array is no T[] array, since a type parameter T must always be an Object. While a double may be autoboxed to T (with T=Double), a double[] cannot be autoboxed to T[].
The reason why arrays are not autoboxed is probably that this operation would be very costly: Boxing an array means creating a new array and boxing each element. For large arrays, this has a huge performance hit. You don't want such a costly operation to be done implicitly, hence no autoboxing for arrays. In addition, boxing a complete array would yield a new array. Thus, when writing to the new array, the changes would not write through to the old array. So you see, there are some semantics problems with array-boxing, so it is not supported.
If you must return a double[] array, then your must either write your own function or use a third-party library like Guava (see msandiford's answer). The Java Collections framework has no methods for (un)boxing of arrays.
You could use TDoubleArraList or guava's primitive list collection.
You could also determine the size in advance in one loop and add the values in another.
Why not make your own shortcut?
static double[] doubleListToArray(List<Double> list) {
int k = 0;
double[] result = new double[list.size()];
for(double value : list)
result[k++] = value;
return result;
}
Google guava has Doubles#asList(...) and Doubles#toArray(...) which provide conversions from double[] to List<Double> and from Collection<? extends Number> to double[] respectively.
You are right that this is not very intuitive at first look. However, this limitation is related to the way the Java language implements generic types and auto-boxing:
Generic types are erased at runtime. This implies that any ArrayList<Double> is represented by a single compiled Java class ArrayList which is shared with other generic representations of ArrayList such as for example ArrayList<String>. As a consequence, the compiled method ArrayList::toArray does not (and must not) know what generic type an instance represents as the single compiled method must be applicable for any generic type. As the elements could therefore be anything like String or Double, you need to provide an array to the method. The method can then check the type of the target array at runtime and check the elements that are filled into the array at runtime to be assignable to the array's component type. All this logic can be implemented by a single compiled method.
Secondly, auto-boxing and -unboxing is something that only exists at compile time. This means that the statements
Integer i = 42;
int j = i;
are compiled as if you wrote
Integer i = new Integer(42);
int j = i.intValue();
It is the Java compiler that adds the boxing instructions for you. The Java runtime applies a slightly different type system where boxing is not considered. As a consequence, the single compiled method ArrayList::toArray that we mentioned in (1) cannot know that this boxing needs to be applied as we argued that the method must be applicable for any type T which might not always represent a Double.
In theory, you could alter the implementation of ArrayList::toArray to explicitly checks if an array's component type and a lists element type are applicable for unboxing but this approach would result in several branches which would add quite a runtime overhead to the method. Rather, write a small utility method that specializes on the Double type and applies the implicit unboxing due to the specialization. An iteration over all list items suffices for this purpose, this is how the ArrayList::toArray is implemented as well. If your array is small, consider to use an array of boxed values Double[] instead of double[]. If your array is however large, lives long or you are restrained to primitive types in order to comply to a third-party API, use the utility. Also, look out for implementations of primitive collections if you want to ungo the overall boxing. With Java 8, use a Stream in order to inline the array conversion.
If arrays are treated as objects in Java and if we have a multidimensional array like an array of integer arrays then is it correct to say that this multidimensional array is also an array of objects?
I am kinda confused as I have read that arrays can hold only two types i.e. either primitives or references so if an array holds an array will it be correct to regard the same a array of objects?
Is it correct to say that this multidimensional array is also an array of objects?
Yes, that is correct. An array is an object. So, an array of arrays, is an array of objects.
Yes it is correct because arrays are objects
Arrays are not treated as objects, they are objects.
Multidimensional arrays are "arrays of arrays". You can get more information here http://www.ensta-paristech.fr/~diam/java/online/notes-java/data/arrays/arrays-2D-2.html
So it is also possible to create multi-dimensional arrays which are not square and so on
Yes, your reasoning is correct. When we say "array of objects" in Java we generally mean "array of references to objects", so when we have something like
int[][] x = ...;
then x is an array holding references to int[]s (i.e. int arrays).
From the JLS ยง10:
The component type of an array may itself be an array type. The components of such an array may contain references to subarrays. If, starting from any array type, one considers its component type, and then (if that is also an array type) the component type of that type, and so on, eventually one must reach a component type that is not an array type; this is called the element type of the original array, and the components at this level of the data structure are called the elements of the original array.
There are some situations in which an element of an array can be an array: if the element type is Object or Cloneable or java.io.Serializable, then some or all of the elements may be arrays, because any array object can be assigned to any variable of these types.
I'm doing a project in Java in which I'm looking at the frequency characters occur after each other character in a text. When I'm collecting my results, I'm storing them in a 2d array of ints. However, in the same results table, I want to store some results about the whole thing.
Is it possible to have an array where some of the elements are arrays, and others are primitives?
Yes, you can have Object[] and store a mix a types, although it would have to be the wrapper Integer (not the primitive int). (Note: you could "cheat" and save each int as a single-element array int[], thus making it an Object, but "don't try this at home")
But even if you could, an array isn't the right approach. Instead, create a class for this.
Try something like this:
public class FrequencyAnalysis {
private int[] frequencies;
private String info;
private Date lastRun;
// etc
}
No, it is not working. There can only be objects OR primitives in one array. Anything else is just a workaround.
In that case you would have to store Objects (primitives will autobox to Wrapper classes) and then when you read the entries you would need to instanceof the Object and then cast it safely.
You can use boxed types, i.e. java.lang.Integer (So your array type must be Object[]), but better do make a new class for results Storage
Can someone explain to me the usage of Integer, Boolean etc in place of their primitive types in JAVA?
I can't seem to grasp the advantages their are providing. They seem to create unnecessary problems of handling null values.
Thanks!
Boolean, Integer, Long, ... are Objects. You can use them in places where you can't use primitive types, e.g.
storing them in a Collection like a Map
using them as template parameter
assigning them a null value
using them in a more general way (e.g. Long as Number)
Examples:
new ArrayList<Integer>();
Long id = null;
Number num = new Long( 3 );
The rationale for Integer, Boolean, and so on is to allow primitive types to be used in contexts that require a reference type. The classic use-case is the collection APIs which provide sets, lists, maps, queues and so on where the element type must be some reference type.
Thus I can write:
List<Integer> list = new ArrayList<Integer>();
but the following is a compilation error:
List<int> list = new ArrayList<int>();
Note that this use-case for the primitive wrapper types predates both generic types and the "new" collections APIs, and goes back to the days where the only collection types were the original (pre-generic) forms of Vector and Hashtable, and their ilk.
Sometimes you really need a value to be nullable, for instance if your app stores user data, a social security # may be unknown. In that case it's cleaner to store null instead of -1.
Also there are things you can't do with primitive types, like storing them in a map or using polymorphism (Double and Integer both are instances of Number).
primitives are always faster.
however there are times, when objects are really useful:
1. upcasting. Your function can take Number(is a parent for all numeric objects: Integer, Float, etc.) for an argument.
2. Possible null value. For example it is used while storing in database. Object can be null, primitives must have value. So if field in db is nullable, it is better to use object version of primitive value.
3. if function takes object and you always give it a primitive there are expenses on autoboxing(turning primitive into object). The same for returning from function.
4. Objects have certain methods, such as getHashcode(), toString() etc., which can be really useful in some cases.