Преобразование ArrayList в 2D-массив, содержащий различные длины массивов
Итак, у меня есть:
ArrayList<ArrayList<String>>
Что содержит x число ArrayLists, которые содержат другое y число строк. Чтобы продемонстрировать:
Index 0:
String 1
String 2
String 3
Index 1:
String 4
Index 2:
Index 3:
String 5
String 6
Если индекс относится к индексу массива, содержащему строку.
Как я могу преобразовать это в 2D-массив, который выглядит так:
{{String1, String2, String3},{String4}, {}, {String5, String6}}
Большое вам спасибо.
Ответы
Ответ 1
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()]);
}
где arrayList
- ваш ArrayList<ArrayList<String>>
(или любой List<List<String>>
, измените первую строку внутри цикла for
)
Ответ 2
Добро пожаловать в мир с Java 8!
Мне потребовалась целая ночь, чтобы не спать, чтобы узнать, что нужно, чтобы написать эту чертовую линию кода. Я уверен, что он уже там где-то, но я не мог его найти. Поэтому я делюсь своими часами и часами исследований, наслаждаюсь. Woot!
Предполагая, что:
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. Этот поток немного похож на Vector, связанный с LinkedList, и у них был ребенок. И этот ребенок, позже в жизни, дозаправлялся на некоторых NZT-48. Я отвлекся; mainList.stream()
возвращает поток элементов ArrayList<String>
. Или даже в geekier говорят: mainList.stream()
возвращает Stream<ArrayList<String>>
, sorta.
-
Вызовите функцию .map
в этом потоке, которая вернет новый поток с содержимым, которое соответствует новому типу, заданному параметрами, переданными в map
. Эта функция map
будет скрывать каждый элемент нашего потока для нас. Он имеет встроенный оператор foreach
. Чтобы это сделать; функция map
принимает в качестве своего параметра лямбда-выражение. Выражение Lambda подобно простой встроенной однострочной функции. У этого есть два типа данных, которые можно использовать для Jiggy. Во-первых, это тип данных в потоке, на который он был вызван (mainList.stream()
). Следующий тип - это тип данных, к которым он будет u → u.toArray(new String[0])
, который находится в правой половине выражения лямбда: u → u.toArray(new String[0])
. Здесь u
- идентификатор, который вы выбираете так же, как при использовании инструкции foreach
. Первая половина объявляет это так: u ->
. И как и foreach
, переменная u
теперь будет каждым элементом в потоке, поскольку она итерации через поток. Таким образом, u
относится к типу данных, что элементы исходного потока являются тем, что они являются ими. Правая половина выражения Lambda показывает, что делать с каждым элементом: 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[]>
а не поток типа, возвращаемого выражением Lambda внутри?
-
Теперь, когда мы получили toArray
из нашего mainList
потока, действующего правильно. Мы можем просто сбрасывать его в локальную переменную достаточно просто: String[][] stringArray = mainList.stream...
Преобразование 2D ArrayList из целых чисел в 2D-массив примитивных ints
Теперь, я знаю, что некоторые из вас идут туда. "Это не работает для ints!" Как и в моем случае. Однако он работает для " Ents ", см. Выше. Но если вам нужен 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 и выясняет очевидное для нас это [время выполнения]. Я не уверен, почему он не мог просто сделать это в приведенном выше примере. О, это правильно.... ArrayLists не берут NZT-48, как Streams. Подождите... о чем я вообще говорю?
Annnyhoow, потому что потоки настолько умны. Как и Шелдон, нам нужен совершенно новый протокол, чтобы справиться с ними. По-видимому, продвинутый интеллект не всегда означает, что с ним можно справиться. Поэтому этот новый mapToInt
необходим для создания нового Stream
который мы можем использовать с его умным toArray
. И i->i
Lambda в mapToInt
является простым распаковкой Integer
для int
, используя неявное авто-unboxing, которое позволяет int = Integer
. Который теперь кажется глупым тривиальным делом, как будто разум имеет свои пределы. Во время моего приключения изучая все это: я на самом деле пытался использовать mapToInt(null)
потому что я ожидал поведения по умолчанию. Не аргумент! (кашель Шелдон кашля) Тогда я сказал в своем лучшем Husker долины девушки акцент, "Afterall, это называется mapToInt
, я предположил бы, что, вроде бы, 84% времени (42 х2) будет, как, прошли i->i
, как, все, так что, omgawd! " Само собой разумеется, я чувствую себя немного... вроде.. этого парня. Не знаю, почему это так не работает!
Ну, я красноглазый, полуразличный и полуспящий. Я, вероятно, допустил некоторые ошибки; пожалуйста, проведите их, чтобы я мог их исправить и сообщить, если есть еще лучший способ!
PT
Ответ 3
Вы можете использовать метод toArray()
для преобразования массива ArrayList в массив. Поскольку у вас есть ArrayList в ArrayList, вам нужно будет перебирать каждый элемент и применять этот метод.
Что-то вроде этого: -
ArrayList<ArrayList<String>> mainList = new ArrayList<ArrayList<String>>();
// populate this list here
//more code
// convert to an array of ArrayLists
ArrayList<String[]> tempList = new ArrayList<String[]>();
for (ArrayList<String> stringList : mainList){
tempList.add((String[])stringList.toArray());
}
//Convert to array of arrays - 2D array
String [][]list = (String[][])tempList.toArray();
Подробнее о toArray()
здесь.
Ответ 4
ArrayList<ArrayList<String>> list= new ArrayList<ArrayList<String>>();
ArrayList<String> a = new ArrayList<String>();
ArrayList<String> b = new ArrayList<String>();
a.add("Hello");
b.add("Hell");
list.add(a);
list.add(b);
Object[][] array = new Object[list.size()][];
Iterator<ArrayList<String>> iterator = list.iterator();
int i = 0;
while(iterator.hasNext()){
array[i] = iterator.next().toArray();
}
Вы можете использовать приведенный ниже фрагмент для преобразования Object [] в String []
String[] stringArray = Arrays.copyOf(objectArray, objectArray.length, String[].class);
Ответ 5
Например:
public String[][] toArray(List<List<String>> list) {
String[][] r = new String[list.size()][];
int i = 0;
for (List<String> next : list) {
r[i++] = next.toArray(new String[next.size()]);
}
return r;
}
Ответ 6
Этот полный программный код отвечает на этот вопрос вполне понятным образом. Просто вставьте его и запустите:
import java.util.ArrayList;
import java.util.List;
public class ListTo2Darray {
public String[][] toArray(List<List<?>> list) {
String[][] r = new String[list.size()][];
int i = 0;
for (List<?> next : list) {
r[i++] = next.toArray(new String[next.size()]);
}
return r;
}
public static void main(String[]arg){
String[][] sham;
List<List<?>> mList = new ArrayList();
List<String> a= new ArrayList();
List<String> b= new ArrayList();
a.add("a"); a.add("a");
b.add("b"); b.add("b");
mList.add(a); mList.add(b);
ListTo2Darray mt= new ListTo2Darray();
sham= mt.toArray(mList);
System.out.println(sham[0][0]);
System.out.println(sham[0][1]);
System.out.println(sham[1][0]);
System.out.println(sham[1][1]);
}
}