Convert java.util.Collections to Integer array - java

When I run my code I get the following error:
Caused by: java.lang.ClassCastException: java.util.Collections$UnmodifiableSet cannot be cast to [Ljava.lang.Integer;
The code that causes is:
Integer[] selects = (Integer[]) tbl_analytes.getValue();
But when I do this:
Object obj = tbl_analytes.getValue();
System.out.println(obj);
I get the following output:
[1,7,15]
I don't understand why I can't convert this to an Integer[]. Any tips?

The Collection interface has methods to convert Collections to arrays :
Object[] toArray();
or
<T> T[] toArray(T[] a);
You can't just cast an object one one type to an unrelated type and expect it to work.
The fact that printing the Set produces an output that looks like the output you get when printing an array doesn't mean anything.

final ArrayList<Integer> integerList = new ArrayList<>();
final Integer[] integerArray = new Integer[integerList.size()];
integerList.toArray(integerArray);

It seems that 'tbl_analytes' is a Set, not an array. You can not cast it, you have to convert it:
Integer[] array = set.toArray(new Integer[0]);

You have to use the toArray(T a[])-method defined in the Collection interface, passing an empty Integer[] to the method. This solution assumes, that your List is of type List<Integer>. Otherwise, this would fail.

Set<Integer> values = (Set<Integer>) tbl_analytes.getValue();
The class cast exception gives the actual type. So use that or better a generalisation (List instead of ArrayList etcetera).

In the java language arrays are primitive. Collections are not.
Since a set is unordered it has no way to understand how to build an ordered array from a hashed set of memory locations.
When you output a set you are calling the toString method on that set.
So:
When I call
Integer[] selects = (Integer[]) tbl_analytes.getValue();
I get the following error:
Caused by: java.lang.ClassCastException: java.util.Collections$UnmodifiableSet cannot be cast to [Ljava.lang.Integer;
But when I do this:
Object obj = tbl_analytes.getValue();
System.out.println(obj);
I get the following output
[1,7,15]
The reason is Integer[] is completely uncastable from Set<Integer> but
the output from toString is derived from:
The java.util.Collections$UnmodifiableSet extends java.util.AbstractCollection
https://docs.oracle.com/javase/10/docs/api/java/util/AbstractCollection.html#toString()
Returns a string representation of this collection. The string representation consists of a list of the collection's elements in the order they are returned by its iterator, enclosed in square brackets ("[]"). Adjacent elements are separated by the characters ", " (comma and space). Elements are converted to strings as by String.valueOf(Object).
That is the resason you are getting the exception. The solution to it is answered here in this stack overflow question:
How to convert Set<String> to String[]?

Related

Is it possible to make a List of arrays?

I have 3 arrays, 2 arrays of the type int, and one array of the type String.
My question is, is it possible to make a List that contains those 3 arrays?
I want to be able to do something like this: myList.get(0) which should give me the first array in the List.
That is possible but which value to add arrays of different types in a List ?
You will have to declare a List<Object> or List<Object[]>. So you lose the benefit of type safety as you have to cast the array or the array elements to manipulate other things as Object variables.
For example :
List<Object[]> list = new ArrayList<>();
list.add(new String[5]);
list.add(new Integer[5]);
Object[] objects = list.get(0);
You is stuck with an Object[].
To manipulate a more specific type you will have to perform downcast :
String[] objects = (String[]) list.get(0);
This will work but you can make an error such as :
Integer[] objects = (Integer[]) list.get(0);
And you would have the information only as an exception at runtime.
Note that using the instanceof operator before downcasting the array will not prevent malfunctioning of the program.
For example this will not rise a ClassCastException as the conditional statement will be evaluated to false :
if (list.get(0) instanceof Integer[]){
Integer[] objects = (Integer[]) list.get(0);
...
}
But as consequence, it will never execute the processing. It is in a some way even worse as the issue could be not visible for the client.
And using a reversed logic will throw an exception as the initial code if the client uses incorrectly the list but is finally more verbose :
if (!(list.get(0) instanceof Integer[])){
... // throw exception
}
Integer[] objects = (Integer[]) list.get(0);
So definitely, you should forget the idea to add these arrays in a List.

misunderstanding the generic in java

I am trying to understand generics in Java.
private List<Own> l = new ArrayList<Own>();
I have the following error :
no instance of Typed array variable T exist so that List<Own> conform to T[]
when I pass it in a method (readTypedArray) that expects T[].
private List<Own> list = new ArrayList<Own>();
private OwnParceable(Parcel in) {
in.readTypedArray(list, CategoriesParceable.CREATOR);
}
The method in.readTypedArray() expects an array T[], but you passed a List<Own which is not an array.
List is not an array you can't use it where an array is expected, List is an interface which extends Collection while array is a data structure in Java, check Difference between List and Array for further details.
You can either declare an Own[]instead of List<Own> or convert this list into an array before passing it to the method, check Convert list to array in Java:
in.readTypedArray(list.toArray(new Own[list.size()]), CategoriesParceable.CREATOR);
This has nothing to do with generics - Lists and arrays are just two different things. If your method expects an array, you need to pass it an array, not a List:
Own[] arr = new Own[10]; // Or some size that makes sense...
in.readTypedArray(arr, CategoriesParceable.CREATOR);
There is a possibility to create an array filled with content of specified List. To achieve that you can call method toArray() of your list reference, for example:
Integer[] array = list.toArray(new Integer[list.size()]);

Different behaviour during converting a list of Strings to String array

I was working on Collection framework in Java , where i encountered a strange problem .
I made 2 lists of Strings 1 with the help of ArrayList while second was made using Arrays.asList(T ...).
After creation of these two list i tried to convert these lists into String arrays with the list.toArray() ,
as list.toArray() method call returns an object array , so i had to explicitly cast to String[] .
After casting some strange behaviour is happening as :
Case #1 : ( where list was created using ArrayList) , gives runtime exception as
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
Case 2 : (where list as created using Arrays.asList(T ... ) ) runs fine .
here is the code
String [] str = null ,str1 = null ;
List<String> list = new ArrayList<String>();
list.add("a");
List<String> list1 = Arrays.asList("a");
str = (String[]) list.toArray(); // Runtime Exception
str1 = (String[]) list1.toArray(); // Runs Fine
An ArrayList is backed by an Object[]. A copy of that array is returned with toArray().
Returns an array containing all of the elements in this list in proper
sequence (from first to last element).
It make no guarantees on the type of array returned. But we know this from the exception's message. If you want it to return a String[], use the overloaded method provided for this reason.
str = list.toArray(new String[0]);
The cast becomes unnecessary.
The List implementation returned by Arrays.asList maintains a reference to the array (implicit or explicit) passed as its variable arity argument.
Returns a fixed-size list backed by the specified array.
The invocation
List<String> list1 = Arrays.asList("a");
creates a String[] and passes that as the argument to asList. This isn't specified clearly by the API documention, but backed by seems to indicate that it will return that same array. (Looking at the implementation, it returns a clone.) Since it is a String[], there is no error when casting and assigning it to a variable of that type.
In both cases, the appropriate solution is to use the overloaded List#toArray(T[]).
For fun, run the following and check the type of array that is returned.
List<String> list1 = (List) Arrays.<Object> asList("a");
System.out.println(list1.toArray().getClass());
Don't make assumptions. Always rely on the API documentation. If it isn't clear, try to find a better solution.
The different calls to toArray are returning arrays with different component types. You can see this by running the following code:
List<String> list = new ArrayList<String>();
list.add("a");
List<String> list1 = Arrays.asList("a");
System.out.println(list.toArray().getClass());
System.out.println(list1.toArray().getClass());
On any version of Java 8 or earlier, the result is
class [Ljava.lang.Object;
class [Ljava.lang.String;
Basically this output means Object[] and String[] respectively.
However, this is a bug. See JDK-6260652. Although it's not stated very clearly, Collection.toArray() must return an Object[] and not an array of some subtype of Object. There are a couple reasons for this.
First is that Collection.toArray() was introduced in JDK 1.2, long before generics were added to the language. There was no possibility of any collection implementation returning anything other than Object[], so for compatibility, all collections' toArray() implementations must return Object[].
The second reason is that a rather offhand comment in the specification for toArray(T[]) says:
Note that toArray(new Object[0]) is identical in function to toArray().
which again requires toArray() to return Object[] and not an array of some other type.
This bug has been fixed in JDK 9. Running the code snippet above on a recent JDK 9 build gives the following output:
class [Ljava.lang.Object;
class [Ljava.lang.Object;
The fact that Arrays.asList("a") uses a String[] for internal storage is an implementation detail. The bug where toArray() returned something other than Object[] is this implementation detail leaking out. (In fact, the array is created by the varargs machinery, using the method's type parameter as the array component type. Arrays.asList() just wraps the array it's given.)
As others have said, if you want to control the component type of the returned array, use the other overload toArray(T[]):
String[] array = list.toArray(new String[0]);
String[] array1 = list1.toArray(new String[0]);
List<String> list = new ArrayList<String>();
list.add("a");
str = (String[]) list.toArray();
In this case your list invoke method toArray() of ArrayList class. Which looks like below, it returns Object []:
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
And elementData declare:
transient Object[] elementData;
And constructor method:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
And DEFAULTCAPACITY_EMPTY_ELEMENTDATA:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
There for, elementData is totaly Object [] and can't be casted to any type, String etc...
With Arrays.asList(T...), it returns java.util.Arrays$ArrayList class. And java.util.Arrays$ArrayList also has toArray() method. That subtle toArray() method makes some confuse :). Here is its implementation:
public Object[] toArray() {
return a.clone();
}
And finally a field declare:
private final E[] a;
java.util.Arrays$ArrayList.toArray() able to return Object [] and actually E []. Hope this will help you :)
The key here is that Arrays.asList(..) does not return a java.util.ArrayList, but instead it returns a java.util.Arrays$ArrayList. So the .toArray() methods vary slightly.
If you want the first case to return a String[], you can change the call to
str = list.toArray(new String[0]);

Collection.toArray() method, detail about it

Why would not it work?
List<String> lista = new ArrayList<>();
lista.add("Lol");
lista.add("ball");
String [] array = (String[])lista.toArray();
It throws a RunTimeException (ClassCastException), I am aware that there is another method for the purpose of returning the object contained in the List, however what is happening behind the scenes? I mean I am casting an array of Objects which actually is an array of Strings to an Array of Strings. So it should compile, but it does not.
Thanks in advance.
That version of toArray() returns Object[]. You can't cast an Object array into a String array even if all the objects in it are Strings.
You can use the lista.toArray(new String[lista.size()]); version to get the actual type correctly.
List.toArray()
returns an Object[], because of type erasure. At runtime your list does not know if it has String objects. From there you can see where that error is coming from.
You cannot type cast an Object[] into a String[]
Array of objects is not array of Strings and can't be cast to one.
Check this.
use toArray(T[] a) instead.
Ie.
List<String> lista = new ArrayList<String>();
lista.add("Lol");
lista.add("ball");
String [] array = lista.toArray(new string[1]);
This insures that toArray returns an array of type String[]
As others have noted, toArray() returns an array of type Object[], and the cast from Object[] to String[] is illegal.
List lista = new ArrayList<>(); ---> List lista = new ArrayList();
There are two toArray() versions.You can use another one!

why the cast is failing?

I am trying to do this
List<String> stringList = new ArrayList<String>();
stringList.add("one");
stringList.add("two");
stringList.add("three");
(String[]) stringList.toArray();
why does this gives me class cast exception ?
Caused by: java.lang.ClassCastException: [Ljava.lang.Object;
The reason why your code fails is because .toArray() returns an array of type Object[], which you cannot cast down into a String[]. To fix it, use the other toArray(T[] a) i.e.
stringList.toArray(new String[0]);
Better try this other method:
String[] stringArray = stringList.toArray(new String[stringList.size()]);
In that way the array returned is of the exact type that you need, no cast needed. The method you're invoking returns an Object[], not a String[] and the cast you're trying to perform is invalid.
Because toArray() method of List class returns Object[] not String[], and you cannot cast from Object[] to String[]. However, the right way to do it is:
String[] array = new String[stringList.size()];
stringList.toArray(array);
or:
String[] array = stringList.toArray(new String[stringList.size());
You cannot cast to a String array. You want:
String[] test = stringList.toArray(new String[stringList.size()]);
The ArrayList<T>.toArray() method returns an array of type Object, since that is a perfectly acceptable thing to do. In fact, because of type-erasure, it's the only thing it can do.
If you want to get an array of type String, then call the ArrayList<T>.toArray(T[]) method. In your case, you would call it like this:
stringList.toArray(new String[3]);
Calling it like that will stuff the ArrayList contents into the provided String array.

Categories