欢迎来到 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);
砰!一行。
我不确定它与其他选项相比有多快。但这就是它的工作原理:
-
获取mainList 2D ArrayList 的流。这个流有点像一个连接了 LinkedList 的 Vector 并且他们有了一个孩子。那个孩子,在以后的生活中,服用了一些NZT-48。我离题了; mainList.stream() 正在返回 ArrayList<String> 元素流。或者用更极客的话来说:mainList.stream() 返回一个Stream<ArrayList<String>>,排序。
-
对该流调用.map 函数,该函数将返回一个新流,其内容与传递给map 的参数指定的新类型相匹配。这个map 函数将为我们隐藏流中的每个元素。它有一个内置的foreach 语句。为了做到这一点; map 函数将 lambda 表达式作为其参数。 Lambda expression 就像一个简单的内联单行函数。其中有两种数据类型gettin' Jiggy wit it。首先是调用它的流中的数据类型 (mainList.stream())。下一个类型是它将映射到的数据类型,它位于 lambda 表达式的右半部分:u -> u.toArray(new String[0])。这里u 是您选择的标识符,就像使用foreach 语句时一样。前半部分是这样声明的:u ->。和foreach 一样,变量u 现在将成为流中的每个元素,因为它遍历流。因此,u 是原始流元素的数据类型,因为它是它们。 Lambda 表达式的右半部分显示了如何处理每个元素:u.toArray(new String[0])。结果将存储在新流中的应有位置。在这种情况下,我们将其转换为String[].. 因为毕竟这是String.. 的二维数组,或者更确切地说,从代码中的这一点开始,String[](字符串数组)的一维数组。请记住,u 最终是 ArrayList。请注意,从ArrayList 对象调用toArray 将创建一个传入它的类型的新数组。这里我们传入new String[0]。因此它创建了一个String[] 类型的新数组,其长度等于ArrayList u 的长度。然后它用ArrayList 的内容填充这个新的字符串数组并返回它。留下 Lambda 表达式并返回到map。然后,map 收集这些字符串数组并用它们创建一个新流,它具有关联的类型 String[],然后返回它。因此,在这种情况下,map 返回Stream<String[]>。 (嗯,实际上它返回一个Stream<Object[]>,这很混乱,需要转换,见下文)
-
因此,我们只需要在新的字符串数组流上调用toArray。但是在Stream<Object[]> 上调用toArray 与在ArrayList<String> 上调用它有点不同,就像我们之前所做的那样。在这里,我们不得不使用一个函数引用令人困惑的东西。它从中获取类型:String[][]::new。 new 函数的类型为 String[][]。基本上,由于该函数被称为 toArray,因此它始终是某种[]。在我们的例子中,因为里面的数据是另一个数组,我们只是添加了另一个[]。我不确定为什么 NZT-48 不能在这个上工作。我本来希望对toArray() 的默认调用就足够了,因为它是一个流和所有内容。一个特别是Stream<String[]> 的流。有谁知道为什么map 实际上返回一个Stream<Object[]> 而不是内部 Lambda 表达式返回的类型的流?
-
现在我们从mainList 流中获得了toArray 正常运行。我们可以简单地将其转储到一个局部变量中:String[][] stringArray = mainList.stream...
将 2D ArrayList of Integers 转换为 2D 原始整数数组
现在,我知道你们中的一些人正在外面。 “这对整数不起作用!”就像我的情况一样。然而,它确实适用于“Ents”,见上文。但是,如果您想要来自Integer 的二维ArrayList 的二维原始int 数组(即ArrayList<ArrayList<Integer>>)。你必须改变那个中[地球]映射。请记住,ArrayLists 不能有原始类型。因此,您不能在ArrayList<Integer> 上致电toArray 并期望得到int[]。您将需要重新绘制它...。
int[][] intArray = mainList.stream().map( u -> u.stream().mapToInt(i->i).toArray() ).toArray(int[][]::new);
为了便于阅读,我尝试将其隔开。但是您可以在这里看到,我们必须再次经历相同的整个映射过程。这一次我们不能简单地在 ArrayList 上调用toArray u;和上面的例子一样。在这里,我们在 Stream 而不是 ArrayList 上调用 toArray。因此,出于某种原因,我们不必将其传递给“类型”,我认为它正在服用大脑类固醇。因此,我们可以采用默认选项;它需要 NZT-48 的打击,并在这个 [运行] 时间为我们找出显而易见的东西。我不确定为什么它不能在上面的例子中做到这一点。哦,没错.... ArrayLists 不像 Streams 那样采用 NZT-48。等等……我到底在说什么?
Annnyhoow,因为流非常聪明。就像Sheldon 一样,我们需要一个全新的协议来处理它们。显然,先进的智能并不总是意味着容易处理。因此,需要这个新的mapToInt 来创建一个新的Stream,我们可以使用它更智能的toArray。而mapToInt 中的i->i Lambda 表达式是Integer 到int 的简单拆箱,使用允许int = Integer 的隐式自动拆箱。现在,这似乎是一件愚蠢的小事,好像智力有其局限性。在我冒险学习所有这些的过程中:我实际上尝试使用mapToInt(null),因为我期望一个默认行为。不是争论!! (咳 Sheldon 咳)然后我用我最好的Husker山谷女孩口音说,“毕竟,它是叫mapToInt,我会猜测,就像,84% 的时间 (42x2) 它会像,像,通过 i->i,像,像,像,像,像,我的天啊!”不用说,我觉得有点……像……this guy。我不知道,为什么它不能那样工作。
嗯,我红眼了,半昏迷半睡着。我可能犯了一些错误;请把它们拖出来,这样我就可以修复它们,如果有更好的方法,请告诉我!
PT