Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer; - java

The map function simply iterates through the integer array and applies function to it and then adds it to an output array. I'm getting this error and I can't seem to find where it's casting an Object to an Integer. The map function returns an Integer array and is sent to printArray which takes an Integer array. Any ideas?
public static void main(String[] args)
{
Function<Integer,Integer> function = new CalculateSuccessor<Integer,Integer>();
Integer[] integerArray={1,3,4,2,5};
printArray(map(function, integerArray));
}
I've removed the rest of the code because the solution was found to be the <Integer, Integer> after Function.

its because you use generics Function<Integer,Integer> guava is trying to cast the values you pass as to Integer but you actualy pass Object.

I assume that your printArray method expects an Object[]
An Object[] is not an definition of a "super" instance of Integer[] even if Object is a super class of Integer.
Assume this code was valid:
Object[] array = new Integer[10];
then this would also be valid
array[0] = new Car("Mercedes");
But the latter should not be possible. Hence the "inheritance" restriction on arrays.
Same goes for list for example
List<Object> myList = new ArrayList<Integer>();
It will give you a compiler error.

Related

Convert Collection to int[] array

There are two existing methods named getDetails(...). One expects a minimum of one mandatory parameter and the other expects a collection (doesn't validate the content/size of the collection).
The problem is that the collection is sometimes passed as empty and according to my business case, I always expect a minimum of one value, to be passed. So, I need to make that method private, which accepts Collections.
// There are two params, to make sure that at-least one is passed by the caller
public static CustomerContext getDetails(int id, int... ids) {
Collection<Integer> idCollection = Instream.of(ids).boxed().collect(Collectors.toSet());
if(!idCollection.contains(id)){
idCollection.add(id);
}
return getDetails(idCollection);
}
I'm planning to make the below method scope to private so that the callers would not call this method with Zero attributes.
public static CustomerContext getDetails(Collection<Integer> idCollection) {
return getDetails(idCollection,false);
}
One of the caller methods is passing Collection object to getDetails like below,
CustomerContext.getDetails(id.getDetails().values());
The id.getDetails() is as below,
public Map<Id,Integer> getDetails(){
return Collections.unmodifiableMap(details);
}
I'm looking for a way to convert the collection id.getDetails().values() into int[] for passing to getDetails(int id,int... ids) instead of calling getDetails(Collection<Integer> idCollection).
I could cast the collection to Integer[] as below,
(Integer[])id.getDetails().values().toArray()
I did not find a way to cast Collection to int[].
Any suggestions would be of great help.
I already referred to some of the existing questions but did not succeed to solve my issue:
Conversion of collection to int array
Convert java.util.Collections to Integer array
Collection to Integer[]
When you need to get a result of type Integer[], you have to provide a function as an argument while calling toArray(), there's no need to apply casting (if you're not passing a parameter toArray() returns an array Object[]).
Integer[] arr = id.getDetails().values().toArray(Integer[]::new);
Collection to int[]
There's no way convert a Collection of Integer type or an array Integer[] into an array int[] directly. It's not possible to obtain one from another simply by doing casting, these types are not compatible.
You have to iterate over the source and populate the newly created int[] array. It can be done either "manually" using a loop, or in a more convenient way with streams, the overall approach doesn't change.
That's how it can be done using Stream API:
int[] arr = id.getDetails().values().stream() // Stream<Integer> - stream of objects
.mapToInt(Integer::intValue) // IntStream - stream of primitives
.toArray();
You can't cast Collection<Integer> to int[], but you can create the array:
int[] values = id.getDetails().values().stream()
.mapToInt(n -> n)
.toArray();
An aside... this code:
if (!idCollection.contains(id)) {
idCollection.add(id);
}
May be changed to just:
idCollection.add(id);
because idCollection is a Set and that's how sets work. It matters not that it's declared as a Collection; it is a Set.

Convert generic arraylist to non-generic using Java 8 Stream

I have some old code I'm trying to streamline:
ArrayList arr = (generic arraylist)
int[] newArr = new int[arr.size()];
for(int i=0; i<arr.size(); i++){
newArr[i]=(int)arr.get(i);
}
I want to use the Java Stream API to simplify this. Here is my attempt:
ArrayList arr = (generic arraylist)
List<Integer> = arr.stream().map(m -> (int)m).collect(Collectors.toList());
My understanding is that it would iterate through arr, typecast every object m to an int, and then collect it into a List. But my compiler says that the right-hand-side of the second line returns and Object and not a List. Where am I going wrong?
Per your attempt, it looks like you want to map your ArrayList to an ArrayList<Integer>. The good news is, you don't need to do any of this. The runtime type of ArrayList<Integer> is just ArrayList (this is called type erasure if you want to search for information about it). Only the compiler knows about the parameterized type.
So this code does what you want:
import java.util.ArrayList;
public class Cast {
public static void main(String[] args) {
// This represents the ArrayList of Integer in your existing code
ArrayList raw = new ArrayList(java.util.Arrays.asList(
Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)
));
// You know what it is, so all you need to do is cast
ArrayList<Integer> typed = (ArrayList<Integer>)raw;
// Still works; now recognized as list of integer
for (Integer x : typed) {
System.err.println(x);
}
}
}

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()]);

java.lang.ClassCastException:[I cannot be cast to java.lang.Integer

public class Solution {
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int l1=Integer.parseInt(br.readLine());int count=0;
String l2=br.readLine();
String[] a=l2.split(" ");int[] no=new int[l1];
for (int i=0;i<l1;i++) {
no[i]=Integer.parseInt(a[i]);
}
List list=Arrays.asList(no);
Set<Integer> set=new LinkedHashSet<Integer>(list);
***for (int integer : set) {***
count=Math.max(count, Collections.frequency(list, integer));
}
}
}
I get java.lang.ClassCastException:
[I cannot be cast to java.lang.Integer at Solution.main(Solution.java:23) at the highlighted part of the code. What is the reason for this?
You are trying to initialize a set from an array of primitive integers. When you do this
List list=Arrays.asList(no);
since List is untyped, you construct a list of integer arrays; this is definitely not what you are looking for, because you need List<Integer>.
Fortunately, this is very easy to fix: change declaration of no to
Integer[] no=new Integer[l1];
and construct list as follows:
List<Integer> list = Arrays.asList(no);
Everything else should work fine.
Set<Integer> set=new LinkedHashSet<Integer>(list); produce unchecked warnings. This masks that the correct generic type of list is List<int[]>, so set contains not Integers as intended, but arrays of ints. That's what is reported by ClassCastException: int[] (referred as [I) cannot be cast to Integer.
The simplest way to fix this code is to declare no as Integer[], not int[]. In this case, Arrays.asList will return correctly-typed List<Integer>.

Why java does not autobox int[] to Integer[]

When I do the following,
arrayList1 - contains one element and it is an int[].
arrayList2 - not compiling (Error : The constructor ArrayList<Integer>(List<int[]>) is undefined)
arrayList3 - contains 7 elements and they are Integer objects
Here's the code:
int[] intArray = new int[]{2,3,4,5,6,7,8};
ArrayList arrayList1 = new ArrayList(Arrays.asList(intArray));
ArrayList<Integer> arrayList2 = new ArrayList<Integer>(Arrays.asList(intArray));
Integer[] integerArray = new Integer[]{2,3,4,5,6,7,8};
ArrayList<Integer> arrayList3 = new ArrayList<Integer>(Arrays.asList(integerArray));
Question :
Why doesn't the compiler auto-box the elements in the int[] to Integer and create an ArrayList<Integer>? What is the reason behind this? Is that my stupidity or some other reason?
The difference is int[] is itself an Object, whereas Integer[] is an array of references to Integer object.
Arrays.asList(T...) method takes variable arguments of some type T with no upper bounds. The erasure of that method is Arrays.asList(Object...). That means it will take variable number of arguments of any type that extends from Object.
Since int is not an Object, but a primitive type, so it can't be passed as individual element of T[], whereas int[] is an Object itself, it will go as first element of the T[] array (T... internally is a T[] only). However, Integer[] will be passed as T[], with each reference in Integer[] passed as different argument to T[].
And even if you would argue that compiler should have done the conversion from each element of int[] array to Integer, well that would be too much work for the compiler. First it would need to take each array element, and box it to Integer, then it would need to internally create an Integer[] from those elements. That is really too much. It already has a direct conversion from int[] to Object, which it follows. Although I have always wished Java allowed implicit conversion from int[] to Integer[], that would have made life simpler while working with generics, but again, that's how the language is designed.
Take a simple example:
Object[] array = new Integer[10]; // this is valid conversion
Object[] array2 = new int[10]; // this is not
Object obj = new int[10]; // this is again a valid conversion
So, in your code Arrays.asList(intArray) returns a ArrayList<int[]> and not ArrayList<Integer>. You can't pass it to the ArrayList<Integer>() constructor.
Related:
int[] and Integer[]: What is the difference?
An int[] is not the same as an Integer[].
An array has as associated Class object. The class object for an array of primitive ints is [I. The class object for an array of Integer is [Ljava/lang/Integer.
An array is itself an object, so converting between two objects of the same type is an identity conversion. Converting between two different typed objects isn't - and int[] and Integer[] are definitely different, as evidenced by the bytecode above.
Lastly, bear in mind that autoboxing would only really apply if there was an associated boxing conversion.
Technically it is possible to do it of course. However autoboxing/unboxing of primitive type array to wrapper type array is more than what you expect.
First look into the auto-boxing/unboxing of Java: What it does is simply a syntax sugar to save you typing the primitive wrapper code. e.g.
Integer i = 10;
Compiler knows that it is expecting an Integer, but int present instead. Therefore what the compiler doing is translating your code to:
Integer i = Integer.valueOf(10);
It does similar thing for unboxing: when in situation that it expects int but Integer is present, compiler replace it with varName.intValue()
Back to array. There are two problems we can forsee:
The first problem is, there is no straight-forward way to transform from an int array to an Integer array. You may argue that the compiler can transform
int[] intArray = ....;
Integer[] wrapperArray = intArray ;
to
Integer[] wrapperArray = new Integer[intArray.size()];
for (int i = 0; i < intArray.size(); i++) {
wrapperArray[i] = Integer.valueOf(intArray[i]);
}
but that seems too much for a syntax sugar.
The second big problem is, when you are passing it as a parameter to a method, if autoboxing/unboxing happens for array, instead of reference of original array is passed, you are now passing the reference of a copy of the original array. In case you are changing the content of array in your method, the original array will not be affected. That can bring you lots of surprises.
e.g.
void foo(Integer[] arr) {
arr[0] = 0;
}
// invoking foo in some code:
int[] intArr = new int[]{9,8,7,6};
foo(intArr);
// intArr[0] will still be 9, instead of 0
Because int[] and Integer[] both are objects. First will hold primitive int values, which are not of type Object while second will store references of Integer objects, which are of type Object.
arrayList1 is really a List of size one.
http://ideone.com/w0b1vY
arrayList1.size() = 1
arrayList3.size() = 7
The int[] is being cast to a single Object. That Object cannot be cast to Integer.

Categories