在Java中创建一个泛型数组列表?

4uqofj5v  于 2022-10-30  发布在  Java
关注(0)|答案(2)|浏览(224)

如何在java中创建一个泛型数组列表?如何存储不同的数据类型?如果我想创建一个包含所有方法的整型数组列表,它会工作。但是使用泛型****会出错。我该如何解决这个问题?
第一个
有没有这样工作机会?

tzxcd3kk

tzxcd3kk1#

如何存储不同的数据类型?
有两种方法来“解读”这个问题。

我想存储int之类的基元,或者对象

Java通常不能做到这一点。你可以动态地创建一个数组,这样就很灵活;数组本身就是对象。

public class MyArrayList {
  private Object store;
  private int length;

  public MyArrayList(Class<?> componentType) {
    store = java.lang.reflect.Array.newInstance(componentType, 10);
  }
}

这甚至可以生成int[]数组。我有意不在这里显示任何泛型,因为泛型不能是原始的。你根本不能生成任何类型的List<int>,句号。项目Valhalla可能会在未来的java版本中改变这一点,但是最新的java版本没有包含valhalla,而且在一段时间内不会。
一个更好的方法是多态性:创建一个abstract class AbstractList,然后进行多个实现:

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

请再次注意Integerint的尴尬之处。

我想存储一些特定的引用类型,例如String s OR LocalDate s。

数组被具体化并(不正确地)covariant,泛型是不变的并且被擦除。它们不会混合和匹配。这没有问题--你只需要自己写保证不会返回错误的类型,并添加适当的忽略警告代码。Object已经是你想要的一切了--毕竟,所有类型都是Object的子类型。因此,Object[]可以存储任何条带的任何引用类型,这实际上就是java已经存在的ArrayList实现的工作方式:

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

泛型被“擦除”,这意味着:编译器使用泛型以静默方式注入类型转换,并检查代码是否正确--在运行时,运行时什么也不做,也不知道泛型是什么,因此向(T)的类型转换实际上什么也不做:在运行时没有办法检查它,因为T在运行时消失了。你只是添加了那个强制转换,因为否则编译器会注意到你在返回T的时候返回了某个Object。编译器做不到这一点,但你的眼球和人脑可以:你知道,如果add()方法只接受Ts,那么数组中的对象将是类型为T或T的某个子类型的对象,即使编译器不能确定,你也可以。所以,你添加了强制类型转换,并告诉编译器停止抱怨(添加@SuppressWarnings),一切都很好。
同样,java.util.ArrayList是如何做到的。
但我真的想要一个T[]
我想要一匹小马。你不能这样做。你唯一能做的就是接收一个T[]或接收可以制造它们的代码,你不能自己制造它们。如果你必须:

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);
  • caller* 知道T是什么(它是String),所以我们让 * caller* 传入一个函数,该函数将把一个int转换为与该int一样大的正确类型的数组; String[]::newsize -> new String[size]的简写,size -> new String[size]是以下内容的简写:
class StringArrMaker implements IntFunction<String[]> {
  @Override public String[] apply(int size) {
    return new String[size];
  }
}
return new StringArrMaker();

换句话说,我们传递一个可以生成数组的东西给你的数组列表,这样数组列表就可以使用 that,因为它自己不能生成T[]
然而,在一些情况下,这都是一堆毫无意义的废话--手动确保基本的数组列表代码是微不足道的(添加了一个不安全的(T)强制转换)实际上是100%安全的,不可能出错。(让它们实际上是String[]而不是Object[])是在运行时可以询问数组的类型,运行时将确保您不会将错误的内容放入:

Object[] a = new String[10]; // legal
a[0] = LocalDate.now(); // compiles - but throws ArrayStoreException

System.out.println(a.getClass().getComponentType()); // prints String.

但是,如果data数组没有从数组列表中“泄漏”出来,也不应该“泄漏”出来(毕竟这是一个私有的实现细节),那么这一切都没有意义。
这大概就是ArrayList使用Object[]而不是T[]+一个IntSupplier的原因。

sr4lhrrt

sr4lhrrt2#

它是如此简单,只要创建一个类,你想要forex产品和定义字段和构造函数和getter & setter当创建一个对象从类简单地在一个数组列表中使用这List<Product> products list = new ArrayList<Product>();通过使用这一行,你正在创建一个对象在产品和存储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  
    }  
}```

相关问题