Passing ArrayList to TreeSet constructor - java

When I am passing an ArrayList to TreeSet constructor, I am getting the following error:
Exception in thread "main" java.lang.ClassCastException: [I cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1294)
at java.util.TreeMap.put(TreeMap.java:538)
at java.util.TreeSet.add(TreeSet.java:255)
at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
at java.util.TreeSet.addAll(TreeSet.java:312)
at java.util.TreeSet.<init>(TreeSet.java:160)
at jay.week1.MaxPairwiseProduct.getMaxPairwiseProduct(MaxPairwiseProduct.java:8)
at jay.week1.MaxPairwiseProduct.main(MaxPairwiseProduct.java:17)
I am getting the above error at this line :
TreeSet<Integer> set = new TreeSet(Arrays.asList(numbers));
This is the full program:
import java.util.*;
public class MaxPairwiseProduct {
static int getMaxPairwiseProduct(int[] numbers) {
TreeSet<Integer> set = new TreeSet(Arrays.asList(numbers));
int max1 = set.pollLast();
int max2 = set.pollLast();
int result = max1 * max2;
return result;
}
public static void main(String[] args) {
int[] numbers = {1, 2, 3};
System.out.println(getMaxPairwiseProduct(numbers));
}
}
What is it that I am doing wrong?

What Arrays.asList() actually returning is list of int array.
List<int[]> list = Arrays.asList(numbers);
You need to do the following.
TreeSet<Integer> set = Arrays.stream(number).boxed()
.collect(Collectors.toCollection(TreeSet::new));

It is failing to do that because you can't have a TreeSet<int>, only a TreeSet<Integer>.
Because you did not specify a generic type for TreeSet, Arrays.asList tries to create a List<int[]>, which it succeeds. Why a int[]? You might ask. This is because int cannot be a generic type, so the generic parameter of asList is inferred to be int[], which can be a generic type. But then this list goes into TreeSet's constructor and TreeSet discovers that this is not a list of Integers, throwing an exception.
To fix this, you either change the parameter type from int[] to Integer[], or convert the int[] to a Integer[] before passing it into Arrays.asList.
TreeSet<Integer> set = new TreeSet<>(Arrays.stream(numbers).boxed().collect(Collectors.toList()));

Related

casting in method java [duplicate]

This question already has answers here:
What is a raw type and why shouldn't we use it?
(16 answers)
Closed 5 years ago.
I have problem with the toArray method. In this example i am using Integer and solved it by casting Integer, but the method should work for all types, without casting in main.
why cant i use one of these two in my main method?
arr = (T[]) a.toArray(arr) ;
or even
arr = a.toArray(arr)
I get a type mismatch: cannot convert from object[] to Integer[]
both size() and addFirst() works.
public static void main(String[] args) {
ArrayDeque a = new ArrayDeque(5);
a.addFirst(1);
a.addFirst(2);
Integer [] arr = new Integer[a.size()];
arr= (Integer[]) a.toArray(arr);
System.out.println(Arrays.toString(arr));
}
public class ArrayDeque<E> implements IDeque<E> {
private int counter= 0;
private E[] deque;
#SuppressWarnings("unchecked")
public ArrayDeque(int size) {
deque = (E[]) new Object[size];
}
public <E> E[] toArray(E[] a) {
return (E[]) Arrays.copyOf(deque, counter, a.getClass());
}
}
You are instantiating a raw type:
ArrayDeque a = new ArrayDeque(5);
change it to
ArrayDeque<Integer> a = new ArrayDeque<>(5);
This will remove the need to cast the returned array to Integer[].
P.S., it doesn't make sense for the toArray(E[] a) to define its own generic type parameter E. It should use the parameter defined in the class level.
You are instantiating a raw type when declaring the ArrayDeque a. You should parameterize it:
ArrayDeque<Integer> a = new ArrayDeque<Integer>(5);
a.addFirst(1);
a.addFirst(2);
Integer [] arr = new Integer[a.size()];
arr= a.toArray(arr);

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>.

Error with return-statement of generic type function

I am trying to make a generic function into which I pass an array (int[], String[]) and gets back the sorted version of it using TreeSort. I haven't even had the chance to begin to debug it since the mainclass refuses to accept an int[] array as the parameter.
TreeSort
public T[] treeSort(T[] arr) {
T[] result = (T[]) new Object[arr.length];
for (int i = 0; i < arr.length; i++)
if (arr[i] != null)
add(arr[i]);
Iterator it = iterator();
int count = 0;
while (it.hasNext())
result[count++] = (T) it.next();
return (T[]) result;
}
Main
BinarySearchTree<Integer> tree2 = new BinarySearchTree<>();
int[] unsortedNums = {6,3,7,4,1,2,9,8,5};
int[] sortedNums = tree2.treeSort(unsortedNums);
Error
The method treeSort(Integer[]) in the type BinarySearchTree is not applicable for the arguments (int[])
So I attempted to change unsortedNums and sortedNums from int to Integer (why should this matter?), and now running it yields this error:
Errorr 2
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
on line
T[] result = (T[]) new Object[arr.length];
In a generic method in Java, it is not allowed to create an array of the generic type. You are trying to circumvent this rule by creating an Object array and casting it to the generic type, but the compiler is too smart and prevents this. The reason for this rule is that the generic type could well be an Interface, so the runtime wouldn't know which class to create.
For your example, if you really need to keep the unsorted array as it is and return a copy (usually, sorting happens in-place so you would just edit the original array), you can either let the user pass the type of the generic (as in sp00m's answer), or let the user supply the destination array as a parameter so you don't need to create an array yourself.
IMO, the best practice here would be to make your sorting happen in place instead of returning a sorted copy of the data.
Instead of:
T[] result = (T[]) new Object[arr.length];
You have to use:
T[] result = (T[]) Array.newInstance(clazz, arr.length);
Where clazz is the type of the nested elements:
public T[] treeSort(T[] arr, Class<T> clazz) {...}
Finally, when calling, use the boxed primitive:
Integer[] unsortedNums = { 6, 3, 7, 4, 1, 2, 9, 8, 5 };
Integer[] sortedNums = treeSort(unsortedNums, Integer.class);
In Java, arrays know their component types at runtime (the component type is part of the actual runtime array type), and thus you need to specify the component type at runtime to create an array of that type.
#spoom's answer showed you how to create the array given a class object passed into the function. However, you actually already have that information without passing it separately. The parameter arr is of type T[], which means the array object's actual runtime type must be T[] or a subclass thereof. We can extract the component type from that and use it to create the new array:
T[] result = (T[]) Array.newInstance(arr.getClass().getComponentType(), arr.length);
This is how, for example, Arrays.copyOf() and related functions work.
You can't use primitive types (int) in generitcs. Try to use object wrapper, for example
Integer[] unsortedNums = {6,3,7,4,1,2,9,8,5};
Integer[] sortedNums = tree2.treeSort(unsortedNums);
Combining Generics and arrays is problematic in Java; check out the article Restrictions on Generics for details.
As to solving the problem, the easiest thing to do would be not using an array but rather a List. So for example:
public List<T> treeSort(List<T> list) {
List<T> result = new ArrayList<T>(list.size());
for (int i = 0; i < list.size(); i++)
if (list.get(i) != null)
result.add(list.get(i));
Iterator<T> it = list.iterator();
int count = 0;
while (it.hasNext())
result.set(count++, it.next());
return result;
}
Mind you, I haven't tested the logic.

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

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.

how to put contents of 2 integer array into 1 single arraylist?

I tried below code,
It works only for 1 array, when i try to add another, it throws an runtime exception
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(Unknown Source)
at java.util.AbstractList.add(Unknown Source)
at general.ArrToArrList.main(ArrToArrList.java:32)
The code is
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
public class ArrToArrList {
public static void main(String[] args) {
Integer[] nums = new Integer[5];
nums[0] = 2;
nums[1] = 4;
Integer[] nm = { 3, 5, 7 };
List intList = (Arrays.asList(nums));
List intList2 = (Arrays.asList(nm));
intList.addAll(Arrays.asList(nm));
for (Integer i : intList) {
System.out.println(i);
}
}
}
Read the actual contract for Arrays#asList(). It produces a List that is just a wrapper around the existing array and doesn't support any operations that would resize the array.
If you are wanting to combine the arrays, you need to create a new List object that is resizeable. Try
List<Integer> intList = new ArrayList<Integer>(Arrays.asList(nums));
intList.addAll(Arrays.asList(nm));
Arrays.asList returns a fixed sized List. i.e. no elements can be added or removed. Wrap the result of asList in a new ArrayList to allow elements to be added
List<Integer> intList = new ArrayList<>(Arrays.asList(nums));
Arrays.asList wraps an array to appear as a List. An array cannot be grown, or shrunk and so you cannot add or remove elements from this list.
Perhaps what you intended was
List<Integer> intList = new ArrayList<Integer>(Arrays.asList(nums));
Lists created using Arrays.asList have a fixed size and thus you can't add other elements to the list. You could create a new normal ArrayList and add all elements to the list, like this:
Integer[] nums = new Integer[5];
nums[0] = 2;
nums[1] = 4;
Integer[] nm = { 3, 5, 7 };
List intList = (Arrays.asList(nums));
List intList2 = (Arrays.asList(nm));
List mergeList = new ArrayList();
mergeList .addAll(Arrays.asList(nums));
mergeList .addAll(Arrays.asList(nm));
for (Integer i : mergeList) {
System.out.println(i);
}
if you use
List intList = (Arrays.asList(nums));
it gives the actual object of type java.util.Arrays$ArrayList which has the implementation as
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
but if you use
List intList = new ArrayList<Integer>(Arrays.asList(nums);
it will give you a actual object of type java.util.ArrayList . This makes the difference . This is actually the reason to the cause of this Exception
Arrays.asList returns an fixed size view of the underlying array:
Returns a fixed-size list backed by the specified array.1
You cannot put more elements into the returned List than there were in the array.
You need to copy that into a java.util.ArrayList (confusingly Arrays.asList returns a java.util.Arrays.ArrayList which is not the same thing.)
final List<Integer> list = new ArrayList<Integer>(Arrays.asList(myArray));
The list you get from Arrays.asList isn't mutable. So you need to assign it to intList using the new operator.

Categories