java.util.List를 다른 java.util.List에 복사하는 방법


135

나는이 List<SomeBean>웹 서비스에서 채워집니다. 해당 목록의 내용을 동일한 유형의 빈 목록으로 복사 / 복제하고 싶습니다. 목록 복사를위한 Google 검색에서 Collections.copy()방법 을 사용하도록 제안했습니다 . 내가 본 모든 예제에서 대상 목록에는 복사를 수행 할 정확한 항목 수가 포함되어 있어야합니다.

사용중인 목록이 웹 서비스를 통해 채워지고 수백 개의 객체가 포함되어 있으므로 위의 기술을 사용할 수 없습니다. 아니면 잘못 사용하고 있습니까 ?? !! 어쨌든, 그것을 작동시키기 위해, 나는 이와 같은 것을 시도했지만 여전히 IndexOutOfBoundsException.

List<SomeBean> wsList = app.allInOne(template);

List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList.size());   
Collections.copy(wsListCopy,wsList);
System.out.println(wsListCopy.size());

사용하려고했지만 나중에 코드에서 wsListCopy=wsList.subList(0, wsList.size())얻었습니다 ConcurrentAccessException. 명중과 재판. :)

어쨌든 내 질문은 간단 합니다. 목록의 전체 내용을 다른 목록에 어떻게 복사 할 수 있습니까? 물론 반복하지 않습니다.


11
모든 사본은 물론 반복을 사용합니다. 숨길 수는 있지만 여전히 거기에 있습니다.
피터 로리

1
우선 : 그 목록을 복사해야합니까? 그렇게하는 동기는 무엇입니까?
ppeterka

2
예, 반복은 해당 레이어 아래에 숨겨져 있습니다. 그러나 반복 답변을 방지하기 위해 주석이 추가되었습니다. :)
Mono Jamoon

@ppeterka removeAll ()과 같은 목록에서 작업을 수행하고 있습니다. 이로 인해 목록에서 원래 데이터가 손실됩니다. 그리고 "그 데이터"도 나중에 필요합니다.
Mono Jamoon

에 의해 반환되는 목록의 실제 유형은 무엇입니까 app.allInOne(template)? ArrayList?
Andremoniy

답변:


235

이것을 사용하십시오 :

List<SomeBean> newList = new ArrayList<SomeBean>(otherList);

참고 : 수정하면 여전히 스레드로부터 안전하지 otherList다른 스레드에서, 당신은 확인 할 수 있습니다 otherList(심지어 및 newListA) CopyOnWriteArrayList- 나 같은 프리미티브 잠금을 사용, 예를 들어 ReentrantReadWriteLock 어떤 목록입니다 읽기 직렬화 / 쓰기 액세스를 동시에 액세스.


1
이제는 정말 바보 같은 느낌이 듭니다. :) 이렇게 구성하면 아무 것도 던져지지 않기를 바랍니다 ConcurrentAccessException.
Mono Jamoon


5
ConcurrentModifcationException이 발생하면 +1이고, 먼저 해결해야하는 동시성 문제가 있습니다.
피터 로리

5
질문에 "복사 / 복제"가 언급 된 경우 왜이 답변이 많은 점수를 받고 있습니까? 다른 답변이 복제와 아무런 관련이없는 한, 이것입니다. 사용하는 컬렉션 / 스트림 특정 유틸리티 방법에 관계없이 컬렉션 내부의 개체에 대해 동일한 참조가 유지됩니다.
yuranos 2016 년

3
답이 틀렸다. 내용이 복사되지 않습니다. 오직 참조입니다.
놀라운 1

33

이것은 정말 좋은 Java 8 방법입니다.

List<String> list2 = list1.stream().collect(Collectors.toList());

물론 여기서 이점은 목록의 일부만 필터링하고 건너 뛸 수 있다는 것입니다.

예 :

//don't copy the first element 
List<String> list2 = list1.stream().skip(1).collect(Collectors.toList());

4
결과 목록이 원본 목록의 딥 카피 또는 얕은 사본입니까?
Ad Infinitum

7
얕은 사본.
kap

3
슬프게도 스레드 안전하지 않습니다. list콜렉터가 실행되는 동안 변경 되었다고 가정하면 a ConcurrentModificationException가 발생합니다.
C-Otto

@ Dan, 마지막 요소 복사를 건너 뛰는 방법?
CKM

@chandresh 마지막 요소 복사를 건너 뛰려면 다음을 사용하십시오..limit(list1.size() - 1)
Matthew Carpenter

13
originalArrayList.addAll(copyArrayofList);

addAll () 메서드를 복사에 사용할 때마다 동일한 객체에 대한 두 배열 목록 (originalArrayList 및 copyArrayofList) 참조의 내용이 목록에 추가되므로이 중 하나를 수정하면 copyArrayofList도 같은 변화를 반영하십시오.

부작용을 원하지 않으면 for 또는 while 루프를 사용하는 것처럼 originalArrayList의 각 요소를 copyArrayofList로 복사해야합니다.


2
이것은 #addAll이 얕게 복사하고 딥 복사하는 방법을 지정하기 때문에 여기에 몇 가지 진정한 답변 중 하나입니다. 자세한 내용 : stackoverflow.com/questions/715650/…
cellepo

7

나는 이와 같은 것을 시도했지만 여전히 IndexOutOfBoundsException을 얻었습니다.

ConcurrentAccessException이 발생했습니다

이것은 다른 스레드에서 복사하려고 시도하는 동안 목록을 수정하고 있음을 의미합니다. 이 문제를 해결하려면 다음 중 하나를 수행해야합니다.

  • 동시 액세스 용으로 설계된 모음을 사용하십시오.

  • 컬렉션을 적절히 잠그면 반복 할 수 있습니다 (또는이를 수행하는 메서드를 호출하도록 허용)

  • 원본 목록을 복사하지 않아도되는 거리를 찾으십시오.


4

Java 10 에서 시작 :

List<E> oldList = List.of();
List<E> newList = List.copyOf(oldList);

List.copyOf()List주어진의 요소를 포함 하는 수정 불가능한 것을 리턴합니다 Collection.

주어진 Collection은이어야하며 요소를 null포함해서는 안됩니다 null.

또한의 깊은 사본을 만들려면 여기에서List 많은 좋은 답변을 찾을 수 있습니다 .


3

null 안전 방식으로 Java 8을 사용하는 또 다른 방법이 있습니다.

List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
    .map(Collection::stream)
    .orElseGet(Stream::empty)
    .collect(Collectors.toList());

한 요소를 건너 뛰려면

List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
    .map(Collection::stream)
    .orElseGet(Stream::empty)
    .skip(1)
    .collect(Collectors.toList());

Java 9+에서는 Optional의 스트림 방법을 사용할 수 있습니다

Optional.ofNullable(wsList)
    .stream()
    .flatMap(Collection::stream)
    .collect(Collectors.toList())

1

나는 ConcurrentAccessException 과 같은 문제가 있었고 내 해결책은 다음과 같습니다.

List<SomeBean> tempList = new ArrayList<>();

for (CartItem item : prodList) {
  tempList.add(item);
}
prodList.clear();
prodList = new ArrayList<>(tempList);

따라서 한 번에 하나의 작업 만 작동하고 예외를 피합니다 ...


1

비슷한 것을 시도하고 문제를 재현 할 수있었습니다 (IndexOutOfBoundsException). 아래는 내 결과입니다.

1) Collections.copy (destList, sourceList)의 구현은 먼저 size () 메소드를 호출하여 대상 목록의 크기를 확인합니다. size () 메서드를 호출하면 항상 목록의 요소 수 (이 경우 0)가 반환되므로 생성자 ArrayList (capacity)는 백업 배열의 초기 용량 만 보장하며이 값과 관련이 없습니다. 목록의 크기. 따라서 항상 IndexOutOfBoundsException이 발생합니다.

2) 비교적 간단한 방법은 컬렉션을 인수로 취하는 생성자를 사용하는 것입니다.

List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList);  

0

다시 : indexOutOfBoundsException, 당신의 하위 목록 인수가 문제입니다; 서브리스트를 size-1에서 종료해야합니다. 0부터 시작하므로 목록의 마지막 요소는 항상 크기 -1이며 크기 위치에 요소가 없으므로 오류가 발생합니다.




-2

한 목록에서 다른 목록에 영향을 미치도록 변경하지 않으려면 이것을 시도하십시오
.

  public class MainClass {
  public static void main(String[] a) {

    List list = new ArrayList();
    list.add("A");

    List list2 = ((List) ((ArrayList) list).clone());

    System.out.println(list);
    System.out.println(list2);

    list.clear();

    System.out.println(list);
    System.out.println(list2);
  }
}

> Output:   
[A]  
[A]  
[]  
[A]

-3

subList 함수는 트릭이며 반환 된 객체는 여전히 원래 목록에 있습니다. 따라서 subList에서 작업을 수행하면 단일 스레드 또는 다중 스레드에 관계없이 코드에서 동시 예외가 발생합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.