How to access elements in a generic arraylist of arrays - java

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.

Related

Having problems with extending generic classes

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;
}
}

Construction of a class in java

I should carry out this exercise in the creation of a class, I uploaded this is the professor's solution, in sum and product methods can not quite figure out what place and why use "A".
class Vettore {
private int[] V = new int[6];
public Vettore(int[] X) {
if (X.length != 6)
throw new BadDataException();
for (int i = 0; i < 6; i++)
if (X[i] < 0)
throw new BadDataException();
else
V[i] = X[i];
}
public Vettore() {}
public Vettore somma(Vettore X) {
int[] A = new int[6];
for (int i = 0; i < 6; i++)
A[i] = V[i] + X.V[i];
return new Vettore(A);
}
public Vettore prodotto(Vettore X) {
int k = 0;
for (int i = 0; i < 6; i++)
k += V[i] * X.V[i];
return k;
}
public int get(int i) {
if (i < 0 || i > 5)
throw new BadDataException();
return V[i];
}
public String toString() {
String t = "( ";
for (int i = 0; i < 6; i++)
t += V[i] + (i == 5 ? " " : ", ");
return t + ")";
}
public boolean equals(Vettore X) {
for (int i = 0; i < 6; i++)
if (V[i] != X.V[i])
return false;
return true;
}
}
As far as I see it, and assuming somma means sum and prodotto means product, The A is needed because you have to store the sum values of the V and X.V arrays for every index. If you didn't use another array for this, you wouldn't be able to achive adding the appropriate indexes in somma for example. This method stands for - as I see it - Adding the two arrays' appropriate elements.
EDIT: another thing. Are you sure that the return types match variables to return? I elaborated the use of somma but didn't pay attention that prodotto has a wrong return type, just as it was said in the comments.
You might want to correct the prodotto method definition as -
public Vettore prodotto(Vettore X) {
int[] K = new int[6]; // deault values are 0
for (int i = 0; i < 6; i++)
K[i] += V[i] * X.V[i];
return new Vettore(K);
}
This would evaluate the product of the array field V for two instances of class Vettore namingly X the input param and the current instance that you would call the method from.
return new Vettore(K); creates a new instance of Vettore class with K as arrays field, while executing the constructor logic in place as follows -
public SumAndProductExercise(int[] X) {
if (X.length != 6) { // length of the array is 6 or not
throw new BadDataException();
}
for (int i = 0; i < 6; i++) {
if (X[i] < 0) { // all the elements of array are >=0 or not
throw new BadDataException();
} else {
V[i] = X[i]; // the field on the new instance
}
}
}

How to write a remove method?

Write a method called get which will return an element from the given index. Returns -1 if the index is out-of-bounds.
Write a method called remove which will remove an element from the given index. Returns -1 if the index is out-of-bounds. Data should be shifted accordingly during removal.
//This is the get method
public int get(int index){
if(index < 0 || index >= size) {
return -1;
}else {
return data[index];
}
}
//This is the remove method
public int remove(int index){
if(index < 0 || index >= size){
return -1;
}else {
for(int i = 0; i < size-1; i++) {
index[i] = index[i+1];
}
}
}
This is as far as I got. Not sure how to proceed with the code. I'd appreciate if someone could guide me through. Thank you!
So far, you have the right idea. I am going to assume based on your syntax, that you are using an array. Your get() method looks good, but you are missing some code from your remove() method.
public int remove(int index){
//check for out-of-bounds
if(index < 0 || index >= size) //assumes size is set to the size of the array
{
return -1; }
else
{
for(int i = index; i < size-1; i++){
data[i] = data[i+1]; }
data[size-1] = 0; //assuming the array contains numbers, if not replace '0' with null
}
}
You need to replace the following :
for(int i = 0; i < size-1; i++) {
index[i] = index[i+1];
}
with:
for(int i = index; i < size-1; i++) {
data[i] = data[i+1];
}
Start the loop with index
index[i] won't compile. Should be data[i] probably.
Note:
This will not delete the last element. You need to specifically check for it.
public class MyList<T> {
T[] items = (T[])new Object[10];
public int size() {
int counter=0;
for (int i = 0; i < items.length; i ++) {
if (items[i] != null) {
counter ++;
}
}
return counter;
}
public void remove(int t) {
for (int i = t; i < items.length-1; i++) {
items[i]=items[i+1];
}
items[items.length-1]=null;
items= Arrays.copyOf(items,size());
}
}

How can I override remove method for Set?

I'm trying to write the remove method for Set but it doesn't work when I test it. Am I doing it wrong? the size doesn't reduce after I remove the element.
public class MySet<T> implements Set<T> {
private T[] arrayB;
private int elements;
#Override
public boolean remove(Object f) {
T h = (T) f;
for (T z : arrayB) {
if(z == h) {
z = null;
}
}
return true;
}
#Override
public int size() {
int count = 0;
for(int arr = 0; arr < arrayB.length; arr++){
if(arrayB[arr] != null) {
count++;
}
}
return count;
}
The test code is:
MySet<Integer> ints = new MySet<Integer>();
for (int i = 0; i < 100; i++) {
ints.add(i);
}
for (int i = 0; i < 100; i += 2) {
ints.remove(i);
}
}
Your size method relies on whether the element is null to decide whether to count it. Assuming that you are attempting to place a null in the array, you're doing it wrong. All you've done is assign null to z, which is just a local variable. The array is not changed.
You must use a traditional for loop and use an array access expression to assign null to the array element. You'll also want to call equals instead of using == to find the element.
for (int i = 0; i < array.length; i++)
{
if (array[i] != null && array[i].equals(h))
{
array[i] = null;
}
}
Depending on whether you want to remove all elements that match, or just the first one, you may consider adding a break statement inside the if.

Using Arrays instead of Lists Java

This method has to remove duplicate elements from the passed-through array at 2 index points. However, I learned that we are not allowed to use Arraylist or LinkedLists, only Arrays. How can I make this work?
public Animal[] removeDuplicateAnimals(Animal[] animals, int fromIndex, int toIndex) {
int constFromIndex = fromIndex;
ArrayList<Animal> uniqueAnimals = new ArrayList<Animal>();
Animal[] uniqueAnimalsArray = new Animal[0];
uniqueAnimals.addAll(Arrays.asList(Arrays.copyOfRange(animals, 0, fromIndex)));
boolean existingFlag;
while (fromIndex < toIndex) {
existingFlag = false;
if(uniqueAnimals.size() == 0)
uniqueAnimals.add(animals[fromIndex]);
else {
int j = (constFromIndex - 1) > 0 ? (constFromIndex - 1): 0;
for (; j < uniqueAnimals.size(); j++)
if(uniqueAnimals.get(j).equals(animals[fromIndex])) {
existingFlag = true;
break;
}
if(!existingFlag)
uniqueAnimals.add(animals[fromIndex]);
}
fromIndex++;
}
uniqueAnimals.addAll(Arrays.asList(Arrays.copyOfRange(animals, toIndex, animals.length)));
return uniqueAnimals.toArray(uniqueAnimalsArray);
}
This has some unhandled edge cases (OOBExceptions etc), but if I understand what you're asking something like this should work:
public Animal[] removeDuplicateAnimals(Animal[] animals, int fromIndex, int toIndex) {
int modifiedAnimalsSize = animals.length;
for (int i = fromIndex; i < toIndex; i++) {
for (int j = i+1; j < toIndex; j++) {
int k = modifiedAnimalsSize -1;
if (animals[i].equals(animals[j])) {
animals[j] = animals[k];
animals[k] = null;
modifiedAnimalsSize--;
j--;
}
}
}
// return a new array which is resized
return Arrays.copyOf(animals, modifiedAnimalsSize);
}
For each animal at index i in the array, search through the indices of the array from i+1 to toIndex for the same animal; if there is a duplicate, write null at that index i in the original array. This will not resize the array. It will just replace duplicates with null.
public Animal[] removeDuplicateAnimals(Animal[] animals, int fromIndex, int toIndex) {
for (int i = fromIndex; i++; i < toIndex) {
for (int j = i+1; j++; j <= toIndex) {
if (animals[i].equals(animals[j])) {
animals[i] == null;
break;
}
}
}
return animals;
}

Categories

Resources