Перейти к содержимому

Как скопировать коллекцию java

  • автор:

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

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

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

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

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

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

 CollectionFoo> srcCollection; 

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

 ArrayListFoo> newList; 

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

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

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

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

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

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

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

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

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

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

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

 ListFoo> newList = srcCollection.stream().collect(toList()); 

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

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

Прежде чем мы упомянули «мелкие копии». Под этим мы подразумеваем, что элементы в новом списке — это точно такие же экземпляры Foo , которые все еще существуют в исходной коллекции. Поэтому мы скопировали Foo в newList по ссылке.

Если мы изменим содержимое экземпляра 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 имеют тип int и String . Эти типы данных копируются по значению. Следовательно, мы можем просто назначить их обоих.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Копирование ArrayList

Есть ArrayList со значениями.
Вопрос: как можно без циклов полностью скопировать значение массива?

ArrayList a; ArrayList b; a = b;// Присвоить все значения b в этот массив. 

Отслеживать

8,910 11 11 золотых знаков 31 31 серебряный знак 55 55 бронзовых знаков

задан 31 авг 2016 в 10:53

960 1 1 золотой знак 7 7 серебряных знаков 17 17 бронзовых знаков

4 ответа 4

Сортировка: Сброс на вариант по умолчанию

  1. Можно с использованием метода Collections.copy(destination, source) (минус в том, что нужно задать ArrayList b нужного размера, иначе будет ругаться):
Collections.copy(b,a); 
ArrayList b = (ArrayList)a.clone(); 
ArrayList a; ArrayList b = new ArrayList(a); 
ArrayList a; ArrayList b = new ArrayList(); b.addAll(0, a); 

Отслеживать

ответ дан 31 авг 2016 в 11:04

8,910 11 11 золотых знаков 31 31 серебряный знак 55 55 бронзовых знаков

ArrayList a = new ArrayList(Arrays.asList("abc", "mno")); ArrayList b; b = (ArrayList) a.clone(); 

А можно ещё так:

ArrayList b = new ArrayList(a); 

Отслеживать

ответ дан 31 авг 2016 в 11:04

10.7k 6 6 золотых знаков 47 47 серебряных знаков 99 99 бронзовых знаков

ArrayList a; ArrayList b; a=b.clone(); 

Отслеживать

ответ дан 31 авг 2016 в 10:56

12.1k 2 2 золотых знака 25 25 серебряных знаков 47 47 бронзовых знаков

В листе хранятся ссылки на объекты, поэтому копируются именно они, т.е. через новый лист вы по факту работаете со старыми объектами. если хотите перенести скопировать значения, то сначала вам нужно создать новый объект для хранения значения при помощи оператора new .

ArrayList toCopy = new ArrayList<>(); toCopy.add("Something"); ArrayList copy = new ArrayList<>(); copy.add(new String(toCopy.get(0))); 

Отслеживать

51.6k 201 201 золотой знак 63 63 серебряных знака 245 245 бронзовых знаков

Скопируйте список в другой список в Java

В этом кратком руководстве мы рассмотрим различные способы копирования списка в другой список и распространенную ошибку, возникающую в процессе.

Для ознакомления с использованием коллекций см . эту статью здесь .

2. Конструктор​

Простой способ скопировать список — использовать конструктор, который принимает коллекцию в качестве аргумента:

 ListPlant> copy = new ArrayList>(list); 

Поскольку здесь мы копируем ссылки, а не клонируем объекты, каждое исправление, сделанное в одном элементе, повлияет на оба списка.

Таким образом, хорошо использовать конструктор для копирования неизменяемых объектов:

 ListInteger> copy = new ArrayList>(list); 

Integer — неизменяемый класс; его значение устанавливается при создании экземпляра и никогда не может измениться.

Таким образом, ссылка Integer может совместно использоваться несколькими списками и потоками, и никто не может изменить ее значение.

3. Список ConcurrentAccessException ​

Распространенной проблемой при работе со списками является ConcurrentAccessException . Обычно это означает, что мы изменяем список, когда пытаемся его скопировать, скорее всего, в другом потоке.

Чтобы решить эту проблему, мы должны:

  • Используйте коллекцию, предназначенную для одновременного доступа
  • Заблокируйте коллекцию соответствующим образом, чтобы перебрать ее
  • Найдите способ избежать копирования оригинальной коллекции

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

Для получения дополнительной информации, пожалуйста, обратитесь к этой статье .

Если мы хотим заблокировать Collection , можно использовать примитив блокировки для сериализованного доступа для чтения/записи, например ReentrantReadWriteLock .

4. Добавить все ​

Другой подход к копированию элементов — использование метода addAll :

 ListInteger> copy = new ArrayList>();  copy.addAll(list); 

При использовании этого метода важно помнить, что, как и в случае с конструктором, содержимое обоих списков будет ссылаться на одни и те же объекты.

5. Коллекции.copy ​

Класс Collections состоит исключительно из статических методов, которые работают с коллекциями или возвращают их.

Одним из них является copy , для которого требуется исходный список и целевой список, длина которого не меньше исходного.

Он будет поддерживать индекс каждого скопированного элемента в списке назначения, например оригинала:

 ListInteger> source = Arrays.asList(1,2,3);   ListInteger> dest = Arrays.asList(4,5,6);   Collections.copy(dest, source); 

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

Если размер списка назначения больше, чем размер источника:

 ListInteger> source = Arrays.asList(1, 2, 3);   ListInteger> dest = Arrays.asList(5, 6, 7, 8, 9, 10);   Collections.copy(dest, source); 

Здесь только первые три элемента были перезаписаны, а остальные элементы в списке сохранены.

6. Использование Java 8​

Эта версия Java расширяет наши возможности, добавляя новые инструменты. В следующих примерах мы рассмотрим Stream :

 ListString> copy = list.stream()   .collect(Collectors.toList()); 

Главное преимущество этого варианта — возможность использовать пропуск и фильтры. В следующем примере мы пропустим первый элемент:

 ListString> copy = list.stream()   .skip(1)   .collect(Collectors.toList()); 

Также можно фильтровать по длине строки или сравнивать атрибуты наших объектов:

 ListString> copy = list.stream()   .filter(s -> s.length() > 10)   .collect(Collectors.toList()); 
 ListFlower> flowers = list.stream()   .filter(f -> f.getPetals() > 6)   .collect(Collectors.toList()); 

Вероятно, мы хотим работать нулевым безопасным способом:

 ListFlower> flowers = Optional.ofNullable(list)   .map(List::stream)   .orElseGet(Stream::empty)   .collect(Collectors.toList()); 

Вероятно, мы также захотим пропустить элемент таким образом:

 ListFlower> flowers = Optional.ofNullable(list)   .map(List::stream).orElseGet(Stream::empty)   .skip(1)   .collect(Collectors.toList()); 

7. Использование Java 10​

Наконец, одна из последних версий Java позволяет нам создать неизменяемый список , содержащий элементы данной коллекции:

 ListT> copy = List.copyOf(list); 

Единственным условием является то, что данная коллекция не должна быть нулевой или содержать нулевые элементы.

8. Заключение​

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

Как всегда, образцы кода можно найти на GitHub, здесь и здесь .

  • 1. Обзор
  • 2. Конструктор
  • 3. Список ConcurrentAccessException
  • 4. Добавить все
  • 5. Коллекции.copy
  • 6. Использование Java 8
  • 7. Использование Java 10
  • 8. Заключение

Как скопировать массив в Java? Копирование массивов

В статье поговорим о некоторых методах копирования массивов в Java. Этот язык программирования имеет встроенные методы, предназначенные для решения данных задач. С их помощью вы сможете сделать как полную копию массива, так и выполнить копирование некоторых элементов массива.

Методы для копирования массивов в Java

В Java существует довольно много специальных методов для копирования массивов:

1.В первую очередь, хотелось бы упомянуть Object.clone() — этот метод вы можете использовать для полного копирования массива. Соответственно, если вы хотите скопировать массив частично, этот способ вам не подойдёт.

2.Следующий на очереди — System.arraycopy() — по сути, это один из наилучших способов создать частичную копию массива в Java. В этом методе определены следующие параметры: — массив, элементы которого планируем копировать; — индекс элемента; — итоговый (результирующий) массив; — первый элемент итогового массива; — общее число элементов, предназначенных для копирования.

К примеру, написав System.arraycopy(источник, 2, назначения, 5, 7), вы скопируете семь элементов из массива-источника в итоговый массив, начиная со второго индекса источника в пятый индекс результирующего массива.

3. Arrays.copyOf() — подойдёт вам, если планируете выполнить копирование нескольких первых элементов массива либо сделать полную копию массива. Способ не так универсален, как System.arraycopy() , но так же прост в применении.

4. Arrays.copyOfRange() — полезный метод, обеспечивающий частичное копирование массива.

В принципе, для решения большинства задач по полному либо частичному копированию массивов в Java вышеперечисленных методов вам вполне хватит. Только учтите, что методы, встроенные в Java для копирования, годятся лишь для одномерных массивов.

Пришла пора посмотреть на них в действии.

 
import java.util.Arrays; public class JavaArrayCopyExample < /** * В этом классе мы демонстрируем методы копирования массивов в java * @param args */ public static void main(String[] args)  int[] source = ; int[] source1 = ; int[] destination=null; System.out.println("Массив-источник = " + Arrays.toString(source)); destination = copyFirstFiveFieldsOfArrayUsingSystem(source); System.out.println("Копируем первые пять элементов массива, если они есть. Итоговый массив = " + Arrays.toString(destination)); destination = copyFirstFiveFieldsOfArrayUsingSystem(source1); System.out.println("Копируем первые пять элементов массива, если они есть. Итоговый массив = " + Arrays.toString(destination)); destination = copyFullArrayUsingSystem(source); System.out.println("Осуществляем полное копирование массива посредством System.copyarray(). Итоговый массив = " + Arrays.toString(destination)); destination = copyFullArrayUsingClone(source); System.out.println("Осуществляем полное копирование массива посредством clone(). Итоговый массив = " + Arrays.toString(destination)); destination = copyFullArrayUsingArrayCopyOf(source); System.out.println("Осуществляем полное копирование массива посредством Arrays.copyOf(). Итоговый массив = " + Arrays.toString(destination)); destination = copyLastThreeUsingArrayCopyOfRange(source); System.out.println("Копируем последние три элемента массива посредством Arrays.copyOfRange(). Итоговый массив = " + Arrays.toString(destination)); > /** * Данный метод выполняет полное копирование массива посредством Arrays.copyOf() * @param source * @return */ private static int[] copyFullArrayUsingArrayCopyOf(int[] source)  return Arrays.copyOf(source, source.length); > /** * Данный метод копирует последние три элемента посредством * Arrays.copyOfRange() * @param source * @return */ private static int[] copyLastThreeUsingArrayCopyOfRange(int[] source)  // проверка длины для предотвращения java.lang.ArrayIndexOutOfBoundsException //но для простоты метода мы этого не делаем :) return Arrays.copyOfRange(source, source.length-3, source.length); > /** * Данный метод выполняет полное копирование массива посредством clone() * @param source * @return */ private static int[] copyFullArrayUsingClone(int[] source)  return source.clone(); > /** * Данный метод выполняет полное копирование массива посредством System.arraycopy() * @param source * @return */ private static int[] copyFullArrayUsingSystem(int[] source)  int[] temp=new int1; System.arraycopy(source, 0, temp, 0, source.length); return temp; > /** * Метод копирует первые пять элементов * посредством System.arraycopy() * @param source * @return */ private static int[] copyFirstFiveFieldsOfArrayUsingSystem(int[] source) < if(source.length >5)< int[] temp=new int[5]; System.arraycopy(source, 0, temp, 0, 5); return temp; >else < int[] temp=new int1; System.arraycopy(source, 0, temp, 0, source.length); return temp; >> >

Теперь посмотрим на результат выполнения нашей программы:

 
Массив-источник = [1, 2, 3, 4, 5, 6, 7, 8, 9] Копируем первые пять элементов массива, если они есть. Итоговый массив = [1, 2, 3, 4, 5] Копируем первые пять элементов массива, если они есть. Итоговый массив = [1, 2, 3] Осуществляем полное копирование массива посредством System.copyarray(). Итоговый массив = [1, 2, 3, 4, 5, 6, 7, 8, 9] Осуществляем полное копирование массива посредством clone(). Итоговый массив = [1, 2, 3, 4, 5, 6, 7, 8, 9] Осуществляем полное копирование массива посредством Arrays.copyOf(). Итоговый массив = [1, 2, 3, 4, 5, 6, 7, 8, 9] Копируем последние три элемента массива посредством Arrays.copyOfRange(). Итоговый массив = [7, 8, 9]

Вот и всё. Если же вы хотите получить действительно продвинутые знания по Java, приходите на наш курс:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *