Unchecked warnings for Arraylist - java

Why am I getting these 4 warnings from -Xlint and what should I do about them? I'm just starting in Java, so am likely missing something obvious.
import java.util.*;
class CompareGerbils implements Comparator {
public int compare(Object o1, Object o2) {
return ((Gerbil)o2).number() - ((Gerbil)o1).number();
}
}
class Gerbil {
int gerbilNumber;
Gerbil(int gN) {
gerbilNumber = gN;
}
int number() {
return gerbilNumber;
}
}
public class lt {
public static void main(String[] args) {
// I'd like to be able to add both ints and strings to list
ArrayList list = new ArrayList();
//unchecked call warning:
list.add(1);
//unchecked call warning:
list.add("b");
ArrayList<Gerbil> gerbillist = new ArrayList<Gerbil>();
for(int i = 0; i < 5; i++) {
gerbillist.add(new Gerbil(i));
}
//unchecked conversion warning
//unchecked method invocation
Collections.sort(gerbillist, new CompareGerbils());
}
}
EDIT: replies so far have answered the Arraylist declaration. How about the sort warnings at the bottom of the code? thanks

You're getting this because you have not defined a data type for the ArrayList list. The only way to add both Strings and Integers in list without getting warnings is by defining it as ArrayList<Object> list - which is what happens here implicitly (line list.add(1); is implicitly converting 1 to new Integer(1) - this is called autoboxing). Also note that if you want to have both Strings and Integers in lists, the sorting method does not really make sense - how are you expecting things to get sorted, alphabetically or numerically?
Edit: Also, it is not considered good practice to declare a concrete type (i.e. ArrayList<Object> list) unless you have very good reasons to do so. It is recommended that you initialise using an interface, i.e. List<Object> list.
So, your code would have to be like this (note the part Comparator<Gerbil> which fixes the warning in Collections.sort):
// I'd like to be able to add both ints and strings to list
List<Object> list = new ArrayList<Object>();
list.add(new Integer(1));
list.add(new String("b"));
List<Gerbil> gerbillist = new ArrayList<Gerbil>();
for(int i = 0; i < 5; i++) {
gerbillist.add(new Gerbil(i));
}
Collections.sort(gerbillist, new Comparator<Gerbil>() {
public int compare(Gerbil o1, Gerbil o2) {
int diff = o1.getNumber() - o2.getNumber();
if (diff > 0)
return 1;
else if (diff <0)
return -1;
else
return 0;
}
});
With respect to the Gerbil class, I suggest you use the form getNumber as a method name rather than number - it's a de facto standard for method names to retrieve the value of a member variable (and, respectively setNumber(int value) for setting it):
class Gerbil {
int gerbilNumber;
Gerbil(int gN) {
gerbilNumber = gN;
}
int getNumber() {
return gerbilNumber;
}
}

The warning occurs when you are using a non-generic type in a context where a generic is expected. The compile is saying, you might be right, but I cannot check the type for you.
You cna either;
Make the type the correct generic.
Turn off the warning with #SuppressWarnings
Ignore the warning.
EDIT: In this example, you have to pick a super class/interface of the elements in the list.
// I'd like to be able to add both ints and strings to list
List<Object> list = new ArrayList<Object>();
list.add(1);
list.add("b");
Instead of Object you could pick Seralizable or Comparable however eneither is likely to be useful. Indeed a List<Object> is rarely useful except in exercises.
The correct way to implement the Comparator is to use comparison. Using - is only valid if you know this cannot possibly overflow. e.g. 2000000000 - -2000000000 < 0 whereas you might expect 2000000000 - -2000000000 > 0
class CompareGerbils implements Comparator<Gerbil> {
public int compare(Gerbil a, Gerbil b) {
return a.number() > b.number() ? +1
: a.number() < b.number() ? -1 : 0;
}
}
For testing purposes I suggest trying to sort a List which is not already sorted. A simple way to do this is to use the shuffle() method. This could still be sorted but the large the list, the less likely that is the case.
Collections.shuffle(gerbillis);

public static void main(String[] args) {
final List<Object> list = new ArrayList<Object>();
list.add(1);
list.add("b");
final List<Gerbil> gerbillist = new ArrayList<Gerbil>();
for (int i = 0; i < 5; i++) {
gerbillist.add(new Gerbil(i));
}
Collections.sort(gerbillist, new CompareGerbils());
}

you need to know Generics http://download.oracle.com/javase/1.5.0/docs/guide/language/generics.html
you are trying to add primitive and a string in arraylist.
either u do this to take anything
List<Object> list = new ArrayList<Object>();
or if you want to allow only strings
List<String> list = new ArrayList<String>();

Related

Error : Type mismatch: cannot convert from List<Integer> to ArrayList<Integer>

package set01;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class DFTList {
static List<Integer>[] list;
static boolean[] visited;
public DFTList(int nodes) {
list = new ArrayList[nodes];
visited = new boolean[nodes];
for(int i=0;i<nodes;i++) {
list[i] = new ArrayList<>();
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter no. of nodes : ");
int nodes = scan.nextInt();
DFTList obj = new DFTList(nodes);
System.out.println("Enter no.of vertex : ");
int vertex = scan.nextInt();
for(int i=0;i<vertex;i++) {
int v1 = scan.nextInt();
int v2 = scan.nextInt();
list[v1].add(v2);
list[v2].add(v1);
}
solve(0);
}
public static void solve(int a) {
visited[a] = true;
ArrayList<Integer> l = list[a];
}
}
In the above code snippet, At the DFTList constructor, I have inserted ArrayList object at all the indices of the array. But when I try to retrieve the same object at the solve method and store it under the same reference, I encountered an error stating that "Type mismatch: cannot convert from List to ArrayList". Why does this error occur?
The list variable is a List<Integer>[], which means that any type of List (ArrayList, LinkedList, etc.) could be stored in it. When retrieving an element from this list, all the Java compiler knows is that it's some type of List; it doesn't know the specific type of List (even though you as the programmer know that you're only storing ArrayList items in the array). Therefore, ArrayList<Integer> l = list[a] is a compilation failure because the compiler can't guarantee that the element retrieved from the array is an ArrayList and not a different List type.
There are a few ways to address this issue. Assuming you wanted to keep list as an array, the most idiomatic approach would be to change its type to List<Integer>[] instead of ArrayList<Integer>[]. Since you are not using any methods or other API specific to ArrayList, the List interface is a better choice for this type.
public static void solve(int a) {
visited[a] = true;
List<Integer> l = list[a];
}
Another, less idiomatic approach would be to change the type of the list variable from List<Integer>[] to ArrayList<Integer>[]. This change would cause your variable assignment to work as already written.
public class DFTList {
static ArrayList<Integer>[] list;
...
}
The final approach you could use when you have an array of the interface type (List<Integer> in this case) would be to cast the element to the concrete type when storing it to the variable. This is basically telling the compiler that you as the developer know the element is of that subtype, so even though it cannot guarantee the assignment, it will allow it to happen. This approach defers the type checking — ensuring the List is the ArrayList subtype — until the code is actually run (at runtime). If the stored element is a subtype other than ArrayList when the code is run (e.g. if it's a LinkedList), then Java will throw a ClassCastException since the assignment to ArrayList cannot happen.
Casting like this is not ideal, as it removes guarantees by the compiler that all types being used are guaranteed to be valid at runtime. However, there are times where it is necessary and appropriate.
public static void solve(int a) {
visited[a] = true;
ArrayList<Integer> l = (ArrayList<Integer>) list[a];
}
list is declared as a List<Integer>[] (read: an array of Lists of Integers). The fact that the value in each element is actually an ArrayList is inconsequential - as far as the compiler is concerned, every element is a List.
You could either explicitly downcast the array access:
ArrayList<Integer> l = (ArrayList<Integer>)list[a];
Or, more idiomatically, if you aren't relying on any specific method ArrayList has that isn't present in the List interface, you could declare l as a List<Integer>:
List<Integer> l = list[a];
you are mixing C++ with Java!!
check the following reproducable code:
public class DFTList {
static List<Integer>[] list;
static boolean[] visited;
public DFTList(int nodes) {
list = new ArrayList[nodes];
visited = new boolean[nodes];
for(int i=0;i<nodes;i++) {
list[i] = new ArrayList<>();
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter no. of nodes : ");
int nodes = scan.nextInt();
DFTList obj = new DFTList(nodes);
System.out.println("Enter no.of vertex : ");
int vertex = scan.nextInt();
for(int i=0;i<vertex;i++) {
int v1 = scan.nextInt();
int v2 = scan.nextInt();
list[v1].add(v2);
list[v2].add(v1);
}
solve(0);
}
public static void solve(int a) {
visited[a] = true;
List<Integer> l = list[a];
}
}
Note 0
there is no pointer like concept in java therefore following snippet gives you compile time error:
* list[i] = new ArrayList<>();
Note 1
you are assigning List interface to l type therefore use below syntax.
List<Integer> l = list[a];

Creating a generic method to work on Collection Java to alter content of ArrayList

I want to create a generic method which can take ArrayList of Integer, Float, or any type which extends Number.
public void mulBy2(ArrayList<? extends Number> list) {
// I want to multiply the value of each element in list by 2
// and store it back in list
for(int i = 0; i < al.size(); i++) {
Double d = al.get(i).doubleValue()*2;
al.set(i,d); // Obvious error here says required ? extends Number
// how to solve this issue
}
}
if list was ArrayList with values [2,3,4] , my method should return or make the arrayList with values [4,6,8]
ArrayList with initially [1.2,3.4] should convert to [2.4,6.8]
We do not want to do your homework, but I think the question should be answered because it can be useful for future visitors. The solution should include the following:
iterate the elements
get the class of the current element
call the corresponding method to the class of the current element to get its value, so if it is Integer, invoke the intValue of the object via reflection, multiply it with 2 and set the corresponding element of the list to the new value
Useful to know:
Corresponding methods are: intValue, longValue, floatValue, doubleValue, byteValue and shortValue, the names of the classes more-or less correlate to them, like Double, Float, etc. See here: https://docs.oracle.com/javase/7/docs/api/java/lang/Number.html
You can get the class of an Object by calling its getClass method. Its name can be obtained by calling the getEnclosingClass of the resulting class. Example:
Class<?> enclosingClass = getClass().getEnclosingClass();
if (enclosingClass != null) {
System.out.println(enclosingClass.getName());
} else {
System.out.println(getClass().getName());
}
With reflection you can call invoke to call a method. Example:
Class<?> c = Class.forName("class name");
Method method = c.getDeclaredMethod("method name", parameterTypes);
method.invoke(objectToInvokeOn, params);
Good luck!
1. A <Number> list filled with Double-s
Here is a quick fix:
public void mulBy2(List<Number> list) {
for (int i = 0; i < list.size(); i++) {
Double d = list.get(i).doubleValue()*2;
list.set(i,d);
}
}
The fix consists of the following changes:
It's totally okay expect a List<Number>. A List<Number> can hold any mix of number, e.g. Integer, Float, BigDecimal.
It's better to code to a interface, e.g. List and not to an implementation, ArrayList.
Now we can simply add back the Double numbers.
There are a couple of problems with this code though:
All the doubled numbers are going to be Doubles.
You can't pass a List<Integer> parameter anymore.
This method can't handle BigDecimal -s which have a large value
2. Bound subtype with insanceof checks.
So let's write another fix:
public <T extends Number> void mulBy2Attempt2(List<T> list) {
for (int i = 0; i < list.size(); i++) {
list.set(i, multiplyBy2(list.get(i)));
}
}
private <T extends Number> T multiplyBy2(T num) {
if (num instanceof BigDecimal) {
return (T) ((BigDecimal) num).multiply(new BigDecimal(2));
}
if (num instanceof BigInteger) {
return (T) ((BigInteger) num).multiply(new BigInteger("2"));
}
if (num instanceof Long) {
return (T) new Long(num.longValue() * 2);
}
if (num instanceof Integer) {
return (T) new Integer(num.intValue() * 2);
}
if ((num instanceof Double)) {
return (T) new Double(num.doubleValue() * 2);
}
if (num instanceof Float) {
return (T) new Float(num.floatValue() * 2);
}
if (num instanceof Byte) {
return (T) new Byte((byte) (num.byteValue() * 2));
}
if (num == null) {
throw new NullPointerException("Cannot multiply a null-number by two");
}
throw new IllegalArgumentException("Cannot handle a number of " + num.getClass().getCanonicalName() + " yet.");
}
This is really cool. Because of the bound type <T extends Number>, it can accept any kind of list, like List<AtomicInteger> or List<Number>. This solution has a couple of drawbacks though:
It relies heavily on instanceof checks
It can't possibly handle all the Number subclasses because anybody is free to implement a new Number subclass, and then you're done.
3. Let the caller decide how to multiply by two
We can use lambdas to put this burden on the caller:
public <T extends Number> void mulBy2Attempt3(List<T> list, Function<T,T> multiplier) {
for (int i = 0; i < list.size(); i++) {
list.set(i, multiplier.apply(list.get(i)));
}
}
So you can call it like this:
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
mulBy2Attempt3(list, n -> n * 2);
System.out.println(list);
4. Using Streams and map
What we have now is almost like the map function:
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
List<Integer> list2 = list.stream().map(n -> n * 2).collect(Collectors.toList());
System.out.println(list2);
This is slightly different because it won't modify the original list.
Now you have several options. Based on your requirements you can decide which way to go.

How do I make a deep copy of an ArrayList<Integer> in Java? [duplicate]

This question already has answers here:
How to clone ArrayList and also clone its contents?
(21 answers)
Closed 6 years ago.
I am basically just trying to make a deep copy of ones and zeroes, so I could have used booleans, but I was wondering how to do this in genereal for integers.
private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a) {
ArrayList<Integer> newA = new ArrayList<>(a.size());
for (int i = 0; i < a.size(); i++) {
int newInt = 0;
if (a.get(i) == 1) {
newInt = 1;
}
newA.add(newInt);
}
return newA;
}
The clone() method is protected by the Integer class, so you cannot call Integer.clone() outside of that class. What you can do instead is create a new Integer.
private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> old){
ArrayList<Integer> copy = new ArrayList<Integer>(old.size());
for(Integer i : old){
copy.add(new Integer(i));
}
return copy;
}
You can test that this works by doing something like:
public static void main (String[] args) throws java.lang.Exception
{
ArrayList<Integer> arr = new ArrayList<>();
for(int i = 0; i<5; i++){
arr.add(new Integer(i));
}
ArrayList<Integer> x = makeDeepCopyInteger(arr);
for(int i = 0; i<x.size(); i++){
if(arr.get(i) == x.get(i)){
System.out.println("Same object");
} else {
System.out.println("Not the same object");
}
}
}
Tests
Integer a = new Integer(1);
Integer b = new Integer(a);
System.out.println(a==b); // true
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // false;
Integer a = new Integer(1);
Integer b = a;
System.out.println(a==b); // true
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // true
So from my testing it seems that to create a new reference for copying to a new array, you should use new Integer(). Integer is an immutable object but that reference changes when the value of Integer changes.
Use streams to copy objects. Easy to read, good for JIT. Following code provides a copy of a list with Integer object copies inside.
private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a){
return a.stream().map(val -> new Integer(val)).collect(toList());
}
To copy custom objects other than Integer override implement and call clone()
return a.stream().map(MyObjectClass::clone).collect(toList());
Instead of clone you can use serialization to json. E.g. as used in BeanUtils.getCopy(sourceBean) in following java-utils
You could do something like:
public static List<Integer> clone(List<Integer> source) {
return source.stream()
.map( intObj -> new Integer(intObj.intValue()))
.collect(Collectors.toList());
}
Or, more old-fashioned:
public static List<Integer> clone(List<Integer> source) {
List<Integer> newList = new ArrayList<>();
for(Integer intObj : source) {
newList.add(new Integer(intObj.intValue()));
}
return newList;
}
Both of these could be made shorter by taking advantage of auto-boxing / auto-unboxing. But I've made it explicit to make it absolutely clear what's going on.
However, it's a pointless exercise - in fact it's actively wasteful of memory and detrimental to performance. Integer is immutable, so it's better for references to point at the same instance of Integer. Because it's not possible for the Integer to change value, it's impossible to cause any harm by sharing an instance.
This holds true for immutable objects in general, and is the reason they are a good thing.
You are very unlikely, as a beginner, to find a case in which new Integer(...) is a good idea (or even Integer.valueOf(int i), although this one might return a cached instance). If you already have an Integer, use the one you have:
Integer oldVar = ... ;
Integer newVar = oldVar;
Immutability means that will always be OK. It is impossible for an operation on newVar to corrupt oldVar because there is no newVar.setValue(newValue).
If you have an int use it directly and allow Java's auto-boxing to convert it into an Integer:
int oldValue = ... ;
Integer newValue = oldValue ; // Java will automatically put this through
// Integer.valueOf(int i)
You mentioned that you really wanted to work with booleans. You should consider using BitSet.
you'll have to iterate over the items of the list and clone them before, adding them to the new list, as mentioned here:
How to clone ArrayList and also clone its contents?

Make method generic to CharSequence[] and Set<String>

I am trying convert method to generic for CharSequence[] and for Set. Well I am not experienced in that.
This is the method where the second argument/return value should be generic (T). Is it possible?
private CharSequence[] remove(String string, CharSequence[] charSequences)
{
ArrayList<CharSequence> newArray = new ArrayList<CharSequence>();
int foundPlace = -1;
CharSequence[] v = charSequences;
for (int i = 0; i < v.length; i++) {
if (foundPlace != -1 && v[i].equals(string))
foundPlace = i;
else
newArray.add(v[i]);
}
return newArray.toArray(new CharSequence[newArray.size()]);
}
What I tried. Replaced everywhere where CharSequence[] occurs to T but it didn't work when I placed T in line T.length.
More clarification (sorry). I would like to convert second argument and return value to T - so everywhere where is CharSequence[] to T.
Maybe this is what you want:
private <T> T[] remove(T string, T[] charSequences)
{
ArrayList<T> newArray = new ArrayList<T>();
int foundPlace = -1;
T[] v = charSequences;
for (int i = 0; i < v.length; i++) {
if (foundPlace != -1 && v[i].equals(string))
foundPlace = i;
else
newArray.add(v[i]);
}
#SuppressWarnings("unchecked")
T[] ret = (T[]) Array.newInstance(v.getClass().getComponentType(), newArray.size());
return newArray.toArray(ret);
}
Or, if the containing class should also be generic of type T just remove <T> from above. So this line,
private <T> T[] remove(T string, T[] charSequences)
would then become,
private T[] remove(T string, T[] charSequences)
If the type of string doesn't matter, you may change its type to a plain Object,
private T[] remove(Object string, T[] charSequences)
{
ArrayList<T> newArray = new ArrayList<T>();
int foundPlace = -1;
T[] v = charSequences;
for (int i = 0; i < v.length; i++) {
if (foundPlace != -1 && v[i].equals(string))
foundPlace = i;
else
newArray.add(v[i]);
}
...
}
You might also want to rename string to something else afterwards.
I should also note that in your logic, foundPlace will always be -1.
You use an integer for foundPlace but a boolean is enough since you just test if it has been initialized and never use its value.
You don't even need this boolean, and your equals test is never evaluated since ̀foundPlace will always be equal to -1 (so the array you return is always a copy of charSequences)
You don't need an intermediary variable v, you can simply iterate over charSequences
Here is a version with Object, if it is what you are looking for :
private Object[] remove(Object val, Object[] array)
{
ArrayList<Object> newArray = new ArrayList<Object>();
for (Object o : array)
if(!o.equals(val))
newArray.add(o);
return newArray.toArray(new Object[newArray.size()]);
}
Generics and arrays can be a quite painful combination. I would stick to the List interface, if that is an option for you (ie. change return type to List and simply return newArray which would also be of type List).
Otherwise I recommend this post to better understand Generics and Arrays:
How to create a generic array in Java?
EDIT: Oh, and you definitely don't want to replace "CharSequence[]" with "T", but possibly with "T[]" if you really need to work with arrays here.
To implement a generic collection, use:
int length; // ...
T[] array = (T[])new Object[length];
So, the return statement will look like this:
return (T[])newArray.toArray(new Object[newArray.size()]);
Here is how you can implement a remove routine. Notice that you do not even need a separate remove method. I hope, I am not missing a use case that requires you to create a separate remove method.
package com.anupam;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class SO31535852 {
public static void main(String args[]) {
String[] arr = {"1", "2", "3"};
// Create a copy of the orginal array if you do not want to modify it.
Set<String> test = new HashSet<>(Arrays.asList(Arrays.copyOf(arr, arr.length)));
// In fact you do not even need a remove method. I could not understand why you are using
// foundPlace variable it's not doing much.
System.out.println(remove("1", test));
System.out.println(remove("1", test));
}
/**
* Removes a specific value from the underling collection
*
* #param toRemove the object to be removed
* #param myCollection the colelction from which to be removed
* #return the removed value or null.
*/
private static <T> T remove(T toRemove, Set<T> myCollection) {
return myCollection.remove(toRemove) ? toRemove : null;
}
}

Arrays.asList() of an array

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 the solution found in Create ArrayList from array. The second line (sorting) in getTheNumber(...) causes the following 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.
Let's consider the following simplified example:
public class Example {
public static void main(String[] args) {
int[] factors = {1, 2, 3};
ArrayList<Integer> f = new ArrayList(Arrays.asList(factors));
System.out.println(f);
}
}
At the println line this prints something like "[[I#190d11]" which means that you have actually constructed an ArrayList that contains int arrays.
Your IDE and compiler should warn about unchecked assignments in that code. You should always use new ArrayList<Integer>() or new ArrayList<>() instead of new ArrayList(). If you had used it, there would have been a compile error because of trying to pass List<int[]> to the constructor.
There is no autoboxing from int[] to Integer[], and anyways autoboxing is only syntactic sugar in the compiler, so in this case you need to do the array copy manually:
public static int getTheNumber(int[] factors) {
List<Integer> f = new ArrayList<Integer>();
for (int factor : factors) {
f.add(factor); // after autoboxing the same as: f.add(Integer.valueOf(factor));
}
Collections.sort(f);
return f.get(0) * f.get(f.size() - 1);
}
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 = new ArrayList<Integer>(Arrays.asList(integers));
Collections.sort(f);
return f.get(0)*f.get(f.size()-1);
}
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>
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;
}
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);
}
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.
This works from Java 5 to 7:
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);
}
In Java 4 there is no vararg... :-)
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
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.

Categories

Resources