views:

2400

answers:

8

Hi! My question is: what is wrong with this conversion?

public int getTheNumber(int[] factors) {
    ArrayList<Integer> f = new ArrayList(Arrays.asList(factors));  
    Collections.sort(f);
    return f.get(0)*f.get(f.size()-1);
}

I made this after reading solution found in http://stackoverflow.com/questions/157944/how-to-create-arraylist-arraylistt-from-array-t-in-java
The second line (sorting) in getTheNumber(...) causes exception (Exception in thread "main" java.lang.ClassCastException: [I cannot be cast to java.lang.Comparable).
What is wrong here? I do realize that sorting could be done with Arrays.sort(), I'm just curious about this one. Thanks :)

A: 

this is from Java API "sort

public static void sort(List list) Sorts the specified list into ascending order, according to the natural ordering of its elements. All elements in the list must implement the Comparable interface. Furthermore, all elements in the list must be mutually comparable (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the list)."

it has to do with implementing the Comparable interface

CoDeR
A: 

As far as I understand it, the sort function in the collection class can only be used to sort collections implementing the comparable interface.

You are supplying it a array of integers. You should probably wrap this around one of the know Wrapper classes such as Integer. Integer implements comparable.

Its been a long time since I have worked on some serious Java, however reading some matter on the sort function will help.

Kevin Boyd
+1  A: 

Arrays.asList(factors) returns a List<int[]>, not a List<Integer>. Since you're doing new ArrayList instead of new ArrayList<Integer> you don't get a compile error for that, but create an ArrayList<Object> which contains an int[] and you then implicitly cast that arraylist to ArrayList<Integer>. Of course the first time you try to use one of those "Integers" you get an exception.

sepp2k
+3  A: 

You are trying to cast int[] to Integer[], this is not possible.

You can use commons-lang's ArrayUtils to convert the ints to Integers before getting the List from the array:

public int getTheNumber(int[] factors) {
    Integer[] integers = ArrayUtils.toObject(factors);
    ArrayList<Integer> f = integers.asList();
    Collections.sort(f);
    return f.get(0)*f.get(f.size()-1);
}
Rich Seller
+3  A: 

Use java.utils.Arrays:

public int getTheNumber(int[] factors) {
    int[] f = (int[])factors.clone();
    Arrays.sort(f);
    return f[0]*f[(f.length-1];
}

Or if you want to be efficient avoid all the object allocation just actually do the work:

public static int getTheNumber(int[] array) {
 if (array.length == 0)
  throw new IllegalArgumentException();
 int min = array[0];
 int max = array[0];
 for (int i = 1; i< array.length;++i) {
  int v = array[i];
  if (v < min) {
   min = v;
  } else if (v > max) {
   max = v;
  }
 }
 return min * max;
}
Tom
+4  A: 
Esko Luontola
+1  A: 

there are two cause of this exception:

1

Arrays.asList(factors) returns a List<int[]> where factors is an int array

2

you forgot to add the type parameter to:

ArrayList<Integer> f = new ArrayList(Arrays.asList(factors));

with:

ArrayList<Integer> f = new ArrayList<Integer>(Arrays.asList(factors));  

resulting in a compile-time error:

found   : java.util.List<int[]>
required: java.util.List<java.lang.Integer>
dfa
+1  A: 

I think you have found an example where auto-boxing doesn't really work. Because Arrays.asList(T... a) has a varargs parameter the compiler apparently considers the int[] and returns a List<int[]> with a single element in it.

You should change the method into this:

public int getTheNumber(Integer[] factors) {
    ArrayList<Integer> f = new ArrayList<Integer>(Arrays.asList(factors));  
    Collections.sort(f);
    return f.get(0) * f.get(f.size() - 1);
}

and possibly add this for compatibility

public int getTheNumber(int[] factors) {
 Integer[] factorsInteger = new Integer[factors.length];
 for(int ii=0; ii<factors.length; ++ii) {
  factorsInteger[ii] = factors[ii];
 }

 return getTheNumber(factorsInteger);
}
Robert Petermeier