How can I create a generic Arraylist in java? How to store different data types? If I want to create an integer arraylist that can contains all the methods, It will work. but using generic <T> It gives me error. How can I fix that?
public class Array<T> {
int array[];
Array(int size) {
array = new int[size];
}
}
Array <String>a = new Array(5);
is any chance to work like that?
CodePudding user response:
How to store different data types?
There are two ways to 'read' that question.
I want to store either primitives like int
, OR objects
Java mostly can't do that. You can make an array dynamically and thus be flexible; arrays are themselves objects.
public class MyArrayList {
private Object store;
private int length;
public MyArrayList(Class<?> componentType) {
store = java.lang.reflect.Array.newInstance(componentType, 10);
}
}
This can even make int[]
arrays. I intentionally am not showing any generics here because generics cannot be primitive. You simply cannot make a List<int>
of any sort, period. Project Valhalla may change that for some future java version, but the most recent java version does not have valhalla included and will not for some time.
A better way to do this instead is polymorphism: Make an abstract class AbstractList
and then have multiple implementations:
public abstract class AbstractList<T> {
public abstract T get(int idx);
}
public final class IntList extends AbstractList<T> {
private int[] store = ...;
public Integer get(int idx) {
return store[idx];
}
}
Note again the awkwardness of Integer
vs int
.
I want to store some specific reference type, i.e. String
s OR LocalDate
s.
Arrays are reified and (incorrectly) covariant, generics are invariant and erased. They do not mix and match. This is no problem - you just write the assurance that you don't return the wrong type on your own and add the appropriate ignore warnings code. Object is already everything you want - after all, all types are a subtype of object. Therefore, an Object[]
can store any reference type of any stripe. This is in fact how java's already existing ArrayList
implementation works:
class MyList<T> {
private Object[] data; // not T[] - you can't make those.
private int size;
public MyList() {
this.data = new Object[10];
this.size = 0;
}
public void add(T in) { // this ensures only Ts can be added
ensureCapacity();
this.data[size ] = in;
}
private void ensureCapacity() {
if (size == data.length) {
// Consider data.length*2 overflowing and such
// I'm keeping it (over-)simplified here
Object[] a = new Object[data.length * 2];
System.arraycopy(data, 0, a, 0, data.length);
data = a;
}
}
@SuppressWarnings("unchecked")
public T get(int idx) {
return (T) data[idx];
}
}
Generics are 'erased', meaning: The compiler uses generics to silently inject casts and do some checking if your code is correct - at runtime, the runtime does nothing and has no idea what generics are, hence a cast to (T)
does literally nothing whatsoever: There is no way to check it at runtime as T is gone at runtime. You're just adding that cast because otherwise the compiler will note that you're returning some Object when you're supposed to return a T. The compiler can't do it, but your eyeballs and human brain can: You know that, given that the add()
method only takes in Ts, the objects in that array will be objects whose type is T or some subtype of T, even if the compiler can't be sure, you are. So, you add the cast, and tell the compiler to stop whining (add @SuppressWarnings
), and all is well.
Again, exactly how java.util.ArrayList
does it.
But I really want a T[]
And I want a pony. You can't do that. The only thing you can do is receive a T[]
or receive code that can make them, you cannot make them yourself. If you must:
public class SillyArrayList<T> {
private final IntFunction<T[]> arrayMaker;
private T[] data;
private int size;
public SillyArrayList(IntFunction<T[]> arrayMaker) {
this.arrayMaker = arrayMaker;
data = arrayMaker.apply(10);
}
public void add(T in) {
ensureCapacity();
this.data[size ] = in;
}
private void ensureCapacity() {
if (size == data.length) {
// Consider data.length*2 overflowing and such
// I'm keeping it (over-)simplified here
T[] a = arrayMaker.apply(data.length * 2);
System.arraycopy(data, 0, a, 0, data.length);
data = a;
}
}
// no suppress needed
public T get(int idx) {
return data[idx];
}
}
// and to use:
SillyArrayList<String> myList = new SillyArrayList<>(String[]::new);
The caller knows what T is (it's String
), so we let the caller pass in a function that will turn an int into an array of the right type as large as that int; String[]::new
is shorthand for size -> new String[size]
which is shorthand for:
class StringArrMaker implements IntFunction<String[]> {
@Override public String[] apply(int size) {
return new String[size];
}
}
return new StringArrMaker();
In other words, we pass a thing that can make arrays to your arraylist so that the arraylist can use that, as it can't make T[]
on its own.
However, this is all a lot of hoopla for no purpose whatsoever - it is trivial to manually ensure the basic arraylist code (that adds an unsafe (T) cast) is in fact 100% safe and cannot possibly go wrong. The only reason to 'reify' your arrays (have them actually be String[]
instead of Object[]
) is that you can ask at runtime what an array's type actually is, and the runtime will ensure you don't put the wrong things in:
Object[] a = new String[10]; // legal
a[0] = LocalDate.now(); // compiles - but throws ArrayStoreException
System.out.println(a.getClass().getComponentType()); // prints String.
however, given that the data
array does not 'leak' out of your arraylist and shouldn't (it is a private implementation detail after all), there is no point to any of this.
That's presumably why ArrayList
uses Object[]
and not T[]
an IntSupplier
.
CodePudding user response:
it is so easy simply just create a class that you want forex Products and define fields and constructor and getter & setter when create an object from that class simply in an array list use this
List<Product> products list = new ArrayList<Product>();
by using this line you are creating an object in the product and store int ArrayList
class Product{
int id;
String name;
float price;
public Product(int id, String name, float price) {
this.id = id;
this.name = name;
this.price = price;
}
}
public class JavaArrayListExample {
public static void main(String[] args) {
List<Product> productsList = new ArrayList<Product>();
//Adding Products
productsList.add(new Product(1,"HP Laptop",25000f));
productsList.add(new Product(2,"Dell Laptop",30000f));
List<Float> productPriceList = new ArrayList<Float>();
for(Product product: productsList){
// filtering data of list
if(product.price<30000){
productPriceList.add(product.price); // adding price to a productPriceList
}
}
System.out.println(productPriceList); // displaying data
}
}```