Добро пожаловать в мир 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, и у них есть ребенок. И этот ребенок в более позднем возрасте подсел на какой-то NZT-48. Я отвлекся; mainList.stream()
возвращает поток из ArrayList<String>
элементов. Или, говоря еще более гиковски: mainList.stream()
возвращает Stream<ArrayList<String>>
, вроде как.
Вызовите функцию .map
для этого потока, которая вернет новый поток с содержимым, соответствующим новому типу, заданному параметрами, переданными в map
. Эта функция map
скроет для нас каждый элемент в нашем потоке. Он имеет встроенный оператор foreach
. Для того, чтобы выполнить это; функция map
принимает в качестве параметра лямбда-выражение. лямбда-выражение похоже на простое встроенная однострочная функция. Который имеет два типа данных: задуматься о Джигги. Во-первых, это тип данных в потоке, для которого он был вызван (mainList.stream()
). Следующий тип — это тип данных, на который он будет сопоставляться, который находится в правой половине лямбда-выражения: u -> u.toArray(new String[0])
. Здесь u
— это идентификатор, который вы выбираете так же, как при использовании оператора foreach
. Первая половина объявляет это так: u ->
. И, как и foreach
, переменная u
теперь будет каждым элементом в потоке, когда он проходит через поток. Таким образом, u
имеет тот же тип данных, что и элементы исходного потока, потому что он является ими. Правая половина лямбда-выражения показывает, что делать с каждым элементом: u.toArray(new String[0])
. С сохранением результатов на законных местах в новом потоке. В этом случае мы преобразуем его в String[]
.. потому что, в конце концов, это 2D-массив String
.. или, скорее, с этого места в коде, 1D-массив String[]
(строковые массивы). Имейте в виду, что u
в конечном счете является ArrayList
. Обратите внимание: вызов toArray
из объекта ArrayList
создаст новый массив переданного в него типа. Здесь мы переходим в new String[0]
. Поэтому он создает новый массив типа String[]
и с длиной, равной длине ArrayList u
. Затем он заполняет этот новый массив строк содержимым ArrayList
и возвращает его. Что оставляет лямбда-выражение и возвращается к map
. Затем map
собирает эти строковые массивы и создает с ними новый поток, он имеет ассоциированный тип String[]
и затем возвращает его. Следовательно, в данном случае map
возвращает Stream<String[]>
. (Ну, на самом деле он возвращает Stream<Object[]>
, что сбивает с толку и требует преобразования, см. ниже)
Поэтому нам просто нужно вызвать toArray
для этого нового потока массивов строк. Но вызов toArray
на Stream<Object[]>
немного отличается от вызова на ArrayList<String>
, как мы делали раньше. Здесь мы должны использовать запутанную ссылку на функцию. Он берет тип из этого: String[][]::new
. Эта функция new
имеет тип String[][]
. По сути, поскольку функция называется toArray, она всегда будет иметь вид []
. В нашем случае, поскольку данные внутри были еще одним массивом, мы просто добавляем еще один []
. Я не уверен, почему NZT-48 не работал над этим. Я бы ожидал, что вызова по умолчанию для toArray()
будет достаточно, видя, что это поток и все такое. Поток, который конкретно Stream<String[]>
. Кто-нибудь знает, почему map
на самом деле возвращает Stream<Object[]>
, а не поток типа, возвращаемого лямбда-выражением внутри?
Теперь, когда мы получили toArray
из нашего потока mainList
, работающего правильно. Мы можем достаточно просто сбросить его в локальную переменную: String[][] stringArray = mainList.stream...
Преобразование 2D ArrayList целых чисел в 2D-массив примитивных целых чисел
Так вот, я знаю, что некоторые из вас там собираются. Это не работает для целых чисел! Как было в моем случае. Однако он работает для энтов, см. выше. Но, если вам нужен массив 2D-примитивов int
из 2D-массива ArrayList
из Integer
(т.е. ArrayList<ArrayList<Integer>>
). Вы должны изменить карту Средиземья. Имейте в виду, что ArrayLists не могут иметь примитивные типы. Поэтому вы не можете позвонить toArray
на ArrayList<Integer>
и ожидать получить int[]
. Вам нужно будет составить карту... снова.
int[][] intArray = mainList.stream().map( u -> u.stream().mapToInt(i->i).toArray() ).toArray(int[][]::new);
Я попытался разнести его для удобства чтения. Но вы можете видеть здесь, что нам нужно снова пройти тот же самый процесс сопоставления. На этот раз мы не можем просто вызвать toArray
в ArrayList u
; как и в приведенном выше примере. Здесь мы вызываем toArray
на Stream
, а не на ArrayList
. Так что по какой-то причине мы не должны передавать это типа, я думаю, что это принимает стероиды для мозга. Поэтому мы можем взять вариант по умолчанию; где он берет удар этого NZT-48 и выясняет очевидное для нас в это [run]time. Я не уверен, почему он не мог просто сделать это в приведенном выше примере. О, верно.... ArrayLists не принимают NZT-48, как Streams. Подождите... о чем я вообще здесь говорю?
Annnyhoow, потому что стримы ооочень умные. Как и Шелдон, нам нужен совершенно новый протокол для работы с ними. По-видимому, развитый интеллект не всегда означает, что с ним легко иметь дело. Следовательно, этот новый mapToInt
необходим для создания нового Stream
, который мы можем использовать более умный toArray
. А лямбда-выражение i->i
в mapToInt
представляет собой простую распаковку Integer
в int
с использованием неявной автоматической распаковки, позволяющей int = Integer
. Что сейчас кажется глупым тривиальным занятием, как будто интеллект имеет свои пределы. Во время моего приключения, изучая все это: я действительно пытался использовать mapToInt(null)
, потому что ожидал поведения по умолчанию. Не аргумент!! (кашель Шелдон кашель) Тогда я говорю в своем лучшем Husker с акцентом девушки из долины. В конце концов, это называется mapToInt
, я думаю, что примерно в 84% случаев (42x2) это будет, типа, i->i
пройдено, типа, всеми, так вроде, о боже! Излишне говорить, что я чувствую себя немного... как... noreferrer">этот парень. Я не знаю, почему это так не работает.
Ну, у меня красные глаза, я наполовину в бреду, наполовину во сне. Я, вероятно, сделал несколько ошибок; пожалуйста, отследите их, чтобы я мог их исправить, и дайте мне знать, если есть еще лучший способ!
PT
person
Pimp Trizkit
schedule
04.12.2015