Java перебор элементов arraylist. Коллекции (Collections) в Java. List. Структуры данных в картинках. ArrayList

Я пытаюсь прочитать CSV файл в списке списков (строк), передать его для получения некоторых данных из базы данных, построить новый список списков новых данных, а затем передать этот список списков, его можно записать в новый файл CSV. Я посмотрел на все, и я не могу найти пример того, как это сделать.

Я бы предпочел не использовать простые массивы, так как файлы будут отличаться по размеру, и я не буду знать, что использовать для размеров массивов. У меня нет проблем с файлами. Я просто не знаю, как обращаться со списком списков.

Большинство примеров, которые я нашел, будут создавать многомерные массивы или выполнять действия внутри цикла, которые считывают данные из файла. Я знаю, что могу это сделать, но хочу написать объектно-ориентированный код. Если бы вы могли предоставить некоторый пример кода или указать мне ссылку, это было бы здорово.

7 ответов

ArrayList> listOLists = new ArrayList>(); ArrayList singleList = new ArrayList(); singleList.add("hello"); singleList.add("world"); listOLists.add(singleList); ArrayList anotherList = new ArrayList(); anotherList.add("this is another list"); listOLists.add(anotherList);

Если вы действительно хотите знать, что файлы дескриптора CSV отлично работают на Java, нехорошо пытаться реализовать CSV-ридер/писатель самостоятельно. Проверьте ниже.

Когда ваш документ CSV включает в себя двойные кавычки или новые строки, вы столкнетесь с трудностями.

Чтобы сначала изучить объектно-ориентированный подход, вам поможет другая реализация (через Java). И я думаю, что это не очень хороший способ управлять одной строкой в ​​списке. CSV не позволяет иметь размер столбца разницы.

Вот пример, который читает список строк CSV в списке списков, а затем перебирает список списков и выводит строки CSV на консоль.

Import java.util.ArrayList; import java.util.List; public class ListExample { public static void main(final String args) { //sample CSV strings...pretend they came from a file String csvStrings = new String { "abc,def,ghi,jkl,mno", "pqr,stu,vwx,yz", "123,345,678,90" }; List> csvList = new ArrayList>(); //pretend you"re looping through lines in a file here for(String line: csvStrings) { String linePieces = line.split(","); List csvPieces = new ArrayList(linePieces.length); for(String piece: linePieces) { csvPieces.add(piece); } csvList.add(csvPieces); } //write the CSV back out to the console for(List csv: csvList) { //dumb logic to place the commas correctly if(!csv.isEmpty()) { System.out.print(csv.get(0)); for(int i=1; i < csv.size(); i++) { System.out.print("," + csv.get(i)); } } System.out.print("\n"); } } }

Довольно просто я думаю. Всего лишь пару замечаний:

    Я рекомендую использовать "Список" вместо "ArrayList" с левой стороны при создании объектов списка. Лучше обойти интерфейс "Список", потому что если позже вам нужно будет изменить что-то вроде Vector (например, вам нужны синхронизированные списки), вам нужно только изменить строку с помощью "нового" оператора. Независимо от того, какую версию списка вы используете, например. Vector или ArrayList, вы все равно всегда просто обходите List .

    В конструкторе ArrayList вы можете оставить список пустым и по умолчанию будет иметь определенный размер, а затем динамически увеличиваться по мере необходимости. Но если вы знаете, насколько велик ваш список, вы иногда можете сэкономить некоторую производительность. Например, если вы знали, что в вашем файле всегда будет 500 строк, вы можете сделать следующее:

List> csvList = new ArrayList>(500);

Таким образом, вы никогда не потеряете время обработки, ожидая, что ваш список будет динамично расти. Вот почему я передаю конструктору конструкцию "linePieces.length". Обычно это не очень много, но иногда полезно.

Надеюсь, что это поможет!

В примере, представленном @tster, показано, как создать список списка. Я приведу пример для итерации по такому списку.

Iterator> iter = listOlist.iterator(); while(iter.hasNext()){ Iterator siter = iter.next().iterator(); while(siter.hasNext()){ String s = siter.next(); System.out.println(s); } }

Что-то вроде этого будет работать для чтения:

String filename = "something.csv"; BufferedReader input = null; List> csvData = new ArrayList>(); try { input = new BufferedReader(new FileReader(filename)); String line = null; while ((line = input.readLine()) != null) { String data = line.split(","); csvData.add(Arrays.toList(data)); } } catch (Exception ex) { ex.printStackTrace(); } finally { if(input != null) { input.close(); } }

Я бы повторил то, что сказал xrath - вам лучше использовать существующую библиотеку для обработки чтения/записи CSV.

Если вы планируете перематывать свою собственную фреймворк, я также предлагаю не использовать List> в качестве вашей реализации - вам, вероятно, будет лучше реализовать классы CSVDocument и CSVRow (которые могут внутри себя использовать List или List соответственно), хотя для пользователей выставляют только неизменяемый список или массив.

В этой статье речь пойдет о, пожалуй, наиболее часто используемых коллекциях List, а именно о таких классах как AbstractList, ArrayList, LinkedList.

List - упорядоченная коллекция иногда называемая списком или последовательностью. Список может содержать повторяющиеся элементы. Разработчик имеет абсолютный контроль над тем, в каком месте списка будет вставлен каждый элемент. Также пользователь может получить доступ к элементам списка по индексу. В дополнение к стандартным операциям интерфейса Collection, List содержит следующие:

  • Доступ по позиции ;
  • Поиск ;
  • Диапазон элементов (sublist) .

Доступ по позиции - манипулирует элементами на основе их индексной позиции в списке.

Не взирая на то, что в интерфейсе List присутствуют методы для доступа к элементу по позиции (индексу), делать это не рекоммендуется. В некоторых реализациях списка (например, LinkedList), эти операции могут выполнятся за время, пропорциональное значению индекса.

Поиск - находит указанный элемент и возвращает его позицию в списке. Для этого служит два метода: indexOf() и lastIndexOf().

Специальный итератор ListIterator - содержит усовершенствованный итератор ListIterator для обработки последовательных свойств списка.

ListIterator позволяет вставлять и заменять элементы и производить перебор элементов в двух направлениях. Ниже приведено объявление интерфейса ListIterator:

Public interface ListIterator extends Iterator { boolean hasNext(); E next(); boolean hasPrevious(); E previous(); int nextIndex(); int previousIndex(); void remove(); //optional void set(E e); //optional void add(E e); //optional }

Описание Iterator:

Public interface Iterator { boolean hasNext(); E next(); void remove(); }

Как видно из вышеприведенного кода, в ListIterator появились методы для управления итератором в обратном порядке: hasPrevious(), previous(), previousIndex().

Диапазон элементов (sublist) - позволяет манипулировать произвольным диапазоном в списке. Это выполняется с помощью метода subList(). Например так:

List stringList = new ArrayList(Arrays.asList("2", "1", "2", "4", "3", "5")); stringList.subList(2, 4).clear(); for(String entry: stringList){ System.out.print(entry); } // Output: 2135

Метод subList() принимает два значения: стартовый индекс и конечный индекс подсписка. Обратите внимание, что диапазон элементов (список) не создается дублированием элементов из родительского списка. Этот список является частью родительского списка из-за чего все манипуляции над ним отражаются на родительском списке. Вышеприведенный пример это хорошо демонстрирует.

Также обратите внимание, что элемент с конечным индексом не включается в список.

На Рис.1 приведена иерархия классов List.

Интерфейсу List также принадлежит два устаревших класса: Vector и Stack, о которых упоминалось в предыдущей статье.

В отличие от Set, List может содержать повторяющиеся элементы. Также может содержать null-элементы.

Некоторые реализации списков имеют ограничения на элементы, которые они могут содержать. Например, в некоторых реализациях запрещено использовать null в качестве элемента для вставки (на ArrayList и LinkedList это правило не распространяется).

Два объекта типа List одинаковы (т.е., метод equals() возвращает true) только в том случае, когда они содержат одинаковые элементы в одном и том же порядке.

ArrayList - наиболее широко используемая реализация List. ArrayList обладает наибольшей производительностью в плане доступа к случайному элементу в массиве.

12 сентября 2011 в 18:19

Структуры данных в картинках. ArrayList

  • Java

Приветствую вас, хабралюди!

Взбрело мне в голову написать несколько статей, о том как реализованы некоторые структуры данных в Java. Надеюсь, статьи будут полезны визуалам (картинки наше всё), начинающим java-визуалам а также тем кто уже умеет писать new ArrayList(), но слабо представляет что же происходит внутри.

Сегодня поговорим о ArrayList-ах

ArrayList - реализует интерфейс List. Как известно, в Java массивы имеют фиксированную длину, и после того как массив создан, он не может расти или уменьшаться. ArrayList может менять свой размер во время исполнения программы, при этом не обязательно указывать размерность при создании объекта. Элементы ArrayList могут быть абсолютно любых типов в том числе и null.

Создание объекта

ArrayList list = new ArrayList();
Только что созданный объект list, содержит свойства elementData и size .

Хранилище значений elementData есть ни что иное как массив определенного типа (указанного в generic), в нашем случае String . Если вызывается конструктор без параметров, то по умолчанию будет создан массив из 10-ти элементов типа Object (с приведением к типу, разумеется).

Внутри метода add(value) происходят следующие вещи:

EnsureCapacity(size + 1);
2) добавляется элемент в конец (согласно значению size ) массива.

ElementData = element;
Весь метод ensureCapacity(minCapacity) рассматривать не будем, остановимся только на паре интересных мест. Если места в массиве не достаточно, новая емкость рассчитывается по формуле (oldCapacity * 3) / 2 + 1 . Второй момент это копирование элементов. Оно осуществляется с помощью native метода System.arraycopy() , который написан не на Java.

// newCapacity - новое значение емкости elementData = (E)new Object; // oldData - временное хранилище текущего массива с данными System.arraycopy(oldData, 0, elementData, 0, size);

Ниже продемонстрирован цикл, поочередно добавляющий 15 элементов:
list.add("1");


...

List.add("10");
При добавлении 11-го элемента, проверка показывает что места в массиве нет. Соответственно создается новый массив и вызывается System.arraycopy() .

Добавление в «середину» списка

list.add(5, "100");
Добавление элемента на позицию с определенным индексом происходит в три этапа:

1) проверяется, достаточно ли места в массиве для вставки нового элемента;

EnsureCapacity(size+1);
2) подготавливается место для нового элемента с помощью System.arraycopy() ;

System.arraycopy(elementData, index, elementData, index + 1, size - index);


3) перезаписывается значение у элемента с указанным индексом.

Как можно догадаться, в случаях, когда происходит вставка элемента по индексу и при этом в вашем массиве нет свободных мест, то вызов System.arraycopy() случится дважды: первый в ensureCapacity() , второй в самом методе add(index, value) , что явно скажется на скорости всей операции добавления.

В случаях, когда в исходный список необходимо добавить другую коллекцию, да еще и в «середину», стоит использовать метод addAll(index, Collection) . И хотя, данный метод скорее всего вызовет System.arraycopy() три раза, в итоге это будет гораздо быстрее поэлементного добавления.

Удаление элементов

Удалять элементы можно двумя способами:
- по индексу remove(index)
- по значению remove(value)

С удалением элемента по индексу всё достаточно просто

List.remove(5);
Сначала определяется какое количество элементов надо скопировать

Int numMoved = size - index - 1;
затем копируем элементы используя System.arraycopy()

System.arraycopy(elementData, index + 1, elementData, index, numMoved);
уменьшаем размер массива и забываем про последний элемент

ElementData[--size] = null; // Let gc do its work

При удалении по значению, в цикле просматриваются все элементы списка, до тех пор пока не будет найдено соответствие. Удален будет лишь первый найденный элемент.

Дополнение 1: Как верно заметил

При создании таких игр как "Змейка" или "Морской бой" было удобно использовать двумерный массив для хранения данных игрового поля. Но использование только массивов будет не очень удобным при создании игры "Пасьянс-Косынка". В играх "Змейка", "Морской бой" размеры игровых полей были фиксированного размера и не изменялись во время игры. Массив удобен для хранения, изменения и использования фиксированного набора значений. В игре "Пасьянс-Косынка" нам понадобится хранить наборы значений,количество которых можно увеличивать или уменьшать. В этом нам поможет список значений,который в языке Javaможно реализовать с помощью классаArrayList:

//Подключаем класс ArrayList

import java.util.ArrayList;

Рассмотрим примеры работы со списком на примере списка целых чисел.

Прежде всего, создадим пустой список значений целых чисел:

// Подключаем классArrayList

import java.util.ArrayList;

public class kosinka {

public static void main(String args) {

//Создаем пустой список значений целых чисел

ArrayList lst = new ArrayList();

Внутри угловых скобок указывается тип элементов списка ,Integer –это целое число. Значения элементов списка могут быть любого типа. Создание, например,списка кнопок JButton выглядит так:

ArrayList lst = new ArrayList();

Но сейчас мы будем рассматривать список целых чисел. Работа со списками разных типов значений происходит по одинаковой схеме.

Изначально список пустой:

ArrayList lst = new ArrayList();

Добавим в него три новых элемента с помощью метода add():

// Создаем пустой список значений целых чисел

ArrayList lst = new ArrayList();

//Добавим первый элемент в список

//Добавим второй элемент в список

//Добавим третий элемент в список

Добавление элементов происходит в конец списка (см. рис. 10).

Теперь рассмотрим основные приемы работы со списком:

// Получаем количество элементов в списке

// В данном случае – три (см. рис. 10)

int kol = lst.size();

// Получение значения элемента по номеру

// В данном случае – 100 (см. рис. 10)

int val = lst.get(0);

// Удаление элемента из списка по номеру

// В данном случае – самый верхний (см. рис. 10)

// Удаление всех элементов из списка

С помощью метода size()можно определить количество элементов в списке.

Метод get()позволяет получить значение любого элемента по номеру, нумерация начинается с нуля. Метод remove()удаляет элемент из списка по его номеру, нумерация начинается с нуля.После удаления элемента список автоматически сжимается. Метод clear() позволяет удалить сразу все элементы из списка. Также как и в массиве, каждый элемент списка имеет свой номер. Самый первый элемент списка имеет номер нуль 0, а самый последний элемент имеет номер size()-1. Этих методов работы со списком будет достаточно при создании игры "Пасьянс-Косынка". На игровом поле будут находиться карты,разложенные в несколько стопок.Пользователь будет переносить карты из одной стопки в другую. Карты будут добавляться в конец стопки карт. Поэтому всех перечисленных выше методов будет достаточно.