나는 ArrayList
정확하게 복사하고 싶습니다. 누군가가 올바른 시간을 보냈다는 가정하에 가능하면 유틸리티 클래스를 사용합니다. 그래서 자연스럽게, 나는 Collections
복사 방법을 포함하는 클래스로 끝납니다 .
내가 다음을 가지고 있다고 가정하십시오.
List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
List<String> b = new ArrayList<String>(a.size());
Collections.copy(b,a);
기본적으로 b
크기가 충분하지 않다고 생각하기 때문에 실패합니다 a
. 예 b
, 크기가 0이라는 것을 알고 있지만 이제는 커야합니까? 내가 b
먼저 채워야한다면 , Collections.copy()
내 마음에 완전히 쓸모없는 기능이됩니다. 복사 기능 프로그래밍 (지금 할 것)을 제외하고는 이것을 수행하는 적절한 방법이 있습니까?
답변
부름
List<String> b = new ArrayList<String>(a);
a
within 의 얕은 사본을 만듭니다 b
. 모든 요소는 b
순서와 동일한 순서대로 존재합니다 a
.
마찬가지로 전화
// note: instantiating with a.size() gives `b` enough capacity to hold everything
List<String> b = new ArrayList<String>(a.size());
Collections.copy(b, a);
a
within 의 얕은 사본을 만듭니다 b
. 첫 번째 매개 변수에 모든 요소 를 포함 b
할 수 있는 충분한 용량 (크기가 아님) a
이없는 경우을 발생 IndexOutOfBoundsException
시킵니다. 예상 Collections.copy
대로 작동하는 데 할당이 필요하지 않으며 ,있는 경우 해당 예외가 발생합니다. 복사 된 컬렉션을 미리 할당해야하는 최적화입니다 (b
). 일반적으로 위의 그림과 같이 이상한 부작용이없는 생성자 기반 대안이 주어지면 필요한 검사로 인해 기능이 가치가 있다고 생각하지 않습니다.
딥 카피를 만들려면 List
두 메커니즘 중 하나를 통해 기본 유형에 대한 복잡한 지식이 있어야합니다. String
Java (및 해당 문제의 경우 .NET)에서 변경할 수없는 s 의 경우 딥 카피조차 필요하지 않습니다. 의 경우 MySpecialObject
, 사본을 만드는 방법을 알아야하며 이는 일반적인 작업이 아닙니다.
참고 : 원래 허용 된 답변은 Collections.copy
Google에서 최고 결과 였으며 의견에서 지적한대로 잘못 표시되었습니다.
답변
b
보유 용량이 3이지만 크기 0 사실 ArrayList
는 부분 아니다 – 버퍼 용량 일종의 구현 상세 가지고 List
있으므로 인터페이스 Collections.copy(List, List)
를 사용하지 않고있다. 특별한 경우에는 추한 것 ArrayList
입니다.
MrWiggles가 지적했듯이, 컬렉션을 취하는 ArrayList 생성자를 사용하는 것이 제공된 예제의 방법입니다.
더 복잡한 시나리오 (실제 코드를 포함 할 수 있음)의 경우 구아바 내의 모음이 유용 할 수 있습니다 .
답변
그냥 해:
List a = new ArrayList();
a.add("a");
a.add("b");
a.add("c");
List b = new ArrayList(a);
ArrayList에는 다른 Collection을 받아 요소를 복사하는 생성자가 있습니다.
답변
Stephen Katulka의 답변 (허용 된 답변)이 잘못되었습니다 (두 번째 부분). 그것은 Collections.copy(b, a);
딥 카피 를 수행 한다고 설명 하지만 그렇지 않습니다. 둘, new ArrayList(a);
그리고 Collections.copy(b, a);
단지 얕은 사본을한다. 차이점은 생성자가 새 메모리를 할당 copy(...)
하지만 그렇지 않은 경우 성능 이점이 있으므로 배열을 재사용 할 수있는 경우에 적합하다는 것입니다.
Java 표준 API는 딥 카피 사용을 권장하지 않습니다. 새로운 코더가 정기적으로 이것을 사용하면 좋지 않을 수 있습니다 clone()
. 이는 기본적으로 공개되지 않는 이유 중 하나 일 수도 있습니다 .
소스 코드는 Collections.copy(...)
552 행에서 확인할 수 있습니다.
http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Core/Collections-Jar-Zip-Logging-regex/java/util/ Collections.java.htm
딥 카피가 필요한 경우 각 객체에서 for 루프와 clone ()을 사용하여 항목을 수동으로 반복해야합니다.
답변
List를 복사하는 가장 간단한 방법은 새 목록의 생성자에게 전달하는 것입니다.
List<String> b = new ArrayList<>(a);
b
얕은 사본이 될 것입니다 a
Collections.copy(List,List)
(나는 전에 본 적이 없다) 의 출처를 보면 인덱스로 요소 색인을 처리하는 것으로 보입니다. List.set(int,E)
따라서 요소 0을 사용 하면 대상 목록 등의 요소 0을 덮어 씁니다. 인정해야 할 javadoc에서 특별히 명확하지 않습니다.
List<String> a = new ArrayList<>(a);
a.add("foo");
b.add("bar");
List<String> b = new ArrayList<>(a); // shallow copy 'a'
// the following will all hold
assert a.get(0) == b.get(0);
assert a.get(1) == b.get(1);
assert a.equals(b);
assert a != b; // 'a' is not the same object as 'b'
답변
List b = new ArrayList(a.size())
크기를 설정하지 않습니다. 초기 용량을 설정합니다 (크기를 조정하기 전에 몇 개의 요소를 넣을 수 있는지). 이 경우 더 간단한 복사 방법은 다음과 같습니다.
List b = new ArrayList(a);
답변
Hoijui가 언급했듯이. Stephen Katulka가 선택한 답변에 Collections.copy에 대한 의견이 잘못되었습니다. 저자는 아마도 첫 번째 코드 행이 원하는 사본을 작성했기 때문에 승인했을 것입니다. Collections.copy에 대한 추가 호출은 다시 복사됩니다. (복사 결과 두 번 발생 함).
그것을 증명하는 코드는 다음과 같습니다.
public static void main(String[] args) {
List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
List<String> b = new ArrayList<String>(a);
System.out.println("There should be no output after this line.");
// Note, b is already a shallow copy of a;
for (int i = 0; i < a.size(); i++) {
if (a.get(i) != b.get(i)) {
System.out.println("Oops, this was a deep copy."); // Note this is never called.
}
}
// Now use Collections.copy and note that b is still just a shallow copy of a
Collections.copy(b, a);
for (int i = 0; i < a.size(); i++) {
if (a.get(i) != b.get(i)) {
System.out.println("Oops, i was wrong this was a deep copy"); // Note this is never called.
}
}
// Now do a deep copy - requires you to explicitly copy each element
for (int i = 0; i < a.size(); i++) {
b.set(i, new String(a.get(i)));
}
// Now see that the elements are different in each
for (int i = 0; i < a.size(); i++) {
if (a.get(i) == b.get(i)) {
System.out.println("oops, i was wrong, a shallow copy was done."); // note this is never called.
}
}
}