I am trying to create a generic class called "OrderedList", which uses an array of generic types to store a specific type using the types pre-defined sorting. I am having trouble with what should seem like a simple operation and I don't understand why. Here is my code.
public OrderedList() {
list = (T[]) new Object[100];
size = 0;
}
public <T extends Comparable<T>> void add(T o) {
if (size == list.length) resize();
list[size] = o;
for (int i = 0; i < size; i++) {
o.compareTo((T) list[i]);
}
size++;
}
private void resize() {
int newSize = (int) (1.5 * (double) list.length);
T[] newArray = (T[]) new Object[newSize];
for (int i = 0; i < size; i++) {
newArray[i] = list[i];
}
list = newArray;
}
The error I am getting is with the second line in the add method, "list[size] = o". It is providing me with an error that says "Incompatible Types. Required: T. Found: T." Also, whenever I take the instantiation of <T extends Comparable<T>>, that error goes away but then I cannot compare the two objects that I am trying to sort within the generic array.
Can anyone help me? I really am confused with this. Any help is appreciated.
You need to put the T extends Comparable<T> in the class signature, not the method signature.
class OrderedList<T extends Comparable<T>> {
T[] list;
int size;
public OrderedList() {
list = (T[]) new Object[100];
size = 0;
}
public void add(T o) {
if (size == list.length) resize();
list[size] = o;
for (int i = 0; i < size; i++) {
o.compareTo((T) list[i]);
}
size++;
}
private void resize() {
int newSize = (int) (1.5 * (double) list.length);
T[] newArray = (T[]) new Object[newSize];
for (int i = 0; i < size; i++) {
newArray[i] = list[i];
}
list = newArray;
}
}
Related
I'm trying to implement a generic MergeSort sorting algorithm. the function only accepts the type that implements Comparable interface as well as display function takes an array of any type to display the content of the array. But I'm receiving this exception -
Exception in thread "main" java.lang.ClassCastException: java.base/[Ljava.lang.Comparable; cannot be cast to java.base/[Ljava.lang.Integer;
at mergeSort.MergeSort.main(MergeSort.java:10)
My code is below:
package mergeSort;
import java.util.Arrays;
public class MergeSort
{
public static void main(String[] args)
{
Integer[] array = new Integer[]{3, 4, 2, 9, 5, 7, 8, 1, 6};
display(mergeSort(array));
}
public static <T extends Comparable<T>> T[] mergeSort(T[] array)
{
if(array.length <= 1) return array;
int leftLength = array.length/2;
int rightLength = array.length - leftLength;
T[] left = (T[]) new Comparable[leftLength];
T[] right = (T[]) new Comparable[rightLength];
for(int i = 0; i < array.length; i++)
{
if(i < leftLength)
{
left[i] = array[i];
}
else
{
right[Math.abs(left.length-i)] = array[i];
}
}
return merge(mergeSort(left), mergeSort(right));
}
public static <T extends Comparable<T>> T[] merge(T[] left, T[] right)
{
T[] merged = (T[]) new Comparable[left.length + right.length];
int i = 0;
int j = 0;
int k = 0;
while(i < left.length && j < right.length)
{
if(left[i].compareTo(right[j]) < 0)
{
merged[k++] = left[i++];
}
else
{
merged[k++] = right[j++];
}
}
while(i < left.length) merged[k++] = left[i++];
while(j < right.length) merged[k++] = right[j++];
return merged;
}
public static <T> void display(T[] array)
{
Arrays.stream(array).forEach(value -> System.out.print(value + " "));
System.out.println();
}
}
This method declaration promises something it doesn't do:
public static <T extends Comparable<T>> T[] mergeSort(T[] array)
You're not returning T[]. You're returning Comparable[]. So, either just declare it as such:
public static Comparable<?>[] mergeSort(Comparable<?>[] array) { ... }
public static Comparable<?>[] merge(Comparable<?>[] left, Comparable<?>[] right) { ... }
Alternatively, create your arrays using Array.newInstance(). For example:
public static <T extends Comparable<T>> T[] merge(T[] left, T[] right) {
T[] merged = (T[]) Array.newInstance(
left.getClass().getComponentType(),
left.length + right.length);
...
I'm struggling mightly on doing selection sort on an ArrayList of Strings to alphabetize them. I have no idea what I'm doing wrong. But its just not working properly for me. Heres my code.
ArrayList<String> list = new ArrayList<String>();
list.add("a");
list.add("d");
list.add("f");
list.add("c");
System.out.println(list);
int i;
int j;
int minValue;
int minIndex;
for (i=0; i<list.size(); i++) {
System.out.println(list.get(i));
char iLetter = (list.get(i).charAt(0));
int iValue = (int) iLetter;
minValue = iValue;
minIndex = i;
for(j=i; j<list.size(); j++) {
char jLetter = list.get(j).charAt(0);
int jValue = (int) jLetter;
if (jValue < minValue) {
minValue = jValue;
minIndex = j;
}
}
if(minValue < iValue) {
int temp = iValue;
char idx = list.get(minIndex).charAt(0);
int idxValue = (int) idx;
iValue = idxValue;
idxValue = temp;
}
}
System.out.println(list);
}
It still prints it out as ["a", "d", "f", "c"]
You are not updating your list anywhere in your loop, so it remains unsorted.
In order to actually swap elements of the list, replace:
if(minValue < iValue) {
int temp = iValue;
char idx = list.get(minIndex).charAt(0);
int idxValue = (int) idx;
iValue = idxValue;
idxValue = temp;
}
with:
if(minValue < iValue) {
Collections.swap (list, i, minIndex);
}
Collections.swap performs the following modification:
list.set(i, list.set(minIndex, list.get(i)));
Now the output will be
[a, c, d, f]
As mentioned, you need to do the actual swapping in the list, not just the temporary variables (doh!).
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("d");
list.add("f");
list.add("c");
System.out.println(list);
for (int i = 0; i < list.size(); i++) {
String smallest = list.get(i);
int smallestIndex = i;
for (int j = i; j < list.size(); j++) {
String value = list.get(j);
if (value.compareTo(smallest) < 0) {
smallest = value;
smallestIndex = j;
}
}
if (smallestIndex != i) {
String head = list.get(i);
list.set(i, smallest);
list.set(smallestIndex, head);
}
}
System.out.println(list);
}
Additionally, your code is just a single method, AKA spaghetti code. To make it more object-oriented you could make the following changes.
import java.util.*;
public class SelectionSort<T extends Comparable> {
private List<T> values;
public SelectionSort(List<T> values) {
this.values = values;
}
private void sort() {
for (int headIndex = 0; headIndex < values.size(); headIndex++) {
sortFrom(headIndex);
}
}
private void sortFrom(int headIndex) {
int smallestIndex = findSmallestFrom(headIndex);
if (smallestIndex != headIndex) {
swap(headIndex, smallestIndex);
}
}
private int findSmallestFrom(int i) {
int smallestIndex = i;
T smallest = values.get(i);
for (int j = i; j < values.size(); j++) {
T value = values.get(j);
if (value.compareTo(smallest) < 0) {
smallest = value;
smallestIndex = j;
}
}
return smallestIndex;
}
private void swap(int i, int j) {
T head = values.get(i);
values.set(i, values.get(j));
values.set(j, head);
}
public static void main(String[] args) {
List<String> values = createTestData();
System.out.println(values);
SelectionSort selectionSort = new SelectionSort<>(values);
selectionSort.sort();
System.out.println(values);
}
private static List<String> createTestData() {
List<String> values = new ArrayList<>();
values.add("a");
values.add("d");
values.add("f");
values.add("c");
return values;
}
}
Some of the changes I made:
Separate method for creation of test data
Separate method for printing the before and after state of the list and calling the sort
Create an instance instead of only static code
separate iterations and logic into meaningful methods
Rename the 'list' variable to 'values'. The fact that it's a list is already clear. The convention is to name a collection by the meaning of the data it contains
Introduced a generic type variable on the class (<T extends Comparable>). This allows any type of data to be sorted, as long as it implements the Comparable interface
I have been trying to access the elements of several arrays that are held within an array list. I am able to access it regularly, but the problem comes when I use generic type E to account for different data types. This gives me a class cast exception. If I change the type of tempStart and tempScan and corresponding casts to int[] (since that is what I am using to pass in) it runs.
public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list) {
if (list.get(0).getClass().isArray()) {
System.out.println(" I am an array!");
//go through the arrays and make sure they are
//not the same, remove any that are the same
//make flag to see if something is different
boolean matching;
for (int idx = 0; idx < list.size() - 1; idx++) {
E[] tempStart =(E[])list.get(idx);
for (int k = idx + 1; k < list.size(); k++) {
matching = true;
E[] tempScan = (E[])list.get(k);
for (int index = 0; index < tempStart.length; index++) {
if (tempStart[index] != tempScan[index]) {
matching = false;
}
}
if (matching) {
list.remove(tempScan);
k--;
}
}
}
You are trying to cast E to E[] and it's obviously not correct. Try something like:
import java.lang.reflect.Array
...
public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list) {
ArrayList<E> retList = new ArrayList<>(list.size());
if (list.isEmpty()) return retList;
if (list.get(0).getClass().isArray()) {
boolean matching;
for (int idx = 0; idx < list.size() - 1; ++idx) {
E tempStart = list.get(idx);
for (int k = idx + 1; k < list.size(); k++) {
matching = true;
E tempScan = list.get(k);
int tempStartLen = Array.getLength(tempStart);
for (int index = 0; index < tempStartLen; index++) {
if (Array.get(tempScan, index) != Array.get(tempStart, index)) {
matching = false;
}
}
if (matching) {
list.remove(tempScan);
k--;
}
}
}
return retList;
} else {
throw new IllegalArgumentException("List element type expected to be an array");
}
}
However because we are using Java Reflection Array to manipulate the array operation, using generic E doesn't make sense here. You can simple declare it as ArrayList<Object>
Updates: as #afsantos comments below, the parameter type ArrayList could be declared as ArrayList<?> as nothing is going to be insert into it.
I have implemented Priority Queue interface for making heap. Can you tell me how to implement an iterator on the top of that? point me to some apropriate tutorial,i am new to java and on a very short deadline here.
Actually i need a method to find and modify an object from heap on the basis of Object.id. I dont care if it is O(n).
public interface PriorityQueue {
/**
* The Position interface represents a type that can
* be used for the decreaseKey operation.
*/
public interface Position {
/**
* Returns the value stored at this position.
* #return the value stored at this position.
*/
Comparable getValue();
}
Position insert(Comparable x);
Comparable findMin();
Comparable deleteMin();
boolean isEmpty();
int size();
void decreaseKey(Position p, Comparable newVal);
}
// BinaryHeap class
public class OpenList implements PriorityQueue {
public OpenList() {
currentSize = 0;
array = new Comparable[DEFAULT_CAPACITY + 1];
}
public OpenList(int size) {
currentSize = 0;
array = new Comparable[DEFAULT_CAPACITY + 1];
justtocheck = new int[size];
}
public OpenList(Comparable[] items) {
currentSize = items.length;
array = new Comparable[items.length + 1];
for (int i = 0; i < items.length; i++) {
array[i + 1] = items[i];
}
buildHeap();
}
public int check(Comparable item) {
for (int i = 0; i < array.length; i++) {
if (array[1] == item) {
return 1;
}
}
return array.length;
}
public PriorityQueue.Position insert(Comparable x) {
if (currentSize + 1 == array.length) {
doubleArray();
}
// Percolate up
int hole = ++currentSize;
array[ 0] = x;
for (; x.compareTo(array[hole / 2]) < 0; hole /= 2) {
array[hole] = array[hole / 2];
}
array[hole] = x;
return null;
}
public void decreaseKey(PriorityQueue.Position p, Comparable newVal) {
throw new UnsupportedOperationException(
"Cannot use decreaseKey for binary heap");
}
public Comparable findMin() {
if (isEmpty()) {
throw new UnderflowException("Empty binary heap");
}
return array[ 1];
}
public Comparable deleteMin() {
Comparable minItem = findMin();
array[ 1] = array[currentSize--];
percolateDown(1);
return minItem;
}
private void buildHeap() {
for (int i = currentSize / 2; i > 0; i--) {
percolateDown(i);
}
}
public boolean isEmpty() {
return currentSize == 0;
}
public int size() {
return currentSize;
}
public void makeEmpty() {
currentSize = 0;
}
private static final int DEFAULT_CAPACITY = 100;
private int currentSize; // Number of elements in heap
private Comparable[] array; // The heap array
public int[] justtocheck;
private void percolateDown(int hole) {
int child;
Comparable tmp = array[hole];
for (; hole * 2 <= currentSize; hole = child) {
child = hole * 2;
if (child != currentSize &&
array[child + 1].compareTo(array[child]) < 0) {
child++;
}
if (array[child].compareTo(tmp) < 0) {
array[hole] = array[child];
} else {
break;
}
}
array[hole] = tmp;
}
private void doubleArray() {
Comparable[] newArray;
newArray = new Comparable[array.length * 2];
for (int i = 0; i < array.length; i++) {
newArray[i] = array[i];
}
array = newArray;
}
You might look at java.util.PriorityQueue. If you're in a hurry, Arrays.sort() may suffice. Once sorted, Arrays.binarySearch() becomes possible.
Your underlying data structure is an array, which is difficult to write a Java-style iterator for. You could try creating a container class implementing java.util.Iterator which holds a reference to your Comparable element and its current array index. You'll need to manually update the index when you move the container.
I'm trying to Sort an array from my ArrayList:
ArrayList<Integer> al = new ArrayList<Integer>();
al.insert(0, 4);
al.insert(1, 3);
al.insert(2, 2);
al.insert(3, 1);
SelectionSortWrappers<Integer> ss = new SelectionSortWrappers<Integer>();
ss.sort(al.elements);
ss.show(al.elements);
But when I try to access al.elements, I'm getting:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
Here is my SelectionSort Class:
public class SelectionSortWrappers<T>{
public <T extends Comparable<? super T>> void sort(T[] array){
int index;
for(int i = 0 ; i < array.length;i++){
index = i;
for(int j = i + 1; j < array.length; j++){
if (array[j].compareTo(array[index]) < 0){
index = j;
}
}
T smaller = array[index];
array[index] = array[i];
array[i] = smaller;
}
}
public void show(T[] array){
for(int i=0; i < array.length; i++){
System.out.print(array[i] + " ");
}
}
}
My ArrayList, i had to create, because is for my university project, i cannot use the Java one.
package Lists;
public class ArrayList<T> implements List<T> {
private static int MAX_SIZE = 10;
private static final int NOT_FOUND = -1;
public T[] elements;
protected int size;
public ArrayList() {
size = 0;
elements = (T[]) new Object[MAX_SIZE];
}
public T[] getArray(){
return elements;
}
public int find(T v) {
for(int i = 0; i < size; i++) {
if(v == elements[i]) {
return i;
}
}
return NOT_FOUND;
}
public T elementAt(int pos) {
if(pos >= 0 && pos < size) {
return elements[pos];
}
throw new InvalidArgumentException();
}
public void insert(int pos, T v) {
if (size == MAX_SIZE){
elements = Arrays.copyOf(elements, size * 2);
MAX_SIZE = size * 2;
}
if(pos == size) {
elements[size] = v;
}
else {
for(int i = size; i > pos; i--) {
elements[i] = elements[i-1];
}
elements[pos] = v;
}
size++;
}
public void remove(int pos) {
if(pos >= 0 && pos < size) {
for(int i = pos; i < size-1; i++) {
elements[i] = elements[i+1];
}
size--;
}
else {
throw new InvalidArgumentException();
}
}
public int size() {
return size;
}
public void show(boolean reverse) {
if (!reverse){
for(int i=0; i < size; i++){
System.out.print(elements[i] + " ");
}
} else {
for(int i=size; i >= 0; i--){
System.out.print(elements[i] + " ");
}
}
}
}
Where is the problem? My elements field is public.
You're running into the predictable erasure-versus-arrays problem caused by doing (T[]) new Object[MAX_SIZE]. You'll get a warning on that line -- that warning is warning you about exactly this problem.
Your ArrayList class is pretending an Object[] is a T[], but it really isn't -- the actual referenced array is still an Object[]. When you pull it out with al.elements, it tries to actually cast it to an Integer[] and fails.
You will have to do something ugly to deal with this -- like what the built-in java.util.Collection.toArray(T[]) has to do, for example. Alternately, you could write your sorting method to access your ArrayList directly instead of trying to work on its underlying array.