Рубрики
Без рубрики

Преобразование коллекции в ArrayList в Java

Краткое руководство по созданию списков массивов, приведенное в коллекции на Java.

Автор оригинала: baeldung.

1. Обзор

Преобразование коллекций Java из одного типа в другой-обычная задача программирования. В этом уроке мы преобразуем любой тип Collection в ArrayList .

На протяжении всего урока мы будем предполагать, что у нас уже есть коллекция объектов Foo . Оттуда мы создадим ArrayList , используя различные подходы.

2. Определение Нашего Примера

Но прежде чем продолжить, давайте смоделируем наши входные и выходные данные.

Наш источник может быть любым типом коллекции, поэтому мы объявим его с помощью интерфейса Collection :

Collection srcCollection;

Нам нужно создать ArrayList с тем же типом элемента:

ArrayList newList;

3. Использование конструктора ArrayList

Самый простой способ скопировать коллекцию в новую коллекцию-это использовать ее конструктор.

В нашем предыдущем руководстве по ArrayList мы узнали , что конструктор ArrayList может принимать параметр коллекции:

ArrayList newList = new ArrayList<>(srcCollection);
  • Новый ArrayList содержит неглубокую копию элементов Foo в исходной коллекции.
  • Порядок такой же, как и в исходной коллекции.

Простота конструктора делает его отличным вариантом в большинстве сценариев.

4. Использование API потоков

Теперь давайте воспользуемся API Streams для создания списка массивов из существующей коллекции :

ArrayList newList = srcCollection.stream().collect(toCollection(ArrayList::new));

В этом фрагменте:

  • Мы берем поток из исходной коллекции и применяем оператор collect() для создания списка
  • Мы указываем ArrayList::new , чтобы получить нужный нам тип списка
  • Этот код также создаст неглубокую копию.

Если бы мы не беспокоились о точном типе List , мы могли бы упростить:

List newList = srcCollection.stream().collect(toList());

Обратите внимание, что to Collection() и to List() статически импортируются из Collectors . Чтобы узнать больше, пожалуйста, обратитесь к нашему руководству по сборщикам Java 8 .

5. Глубокое Копирование

Прежде чем мы упомянули о “неглубоких копиях”. Под этим мы подразумеваем, что элементы в новом списке являются точно такими же Foo экземплярами , которые все еще существуют в исходной коллекции. Поэтому мы скопировали Foo s в новый список по ссылке.

Если мы изменим содержимое экземпляра Foo в любой коллекции, эта модификация будет отражена в обеих коллекциях . Следовательно, если мы хотим изменить элементы в любой коллекции без изменения другой, нам нужно выполнить “глубокую копию”.”

Чтобы глубоко скопировать Foo , мы создаем совершенно новый Foo экземпляр для каждого элемента . Следовательно, все поля Foo необходимо скопировать в новые экземпляры.

Давайте определим наш класс Foo , чтобы он знал, как глубоко копировать себя:

public class Foo {

    private int id;
    private String name;
    private Foo parent;

    public Foo(int id, String name, Foo parent) {
        this.id = id;
        this.name = name;
        this.parent = parent;
    }

    public Foo deepCopy() {
        return new Foo(
          this.id, this.name, this.parent != null ? this.parent.deepCopy() : null);
    }
}

Здесь мы видим поля id и name are int и String . Эти типы данных копируются по значению. Следовательно, мы можем просто назначить их обоих.

Поле parent – это другое Foo , которое является классом. Если Foo мутировал, любой код, который использует эту ссылку, будет затронут этими изменениями. Мы должны глубоко скопировать родительское поле .

Теперь мы можем вернуться к нашему ArrayList преобразованию. Нам просто нужен оператор map , чтобы вставить глубокую копию в поток:

ArrayList newList = srcCollection.stream()
  .map(foo -> foo.deepCopy())
  .collect(toCollection(ArrayList::new));

Мы можем изменять содержимое любой коллекции, не затрагивая другую.

Глубокое копирование может быть длительным процессом в зависимости от количества элементов и глубины данных. Использование параллельного потока здесь может обеспечить повышение производительности, если это необходимо.

6. Управление порядком списка

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

Если мы хотим изменить этот порядок , мы можем применить оператор sorted() к потоку . Чтобы отсортировать Foo объекты по имени:

ArrayList newList = srcCollection.stream()
  .sorted(Comparator.comparing(Foo::getName))
  .collect(toCollection(ArrayList::new));

Более подробную информацию о заказе потоков мы можем найти в этом более раннем руководстве .

7. Заключение

Конструктор ArrayList – это эффективный способ получить содержимое Коллекции в новый ArrayList .

Однако, если нам нужно настроить результирующий список, API потоков предоставляет мощный способ изменить процесс.

Код, используемый в этой статье, можно найти полностью на GitHub .