ArrayList error , unchecked and unsafe operation - java

This code will not compile for me , can anyone fix it or see a problem with it?
I keep getting the error arraylistv2.java uses unchecked or unsafe operators,
when i added -Xlint it pointed to
private T[] seq = (T[])(new Object[1024]); // 1024 arbitrary
as the problem , any ideas?
class ArrayList<T>
{
private T[] seq = (T[])(new Object[1024]); // 1024 arbitrary
private int numItems = 0; // seq[0..numItems-1] significant
public int size() { return(numItems); }
public T get(int i)
{
if(i < 0 || i >= numItems)
throw new IndexOutOfBoundsException();
else
return seq[i];
}
public T set(int i, T t)
{
if(i < 0 || i >= numItems)
throw new IndexOutOfBoundsException();
else
{
T temp = seq[i];
seq[i] = t;
return temp;
}
}
public boolean add(T t)
{
add(numItems,t);
return true; // for compatibility reasons only
}
public void add(int i, T t)
{
if(i < 0 || i > numItems)
throw new IndexOutOfBoundsException();
if(numItems == seq.length)
resize(); // extend seq
for(int k = numItems; k > i; k--) // shift seq[i..] to right
seq[k] = seq[k-1];
seq[i] = t;
numItems++;
}
private void resize()
{ // seq is full -- double its size
T[] temp = (T[])(new Object[seq.length * 2]); // bigger array
for (int i = 0; i < seq.length; i++) // copy over items
temp[i] = seq[i];
seq = temp;
}
}
public class arraylistv2{
public static void main(String [] args){
ArrayList<String> arraylist1 = new ArrayList<String>();
arraylist1.add(1,"orange");
arraylist1.add(2,"apple");
int i = arraylist1.size();
System.out.println(arraylist1);
}
}

The message"arraylistv2.java uses unchecked or unsafe operators" is a warning not an error. In other words, there is no compile time error in your code. So, it should compile just fine (albeit with a couple of warning messages).
There is actually a runtime error in your code:
Exception in thread "main" java.lang.IndexOutOfBoundsException
at arraylistv2$ArrayList.add(arraylistv2.java:45)
at arraylistv2.main(arraylistv2.java:5)
Lastly, it seems that the type cast from object[] to T[] is not necessary in your code here:
private T[] seq = (T[])(new Object[1024]);
I'd recommend leaving it as a Object[]. All methods of your custom ArrayList class work with the generic type T so there is no way to put any other type of objects in seq anyways. Here is an example of custom ArrayList class that I wrote some time ago: https://github.com/anshulverma/nuaavee-collections/blob/master/src/main/java/com/nuaavee/collections/list/ArrayList.java
Hope that helps.
P.S. I should also point out that it is usually better to ask specific questions rather than pasting complete code listing. You will have more people responding to your questions that way. Not everyone has a lot of free time like me ;)

Related

Trying to find a Unique Element in the ArrayList Implementation in Java. A getUnique Method

public class MyArrayList<T> implements MyList<T>{
int num; //number of things in the list
T[] vals; //to store the contents
#SuppressWarnings("unchecked")
public MyArrayList() {
num = 0;
vals = (T[]) new Object[3];
}
public T getUnique(){
T distinct = null;
int count = 0;
for (int i=0; i<vals.length; i++){
distinct = vals[i];
for (int j = 0; j<vals.length; j++){
if (vals[j] == vals[i]){
count++;
}
if (count == 1){
return distinct;
}
}
}
if (distinct == null){
throw new IllegalArgumentException();
}
return distinct;
}
I am trying to work on a get Unique Method. A method getUnique that takes no arguments and returns the first value in the list that appears only once. (For example, calling the method on the list [1,2,3,1,2,4] would return 3 since 1 and
2 both appear more than once.) If the list is empty or all its values appear more than once, the method throws a NoSuchElementException
I have added some FIXME's to your code:
public T getUnique(){
T distinct = null;
int count = 0; // FIXME: move this initialization inside the i loop
for (int i=0; i<vals.length; i++){
distinct = vals[i];
for (int j = 0; j<vals.length; j++){
if (vals[j] == vals[i]){ // FIXME: use .equals() not ==
count++;
}
if (count == 1){ // FIXME: move this check outside the j loop
return distinct;
}
}
}
if (distinct == null){ //FIXME: no check needed, just throw it
throw new IllegalArgumentException();
}
return distinct; //FIXME: no valid return can reach this point
}
Patrick Parker's advice will fix your code, but I wanted to provide a cleaner and faster solution to the problem of finding a unique element in a list. This algorithm runs in time O(n) instead of O(n^2).
public static <T> Optional<T> getUnique(List<T> ls) {
// Create a map whose keys are elements of the list and whose values are
// lists of their occurences. E.g. [1,2,3,1,2,4] becomes {1->[1, 1],
// 2->[2, 2], 3->[3], 4->[4]}. Then elements.get(x).size() tells us how
// many times x occured in ls.
Map<T, List<T>> elements = ls.stream()
.collect(Collectors.groupingBy(x -> x));
// Find the first element that occurs exactly one time in ls.
return ls.stream().filter(x -> elements.get(x).size() == 1)
.findFirst();
}
You might call it like this:
Integer[] vals = {1,2,3,1,2,4};
System.out.println(getUnique(Arrays.asList(vals))
.orElseThrow(NoSuchElementException::new));
This code uses Java 8 streams and Optional. Below is another implementation of the same algorithm that doesn't use Java 8 language features; if you've never encountered streams, you may find it more understandable.
private static <T> T getUnique(List<T> arr) {
Map<T, Integer> numOccurrences = new HashMap<>();
for (T item : arr) {
numOccurrences.put(item, 1 + numOccurrences.getOrDefault(item, 0));
}
for (T item : arr) {
if (numOccurrences.get(item) == 1) {
return item;
}
}
throw new NoSuchElementException();
}

Convert Generic Arraylist into an array with Generic Type

I'm trying to use ArrayList's built in Java method that converts an ArrayList to an array. However, the issue is that Java converts the array to an array of type objects. I am trying to convert this to an array of type T (generic type). I tried passing in the class type into the constructor of the class using it to cast the array, but I had no luck. My code is below. Any help would be appreciated:
public class QuickSelect<T extends Comparable<T>> extends Sort<T> implements Selection<T> {
Class<T> t; // for class type
QuickSelect(Class<T> t){
this.t = t;
}
#Override
public T select(T[] data, int n, int k) {
if(data.length == 0) return null;
if(k == 1) return data[0];
if(k >= n || k <=0 ) return null;
Random randomGenerator = new Random();
int pivotPosition = randomGenerator.nextInt(n-1);
T pivotValue = data[pivotPosition];
ArrayList<T> lessThanPivot = new ArrayList<T>();
ArrayList<T> equalToPivot = new ArrayList<T>();
ArrayList<T> greatThanPivot = new ArrayList<T>();
for(int i=0; i < n; i++){
if(compare(pivotValue, data[i]) < 0) lessThanPivot.add(data[i]);
else if(compare(pivotValue, data[i]) == 0) equalToPivot.add(data[i]);
else greatThanPivot.add(data[i]);
}
Class<?> tClass = t.getClass();
if(k <= lessThanPivot.size()) select(lessThanPivot.toArray(), lessThanPivot.size(), k); // this part of the code is where the issue is
return null; //don't worry about this for now
}
}
There are two versions of toArray() methods in ArrayList - the one that gets no argumnets, and returns array of Object (that you use) and the other one, that gets as argument the type of array you want to it to return: public <T> T[] toArray(T[] a)
so you need to use this one, like this: lessThanPivot.toArray(data)
see full javadoc here
If i got your question right i sugget you to use List.toArray(T[])
Example String[]array = list.toArray(new String[list.size()]);
Generics are removed when code is compiled, thus the helper.array will just return an object[].
I hope this will help.

Creating an N-Dimensional array of type T and populating it

I am currently working on a small system where I will read certain values from a byte array. One of the types must be an array. The other types are primitives and strings.
The problem I am having is trying to create the and populate the array. The array gets populated from a method, lets call it next(). next() will return a non-null Object - this object will not be an array. The length is also dynamic and is loaded from another source, but for the following code it will merely be provided.
final Integer[][] array = readArray(Integer[][].class, 10);
//...
// T = Integer[][]
// S = Integer[]
public static <T, S> S[] readArray(final Class<T> cls, final int length) {
if (cls.isArray()) {
final Class<S> subCls = (Class<S>) cls.getComponentType();
final S[] array = (S[]) Array.newInstance(subCls, length);
for (int i = 0; i < length; i++) {
if (subCls.isArray()) {
array[i] = readArray(subCls, length);
} else {
array[i] = (S) next();
}
}
return array;
}
throw new IllegalArgumentException("Type of cls must be an array.");
}
So far, I have this. The problem at the moment is with the line:
array[i] = readArray(subCls, length);
The error is:
Error:(28, 41) java: incompatible types: no instance(s) of type variable(s) T,S exist so that S[] conforms to S
I've tried many ways around this. Including using a HelperArray<T, S> class, but even that did not work.
I would also like to point out that the type of the array may not be guaranteed. The only real guarantee is that the top-level component types for the array will either be a string or a primitive. For example, the following could very well happen:
Object[][]{String[]{}, Integer[]{}, byte[]{}}
Any help with this issue is greatly appreciated, thanks.
I have cobbled this together, does that help you?
For me the output is a 10x10 2D array with all ones.
public class Test {
public static void main(String[] args) {
Integer[][] array = readArray(Integer[][].class, 10);
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++)
System.out.print(array[i][j] + ",");
System.out.println();
}
}
// T = Integer[][]
// S = Integer[]
public static <T, S> S[] readArray(final Class<T> cls, final int length) {
if (cls.isArray()) {
final Class<S> subCls = (Class<S>) cls.getComponentType();
final S[] array = (S[]) Array.newInstance(subCls, length);
for (int i = 0; i < length; i++) {
if (subCls.isArray()) {
array[i] = (S) readArray((Class<?>) subCls, length);
} else {
array[i] = (S) next();
}
}
return array;
}
throw new IllegalArgumentException("Type of cls must be an array.");
}
private static Object next() {
// TODO Auto-generated method stub
return 1;
}
}
So, got it to work. Going to kill myself in 3 years when the legacy code breaks and I have to rewrite this, but I'll deal with that in the future. Technically, #Icewind was correct in his answer - I just forgot to account for primitives which made the problem - literally - exponentially harder.
Warning: Code Gore Ahead [NSFW]
public synchronized <T, S> T readArray(final Class<T> cls) {
if (next() != IDENTIFIER_ARRAY) {
throw new InvalidProtocolException(lastReadIndex);
}
final int nextID = next();
final int length = readRawInt();
final Class<S> component = (Class<S>) cls.getComponentType();
if (component.isPrimitive()) {
switch (component.getCanonicalName()) {
case "boolean":
return (T) readRawBooleanArray(length);
case "byte":
return (T) readRawByteArray(length);
case "short":
return (T) readRawShortArray(length);
case "char":
return (T) readRawCharArray(length);
case "int":
return (T) readRawIntArray(length);
case "float":
return (T) readRawFloatArray(length);
case "long":
return (T) readRawLongArray(length);
case "double":
return (T) readRawDoubleArray(length);
}
}
final S[] array = (S[]) Array.newInstance(component, length);
for (int i = 0; i < length; i++) {
if (component.isArray()) {
array[i] = (S) readArray((Class<?>) component); // Thanks Icewind!
} else {
array[i] = (S) readMethodFor(nextID);
}
}
return (T) array;
}

ClassCastException Object cannot be cast to

I don't understand why I get ClassCastException on below code in line:
for(int i = 0; i < k.t.length; i++)
So problem is that in method addElement I make replacing of array elements by objects with type T. In my opinion in array should be objects with type T. And compiler doesn't protest for that.
But in run-time JVM cannot cast despite in array is really objects with type T (in case below String), why JVM cannot use polymorphism?
But when I change the T[] t; to Object[] t;
and remove cast in constructor it run correctly without any errors, why?
public class MyCollection<T> {
T[] t;
MyCollection( int size){
t = (T[]) new Object[size];
}
boolean addElement(T e, int i){
if(i < t.length){
t[i] = e;
return true;
}
return false;
}
public static void main(String[] ss){
MyCollection<String> k = new MyCollection<String>(3);
k.addElement("a",0);
k.addElement("b",1);
k.addElement("c",2);
for(int i = 0; i < k.t.length; i++)
System.out.println(k.t[i]);
//for(String s : (String[])k.t)
// System.out.println(s);
}
}
The problem is that you're casting Object[] to T[], and then you're exposing the underlying array. The only reason this works altogether is because the type erasure of T is Object. But since in our case T is being interpreted as String, when we access the array externally, we're trying to cast it to String[], which is incorrect. In order to avoid this issue, you should make the array private and provide accessor methods to retrieve elements. By doing that, you only cast individual elements to their correct type without making assumptions about the underlying array.
public class MyCollection<T> {
private T[] t;
MyCollection( int size){
t = (T[]) new Object[size];
}
boolean addElement(T e, int i){
if(i < t.length){
t[i] = e;
return true;
}
return false;
}
T getElement(int index) {
return t[index];
}
int getLength() {
return t.length;
}
public static void main(String[] ss){
MyCollection<String> k = new MyCollection<String>(3);
k.addElement("a",0);
k.addElement("b",1);
k.addElement("c",2);
for(int i = 0; i < k.getLength(); i++)
System.out.println(k.getElement(i));
//for(String s : (String[])k.t)
// System.out.println(s);
}
}
Note that Java's Collection interface demonstrates the same behavior. Collection.toArray() returns Object[] regardless of the type of E. The only available workaround is Collection.toArray(T[]), where you're forced to pass an array with a fixed type, which can then be either be populated or copied.
Check again the line of the problem. In my opinion the exception will be thrown because of:
for(String s : (String[])k.t)
You`re trying to cast to String[] here, while the array is defined as Object[]:
t = (T[]) new Object[size];
you can Create a new instance of array using the reflection to avoid ClassCastException
example:
import java.lang.reflect.Array;
public class MyCollection<T> {
T[] t;
MyCollection(Class<T> clazz, int size) {
t = (T[]) Array.newInstance(clazz, size);
}
boolean addElement(T e, int i) {
if (i < t.length - 1) {
t[i] = e;
return true;
}
return false;
}
public static void main(String[] ss) {
MyCollection<String> k = new MyCollection<String>(String.class, 3);
k.addElement("a", 0);
k.addElement("b", 1);
k.addElement("c", 2);
for (int i = 0; i < k.t.length; i++)
System.out.println(k.t[0]);
}
}

NullPointerException when creating an ArrayList-like class

As a practice exercise, I am creating my own generic class that is basically a copy of ArrayList. While testing the class with JUnit, I come across a NullPointerException error in the add method:
public void add(int index, T element) {
if (index > this.size() || index < 0) {
throw new IndexOutOfBoundsException();
}
if (this.size() == data.length) {
// ^ This is the line that the error points to
resize(this.data);
}
for (int i = index; i < this.size; i++) {
this.data[i + 1] = this.data[i]; //fix
}
this.data[index] = element;
size++;
}
After messing around with the class a lot, I can't figure out where the error is coming from. I can provide any details/other parts of the class that are needed. Any guidance as to where the problem is located would be fantastic. Thank You.
The constructor for the class:
MyArrayList(int startSize) {
// round the startSize to nearest power of 2
int pow2 = 1;
do {
pow2 *= 2;
} while (pow2 < startSize);
startSize = pow2;
this.size = 0;
T[] data = (T[]) new Object[startSize];
}
The following test case tests the size, but encounters the error when it tries to add an element:
public void testSize() {
MyArrayList<Integer> test = new MyArrayList<Integer>();
ArrayList<Integer> real = new ArrayList<Integer>();
assertEquals("Size after construction", real.size(), test.size());
test.add(0,5);
real.add(0,5);
assertEquals("Size after add", real.size(), test.size());
}
T[] data = (T[]) new Object[startSize];
That initializes the local variable data. Which you don't want.
Change it to following to make sure that you initialize the instance variable -
this.data = (T[]) new Object[startSize];
I the NPE is on the line you have mentioned it is only because data is null. Where are you initialyzing data ?
Maybe when you are creating your CustomArrayList you are not initialyzing your internal array data.
The data intialisation is the problem. It should be this.data = (T[])new Object[startSize];

Categories

Resources