【问题标题】:Convert Collection<List<T>> to 2D array T[][] [duplicate]将 Collection<List<T>> 转换为二维数组 T[][] [重复]
【发布时间】:2012-12-09 21:09:33
【问题描述】:

可能重复:
Convert ArrayList into 2D array containing varying lengths of arrays

如何将Collection&lt;List&lt;Foo&gt;&gt; 转换为Foo[][] 类型的二维数组?

我正在尝试使用toArray 方法,但我不确定语法。例如,这不起作用:

import com.google.common.collect.Collections2;
Collection<List<Foo>> permuted = Collections2.permutations(bar);
Foo[][] permutedArray = permuted.toArray(new Foo[10][10]);//exception here

它正在抛出ArrayStoreException。在这种情况下,permutedArray 的类型应该是什么?

【问题讨论】:

  • 所有列表是否都有固定大小?
  • 是的,假设大小是size。但是大小可以在运行时确定吗?
  • 一个问题:T是泛型还是特定类?
  • 这是一个特定的类。我更改了问题以消除歧义

标签: java


【解决方案1】:

.toArray 只能将集合转换为List&lt;Foo&gt;[]。您需要再次对列表数组的每个元素调用.toArray 才能真正获得Foo[][]

    @SuppressWarnings("unchecked")
    final List<Foo>[] permutedList = permuted.toArray(new List[10]);
    final Foo[][] permutedArray = new Foo[10][10];
    for (int j = 0; j < 10; ++j) {
        permutedArray[j] = permutedList[j].toArray(new Foo[10]);
    }

【讨论】:

  • new List&lt;Foo&gt;[10] 出现错误:Cannot create a generic array of List&lt;Foo&gt;
  • 你定义了 Foo 吗? public &lt;Foo&gt; Foo[][] deconstruct(Collection&lt;List&lt;Foo&gt;&gt; colleciton) 应该可以工作
  • 是的 Foo 被定义了,虽然很奇怪...
  • @Chin:检查更新。似乎唯一可行的方法是使用未经检查的转换。
【解决方案2】:

如果您尝试以下通用实用程序函数会怎样:

public static <T> T[][] asMatrix(
    Collection<? extends Collection<? extends T>> source,
    T[][] target) {

    // Create a zero-sized array which we may need when converting a row.
    @SuppressWarnings("unchecked") T[] emptyRow =
        (T[])Array.newInstance(target.getClass().getComponentType().getComponentType(), 0);

    List<T[]> rows = new ArrayList<T[]>(source.size());
    int i = 0;
    for (Collection<? extends T> row : source) {
        T[] targetRow = i < target.length ? target[i] : null;
        rows.add(row.toArray(targetRow != null ? targetRow : emptyRow));
        i += 1;
    }
    return rows.toArray(target);
}

用法:

Collection<List<Foo>> permuted = ...;
Foo[][] result = asMatrix(permuted, new Foo[][] {});

它的工作方式是访问每个子集合(即行),将其转换为数组。我们将这些数组缓存在一个集合中。然后我们要求该集合将自己转换为一个数组,我们将其用作函数的结果。

这个实用函数的好处是:

  1. 它使用Collection.toArray 进行所有数组构造和复制。
  2. 该函数是通用的,因此可以处理任何类型的引用类型(不幸的是,像 intlong 等原生类型需要更多的工作)。
  3. 您传入目标数组,它甚至可能被预分配到特定大小,其行为与Collection.toArray 完全相同。
  4. 该函数可以容忍同时改变其大小的集合(只要集合本身是可以容忍的)。
  5. 转换是类型安全的类型严格的。

更多示例:

List<List<Integer>> list =
    Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4));

Integer[][] result;

result = asMatrix(list, new Integer[][] {});
System.out.println(Arrays.deepToString(result));

result = asMatrix(list, new Integer[][] {new Integer[] {9, 9, 9, 9}, null});
System.out.println(Arrays.deepToString(result));

结果:

[[1, 2], [3, 4]]
[[1, 2, null, 9], [3, 4]]

【讨论】:

    【解决方案3】:

    这似乎是做一组嵌套循环更有意义:

    //Untested, I might have made some silly mistake
    T[][] array = new T[collection.size()[];
    int collection = 0;
    int list = 0;
    
    for(List<T> list : collection)
    {
      list = 0;
      array[collection] = new T[list.size()];
      for(T t : list)
        array[collection][list++] = t;
    
      collection++;
    }
    

    “toArray”方法很方便,但由于是泛型类型,我通常觉得使用起来很沮丧。像这样的实用方法通常更容易阅读,并且可以避免您遇到的问题。

    编辑:我应该注意:你需要知道或转换 T。它会生成一个未经检查的类型异常(这当然是未经检查的!)。

    【讨论】:

      猜你喜欢
      • 2010-10-06
      • 2012-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-26
      • 2021-12-02
      相关资源
      最近更新 更多