I am implementing an ordered list that automatically inserts elements in the correct sorted position using a Comparator. The list is built from scratch (not using java.util.ArrayList) and uses an internal raw array.
Here is the base list implementation:
public class ArrayList<T> implements ListADT<T> {
protected T[] array;
protected int count;
private static final int DEFAULT_CAPACITY = 10;
@SuppressWarnings("unchecked")
public ArrayList() {
array = (T[]) (new Object[DEFAULT_CAPACITY]); // internal storage
count = 0;
}
protected void expandCapacity() {
array = java.util.Arrays.copyOf(array, array.length * 2);
}
}
And here is the ordered version:
public class ArrayOrderedList<T> extends ArrayList<T> implements OrderedListADT<T> {
private Comparator<T> comparator;
public ArrayOrderedList(Comparator<T> comparator) {
this.comparator = comparator;
}
@Override
public void add(T element) {
if (count == array.length)
expandCapacity();
int i = 0;
// The error occurs here:
while (i < count && comparator.compare(element, array[i]) > 0) {
i++;
}
for (int j = count; j > i; j--) {
array[j] = array[j - 1];
}
array[i] = element;
count++;
}
}
public interface OrderedListADT<T> extends ListADT<T> {
public void add(T element);
}
public interface ListADT<T> extends Iterable<T>{
public T removeFirst();
public T removeLast();
public T remove( T Object);
public T first();
public T last();
public boolean contains(T target);
public boolean isEmpty();
public int size();
public Iterator<T> iterator();
public String toString();
}
Demo code:
public class ArrayOrderedListDemo {
public static void main(String[] args) {
ArrayOrderedList<Integer> array1 = new ArrayOrderedList<>(Comparator.naturalOrder());
array1.add(2);
array1.add(5);
array1.add(4);
array1.add(1);
}
}
Expected behavior
I expect the elements to be inserted in sorted ascending order, for example:
[1, 2, 4, 5]
Actual Runtime Error
Exception in thread "main" java.lang.ClassCastException:
class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.Comparable;
([Ljava.lang.Object; and [Ljava.lang.Comparable; are in module java.base of loader 'bootstrap')
at OrderedList.ArrayOrderedList.add(ArrayOrderedList.java:14)
at OrderedList.ArrayOrderedListDemo.main(ArrayOrderedListDemo.java:10)
What I understand so far
This happens because the internal array is actually an Object[] but the comparison operation indirectly expects the stored elements to be in a Comparable[] (even though I am using a Comparator).
Constraints
This is an academic exercise where:
The list must be implemented from scratch.
I cannot use java.util.ArrayList.
I cannot use reflection or Array.newInstance(...).
I must store elements in a generic array like this:
array = (T[]) new Object[n];
My Question
How can I safely compare elements using a Comparator when they are stored in an Object[], without converting the internal array into a Comparable[], and without using reflection?
ClassCastException.ListADTandexpandCapacity, and assume you meant to saynew ArrayOrderedList<>(Integer::compare);in your main method, there are still no exceptions when I run the code.OrderedListADTandListADTthat you're using, plus what your main method actually looks like (As stated it will throw generics-related compiler errors with the passed comparator).ArrayOrderedList<T extends Comparable>instead ofArrayOrderedList<T>. If you changed that at some point of time, you haven’t recompiled your code since then.