可能有许多 ArrayList 的 ArrayList

Posted

技术标签:

【中文标题】可能有许多 ArrayList 的 ArrayList【英文标题】:ArrayList of Possibly Many ArrayLists 【发布时间】:2021-11-15 04:42:53 【问题描述】:

我希望能够使用 Java 实现某种可以在其中存储可能许多 ArrayLists 的类或变量。

例如,一个二维 ArrayList 应该是这样的:ArrayList>

一个三维的ArrayList是这样的ArrayList>>

对于任何 N 大小的 ArrayList 以此类推。

我想实现一个可以将任何 N 大小的数组列表作为参数的函数,但我不太确定如何实现它以及函数签名的外观。我目前正在尝试使用过去使用过的泛型,但在这种情况下我有点迷茫。

有什么建议吗?

【问题讨论】:

泛型在这里不起作用,因为编译器在 List<String>List<List<String>>List<List<List<String>>> 之间没有区别。 我不相信这是可能的,但我最好的猜测是使用具有自身数组列表以及您想要的 Data_type 的 pojo,然后您可以这样嵌套它吗?内部 pojo 将具有 Data_type 并且没有其他属性,而所有其余部分将具有自身的 List 并且没有其他属性。 @rainmaker 是的,我认为您的解决方案是正确的,我想要的只是一种使用某种递归方法在数组列表中遍历的方法,我的问题是知道函数签名以及当我在方法中如何执行它时进行进一步的嵌套调用,并创建它。 考虑将多维列表视为表示灵活大小的多维数组的类的实现细节,它可以支持任意数量的维度。确定你希望你的类支持哪些方法。根据多维列表实现这些。方法可能引用整个数组、单个元素或数组的一部分。方法参数将取决于方法要访问的这些参数中的哪一个。 【参考方案1】:

一种方法是创建一个 Container 类,其中包含包装的值或包含值的列表:

class Container<T> 
    private boolean isSingleElement;
    private T value;
    private List<Container<T>> list;

然后您可以添加这些构造函数和静态工厂方法。他们能够创建容器。

private Container(T value) 
    this.value = value;
    this.isSingleElement = true;


private Container(List<Container<T>> values) 
    this.list = Collections.unmodifiableList(values);
    this.isSingleElement = false;


public static <T> Container<T> ofSingle(T value) 
    return new Container<>(value);


public static <T> Container<T> ofList(List<T> list) 
    return new Container<>(list.stream()
        .map(Container::new)
        .toList());

然后您可以添加方法来检索容器中内容的信息:

public boolean isSingleElement() 
    return isSingleElement;


public T value() 
    if (!isSingleElement) 
        throw new IllegalArgumentException();
    
    return value;


public List<Container<T>> list() 
    if (isSingleElement) 
        throw new IllegalArgumentException();
    
    return list;

请注意,如果容器分别包含单个元素或列表,list()value() 方法都会抛出 IllegalArgumentException。这样做的缺点是,如果调用了错误的方法,这会导致在运行时抛出错误。

如果您愿意,您也可以完全删除 value() 方法,并将单个元素包装到列表中:

public List<Container<T>> list() 
    if (isSingleElement) 
        return List.of(new Container<>(value));
    
    else 
        return list;
    

【讨论】:

【参考方案2】:

此时,你可以创建一个循环和一个递归,同时检查获取的对象是否为ArrayList,如果是arrayList,则再次进行递归。这里是一个例子

// Suppose I've a ArrayList<ArrayList<ArrayList<String>>>


/**
* @param ArrayList<?>
* Prints out all the values inside all the ArrayList present in the ArrayList
*/
public static void printArrayItems(ArrayList<?> a) 
    a.forEach((e) -> 
         if(e instanceof ArrayList) printArrayItems((ArrayList) e); else System.out.println(e);
    );

【讨论】:

问号到底是什么意思,只是表示我们不知道ArrayList可以有什么类型? 是的,这意味着它可以容纳任何类型的 Class 对象。这是一个通配符【参考方案3】:

添加了泛型以提供更好的类型安全代码。但如果不知道维度,就无法使用嵌套的 ArrayLists 创建类型安全的 N 维结构。

也许您可以使用扁平结构将坐标映射到值。

Map<List<Integer>, DataType> twoDimensionalMap = Map.of(
    List.of(0,0), value00,
    List.of(0,1), value01,
    List.of(1,0), value10,
    List.of(1,1), value11
)
Map<List<Integer>, DataType> threeDimensionalMap = Map.of(
    List.of(0,0,0), value000,
    List.of(0,0,1), value001,
    List.of(0,1,0), value010,
    List.of(0,1,1), value011,
    ...
)

这不是完全类型安全的,因为没有检查所有坐标的长度是否相同,或者所有坐标都已填充,但它是某些用例的可行解决方案。

【讨论】:

以上是关于可能有许多 ArrayList 的 ArrayList的主要内容,如果未能解决你的问题,请参考以下文章

2 ArrayList 详解

更新 ArrayList 适配器

JDK1.8源码学习-ArrayList

Java7集合框架——ArrayList

从 BroadcastReceiver 中的 Service 获取 arraylist 给出 NullpointerException

ArrayList