将 ArrayList 转换为包含不同长度数组的 2D 数组将 2D 数组整数列表转换为基元整数的 2D 数组

所以我有:

ArrayList<ArrayList<String>> 

它包含 x 个 ArrayList,其中包含另一个 y 个字符串。演示:

Index 0:
  String 1
  String 2
  String 3
Index 1:
  String 4
Index 2:
Index 3:
  String 5
  String 6

其中 index 是指包含字符串的数组索引。

如何将其转换为2D阵列,如下所示:

{{String1, String2, String3},{String4}, {}, {String5, String6}}

非常感谢。


答案 1

欢迎来到 Java 8 的世界!

我只花了一整夜的时间就不眠不休地学习了编写这一行可怕的代码需要什么。我确定它已经在某个地方了,但我找不到它。所以我正在分享我的时间和时间的研究,享受。呜呼!

若:

ArrayList<ArrayList<String>> mainList = new ArrayList<ArrayList<String>>();
// populate this list here

(或者更确切地说,在Java 8中:

ArrayList<ArrayList<String>> mainList = new ArrayList();
//Populate

)

那么你需要的就是:

String[][] stringArray = mainList.stream().map(u -> u.toArray(new String[0])).toArray(String[][]::new);

砰!一行。

我不确定与其他选项相比,它的速度有多快。但这就是它的工作原理:

  1. 获取 2D 数组列表的流。这个流有点像一个与LinkedList挂钩的Vector,他们有一个孩子。那个孩子,在后来的生活中,服用了一些NZT-48。我说点题外话。 返回元素流。或者用更怪异的话来说:返回一个,sorta。mainListmainList.stream()ArrayList<String>mainList.stream()Stream<ArrayList<String>>

  2. 在该流上调用该函数,该流将返回一个新流,其内容与传递给 中的参数指定的新类型匹配。此函数将为我们隐藏流中的每个元素。它有一个内置语句。为了实现这一目标;该函数采用 lambda 表达式作为其参数。Lambda 表达式类似于简单的内联单行函数。它有两种数据类型,可以得到'Jiggy wit it。首先是流中称为 () 的数据类型。下一个类型是它将映射到的数据类型,它位于 lambda 表达式的右半部分:。下面是您在使用语句时选择的标识符。前半部分是这样声明的:.就像一个,变量现在将是流中的每个元素,因为它循环访问流。因此,是原始流的元素所具有的数据类型,因为它是它们。Lambda 表达式的右半部分显示了如何处理每个元素:.结果存储在新流中的合法位置。在本例中,我们将其转换为 ..因为毕竟,这是一个2D数组..或者更确切地说,从代码中的这一点开始,一个1D数组(字符串数组)。请记住,这最终是一个.请注意,从对象调用将创建传入该对象的类型的新数组。在这里,我们传入 .因此,它将创建一个类型和长度等于 ArrayList 长度的新数组。然后,它用 的内容填充这个新的字符串数组,并返回它。这会将 Lambda 表达式保留并返回到 .然后,收集这些字符串数组并使用它们创建一个新流,它具有关联的类型,然后返回它。因此,在本例中返回 一个 。(好吧,实际上它返回一个,这是令人困惑的,需要转换,见下文).mapmapmapforeachmapmainList.stream()u -> u.toArray(new String[0])uforeachu ->foreachuuu.toArray(new String[0])String[]StringString[]uArrayListtoArrayArrayListnew String[0]String[]uArrayListmapmapString[]mapStream<String[]>Stream<Object[]>

  3. 因此,我们只需要调用新的字符串数组流。但是调用 a 与调用 a 有点不同,就像我们之前所做的那样。在这里,我们要用一个函数引用混淆的东西。它从以下位置获取类型:.该函数的类型为 。基本上,由于该函数被调用到Array,因此它将始终是某种类型的函数。在我们的例子中,由于里面的数据是另一个数组,我们只需在另一个数组上添加。我不确定为什么NZT-48没有在这个上工作。我本来以为默认调用就足够了,因为它是一个流和所有。一个专门为 .有谁知道为什么实际上返回的是 Lambda 表达式返回的类型流,而不是内部的 Lambda 表达式返回的类型流?toArraytoArrayStream<Object[]>ArrayList<String>String[][]::newnewString[][][][]toArray()Stream<String[]>mapStream<Object[]>

  4. 现在,我们从我们的流中获得了正确的操作。我们可以轻松地将其转储到局部变量中:toArraymainListString[][] stringArray = mainList.stream...

将 2D 数组整数列表转换为基元整数的 2D 数组

现在,我知道你们中的一些人正在外面。“这不适用于 ints!”就像我的情况一样。但是,它确实适用于“Ents”,见上文。但是,如果你想要一个2D基元数组从2D的(即)。你必须围绕中土世界地图进行更改。请记住,ArrayList 不能具有基元类型。因此,您不能调用 并期望得到一个 .您将需要将其绘制出来...再。intArrayListIntegerArrayList<ArrayList<Integer>>toArrayArrayList<Integer>int[]

int[][] intArray = mainList.stream().map(  u  ->  u.stream().mapToInt(i->i).toArray()  ).toArray(int[][]::new);

为了便于阅读,我试图将其间隔开来。但是你可以在这里看到,我们必须再次经历相同的整个映射过程。这一次,我们不能只是简单地调用ArrayList;与上面的例子一样。在这里,我们调用的不是 .因此,由于某种原因,我们不必将其作为“类型”,我认为它需要大脑类固醇。因此,我们可以采用默认选项;在那里,它击中了NZT-48,并在这个[运行]时间为我们计算出显而易见的问题。我不确定为什么它不能在上面的例子中做到这一点。哦,没错...ArrayList不会像Streams那样采用NZT-48。我在这里到底在说什么?toArrayutoArrayStreamArrayList

Annnyhoow,因为流太聪明了。像谢尔顿一样,我们需要一个全新的协议来处理它们。显然,先进的智能并不总是意味着容易处理。因此,需要这个新品来制作一个新的,我们可以更聪明地使用它 。而 Lambda 表达式是 to 的简单拆箱,使用允许 的隐式自动拆箱。现在,这似乎是一件愚蠢的微不足道的事情,好像智能有其局限性。在我的冒险学习所有这些的过程中:我实际上尝试使用,因为我期望默认行为。不是争论!!(咳嗽谢尔顿咳嗽)然后我用我最好的Husker山谷女孩口音说,“毕竟,它被称为,我猜,就像,84%的时间(42x2)它会,喜欢,路过,喜欢,每个人,所以喜欢,omgawd!”不用说,我感觉有点...喜欢。。这个家伙。我不知道,为什么它不以这种方式工作。mapToIntStreamtoArrayi->imapToIntIntegerintint = IntegermapToInt(null)mapToInti->i

嗯,我红了,半神志不清,半睡半醒。我可能犯了一些错误;请把它们拖出来,这样我就可以修复它们,让我知道是否有更好的方法!


答案 2
String[][] array = new String[arrayList.size()][];
for (int i = 0; i < arrayList.size(); i++) {
    ArrayList<String> row = arrayList.get(i);
    array[i] = row.toArray(new String[row.size()]);
}

其中 是你的(或任何 ,相应地更改循环内的第一行)arrayListArrayList<ArrayList<String>>List<List<String>>for


推荐