Преобразование 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

Где index относится к индексу массива, содержащему строку.

Как я могу преобразовать это в 2D-массив, который выглядит так:

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

Большое спасибо.


person Stefan Dunn    schedule 06.04.2012    source источник
comment
Вот ответ, который включает в себя массив int (примитивные типы данных) stackoverflow.com/a/62973865/6648326   -  person MasterJoe    schedule 05.08.2020


Ответы (7)


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)

person michele b    schedule 06.04.2012
comment
Что делать, если у меня есть ArrayList‹String[]› и я хочу преобразовать его в 2D-массив? - person shridatt; 22.06.2015
comment
извините, я пропустил это, возможно, вы уже поняли это... В любом случае, это просто String[][] array2D = new String[arrayList.size()][]; for (int i = 0; i < array2D.length; i++) { String[] row = arrayList.get(i); array2D[i] = row; } - person michele b; 29.06.2015
comment
не работает для меня. окончательный массив 2d имеет только один столбец для каждой строки. - person rafa; 21.10.2018
comment
как вы проверяете и как выглядит ваш ввод? - person michele b; 22.10.2018

Добро пожаловать в мир 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. Возьмите поток mainList 2D ArrayList. Этот поток немного похож на вектор, связанный с LinkedList, и у них есть ребенок. И этот ребенок в более позднем возрасте подсел на какой-то NZT-48. Я отвлекся; mainList.stream() возвращает поток из ArrayList<String> элементов. Или, говоря еще более гиковски: mainList.stream() возвращает Stream<ArrayList<String>>, вроде как.

  2. Вызовите функцию .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[]>, что сбивает с толку и требует преобразования, см. ниже)

  3. Поэтому нам просто нужно вызвать toArray для этого нового потока массивов строк. Но вызов toArray на Stream<Object[]> немного отличается от вызова на ArrayList<String>, как мы делали раньше. Здесь мы должны использовать запутанную ссылку на функцию. Он берет тип из этого: String[][]::new. Эта функция new имеет тип String[][]. По сути, поскольку функция называется toArray, она всегда будет иметь вид []. В нашем случае, поскольку данные внутри были еще одним массивом, мы просто добавляем еще один []. Я не уверен, почему NZT-48 не работал над этим. Я бы ожидал, что вызова по умолчанию для toArray() будет достаточно, видя, что это поток и все такое. Поток, который конкретно Stream<String[]>. Кто-нибудь знает, почему map на самом деле возвращает Stream<Object[]>, а не поток типа, возвращаемого лямбда-выражением внутри?

  4. Теперь, когда мы получили 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
comment
Поскольку map принимает лямбду (которая, по общему мнению, знает тип данных каждой стороны лямбды), она должна иметь возможность передавать информацию об этом типе данных дальше. Итак, несмотря на мою сумасшедшую болтовню, мне все же очень хотелось бы получить ответ на два упомянутых выше вопроса: 1) Почему map на самом деле возвращает Stream<Object[]> как поведение по умолчанию, а не поток типа, возвращаемого лямбда-выражением внутри? --- 2) Почему mapToInt не использует по умолчанию i->i ? - person Pimp Trizkit; 11.02.2018
comment
Я использовал ваш ответ pastebin.com/iNkwetbW. Я получаю предупреждение о том, что он переопределяет несколько методов, когда я кодировал это в IntelliJ IDEA. Как убрать эти предупреждения? - person Ralf Rafael Frix; 21.06.2019
comment
Переопределяет? Это кажется странным. Я бы не сказал, что эта строка кода что-то переопределяет. Но я понятия не имею, что такое IntelliJ IDEA и в какой среде она существует. Я ничем не могу помочь. Я надеюсь, что кто-то еще здесь читает это и может помочь вам. Может быть, начать разбивать утверждение на более мелкие части и проверять их по отдельности и смотреть, в чем проблема. Например, попробуйте вытащить .stream() из ArrayList и просто вывести его на экран, чтобы убедиться, что части работают.. затем перейдите к .map()... и т. д. - person Pimp Trizkit; 22.06.2019
comment
Я бы выбрал новый ArrayList‹›() (а не новый ArrayList()) - person Enrico Giurin; 02.09.2019
comment
Если кому-то нужен рабочий код для преобразования 2d-массива int в список - stackoverflow.com/a/62973891/6648326 - person MasterJoe; 19.07.2020

Вы можете использовать метод 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() здесь .

person vaisakh    schedule 06.04.2012

Например:

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;
}
person Eugene Retunsky    schedule 06.04.2012

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);
person Chandra Sekhar    schedule 06.04.2012

Этот полный код мини-программы отвечает на этот вопрос достаточно ясно. Просто вставьте и запустите его:

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]);
    }

}
person Harjit Singh    schedule 27.06.2016

queries=[[1,5,3],[4,8,7],[6,9,1]]
h=queries.size();

        for(i=0;i<h;i++){
            for(j=0;j<3;j++){
                y[i][j]= ( ( queries.get(i) ).get(j) );
            }  
        }

Что он будет делать, так это то, что в y[i][j] в этом операторе сначала query.get(i) выберет первый блок списка, т.е. в i=0 он выберет [1,5,3], а затем в j=0 он выберет 1 из [1,5,3] и т.д.

объяснение цикла: y[][]=[ 1 5 3 4 8 7 6 9 1 ]

Примечание. Замените запросы указанным массивом.

Пожалуйста, дайте мне знать, если это работает, или я должен дать другой способ решить проблему

person Tarun Singh Rawat    schedule 10.06.2021