Cách sao chép java.util.List vào java.util.List khác


135

Tôi có một List<SomeBean>cái được điền từ Dịch vụ web. Tôi muốn sao chép / sao chép nội dung của danh sách đó vào một danh sách trống cùng loại. Một tìm kiếm Google để sao chép danh sách đề nghị tôi sử dụng Collections.copy()phương pháp. Trong tất cả các ví dụ tôi thấy, danh sách đích được cho là chứa số lượng mục chính xác để sao chép diễn ra.

Vì danh sách tôi đang sử dụng được điền thông qua một dịch vụ web và nó chứa hàng trăm đối tượng, tôi không thể sử dụng kỹ thuật trên. Hay tôi đang sử dụng sai ?? !! Dù sao, để làm cho nó hoạt động, tôi đã cố gắng làm một cái gì đó như thế này, nhưng tôi vẫn có một IndexOutOfBoundsException.

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

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

Tôi đã cố gắng sử dụng wsListCopy=wsList.subList(0, wsList.size())nhưng tôi đã nhận được một ConcurrentAccessExceptionmã sau này. Trúng và dùng thử. :)

Dù sao, câu hỏi của tôi rất đơn giản, làm thế nào tôi có thể sao chép toàn bộ nội dung của danh sách của tôi vào một Danh sách khác? Không thông qua lặp đi lặp lại, tất nhiên.


11
Bất kỳ bản sao sẽ sử dụng lặp đi lặp lại của khóa học. Bạn có thể giấu nó đi nhưng nó vẫn sẽ ở đó.
Peter Lawrey

1
Trước hết: bạn có chắc chắn cần sao chép danh sách đó không? Động lực của bạn trong việc đó là gì?
ppeterka

2
Yup, lặp đi lặp lại chỉ được ẩn dưới các lớp đó. Nhưng bình luận đã được thêm vào để ngăn chặn bất kỳ câu trả lời lặp lại. :)
Mono Jamoon

@ppeterka Tôi đang thực hiện các thao tác trong danh sách, như remove ALL (). Điều này khiến danh sách mất dữ liệu gốc. Và "dữ liệu đó" cũng được yêu cầu sau đó.
Mono Jamoon

Loại thực tế của một danh sách, được trả về là app.allInOne(template)gì? ArrayList?
Andremoniy

Câu trả lời:


235

Chỉ cần sử dụng này:

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

Lưu ý: vẫn không an toàn cho chủ đề, nếu bạn sửa đổi otherListtừ một chủ đề khác, thì bạn có thể muốn tạo một otherList(và thậm chí newList) một CopyOnWriteArrayList, chẳng hạn - hoặc sử dụng một khóa nguyên thủy, chẳng hạn như ReentrantReadWriteLock để tuần tự truy cập đọc / ghi vào bất kỳ danh sách nào truy cập đồng thời.


1
Bây giờ, tôi chỉ cảm thấy thực sự ngu ngốc :) Tôi hy vọng rằng việc xây dựng nó như thế này sẽ không ném bất kỳ ConcurrentAccessException.
Mono Jamoon


5
+1 nếu anh ta đang nhận được ConcurrencyModifcationException, anh ta có một vấn đề tương tranh mà anh ta cần khắc phục trước tiên.
Peter Lawrey

5
Tại sao câu trả lời này nhận được nhiều điểm như vậy nếu câu hỏi đề cập đến "bản sao / bản sao"? Điều này, miễn là một số câu trả lời khác không liên quan gì đến nhân bản. Các tham chiếu tương tự sẽ được lưu giữ cho các đối tượng bên trong các bộ sưu tập bất kỳ phương thức tiện ích cụ thể của bộ sưu tập / luồng nào bạn sử dụng.
yuranos

3
Câu trả lời là sai. Nội dung không được sao chép. Chỉ có tài liệu tham khảo.
Không thể tin được vào ngày

33

Đây là một cách thực sự tuyệt vời về Java 8:

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

Tất nhiên lợi thế ở đây là bạn có thể lọc và bỏ qua để chỉ sao chép một phần của danh sách.

ví dụ

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

4
danh sách kết quả là một bản sao sâu hoặc bản sao nông của danh sách gốc?
Quảng cáo Infinitum

7
Một bản sao nông.
kap

3
Điều này, thật đáng buồn, cũng không phải là chủ đề an toàn. Giả sử listđược thay đổi trong khi bộ sưu tập đang chạy, a ConcurrentModificationExceptionbị ném.
C-Otto

@Dan, Làm thế nào để bỏ qua việc sao chép phần tử cuối cùng?
CKM

@ Vendresh để bỏ qua việc sao chép phần tử cuối cùng, bạn sẽ chỉ sử dụng.limit(list1.size() - 1)
Matthew Carpenter

13
originalArrayList.addAll(copyArrayofList);

Xin lưu ý bất cứ khi nào sử dụng phương thức addAll () để sao chép, nội dung của cả hai danh sách mảng (gốcArrayList và copyArrayofList) cho cùng một đối tượng sẽ được thêm vào danh sách, vì vậy nếu bạn sửa đổi bất kỳ một trong số chúng thì copyArrayofList cũng sẽ phản ánh sự thay đổi tương tự.

Nếu bạn không muốn tác dụng phụ thì bạn cần sao chép từng phần tử từ tệp gốcArrayList sang copyArrayofList, như sử dụng vòng lặp for hoặc while.


2
Đây là một trong số ít Câu trả lời đúng ở đây, vì nó chỉ định #add ALL tạo một bản sao nông, cũng như cách sao chép sâu. Thêm chi tiết: stackoverflow.com/questions/715650/ từ
cellepo

7

Tôi đã cố gắng làm một cái gì đó như thế này, nhưng tôi vẫn nhận được IndexOutOfBoundException.

Tôi đã nhận được một concExAccessException

Điều này có nghĩa là bạn đang sửa đổi danh sách trong khi bạn đang cố sao chép nó, rất có thể trong một luồng khác. Để khắc phục điều này, bạn phải

  • sử dụng một bộ sưu tập được thiết kế để truy cập đồng thời.

  • khóa bộ sưu tập một cách thích hợp để bạn có thể lặp lại nó (hoặc cho phép bạn gọi một phương thức thực hiện điều này cho bạn)

  • tìm một nơi để tránh cần phải sao chép danh sách ban đầu.


4

Bắt đầu từ Java 10 :

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

List.copyOf()trả về một giá trị không thể thay đổi Listcó chứa các phần tử đã cho Collection.

Cái đã cho Collectionkhông được null, và nó không được chứa bất kỳ nullyếu tố nào .

Ngoài ra, nếu bạn muốn tạo một bản sao sâu của a List, bạn có thể tìm thấy nhiều câu trả lời hay ở đây .


3

Có một phương thức khác với Java 8 theo cách không an toàn.

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

Nếu bạn muốn bỏ qua một yếu tố.

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

1

Tôi đã gặp vấn đề tương tự ConcurrencyAccessException và mysolution là:

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

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

Vì vậy, nó chỉ hoạt động một hoạt động tại thời điểm đó và tránh được ...


1

Tôi đã thử một cái gì đó tương tự và có thể tái tạo vấn đề (IndexOutOfBoundException). Dưới đây là những phát hiện của tôi:

1) Trước tiên, việc triển khai Collections.copy (DestList, sourceList) kiểm tra kích thước của danh sách đích bằng cách gọi phương thức size (). Vì phương thức gọi đến phương thức size () sẽ luôn trả về số lượng phần tử trong danh sách (0 trong trường hợp này), nên hàm tạo ArrayList (dung lượng) chỉ đảm bảo công suất ban đầu của mảng sao lưu và điều này không có bất kỳ liên quan nào đến kích thước của danh sách. Do đó, chúng tôi luôn nhận được IndexOutOfBoundException.

2) Một cách tương đối đơn giản là sử dụng hàm tạo lấy một bộ sưu tập làm đối số của nó:

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

0

re : indexOutOfBoundsException, danh sách con của bạn là vấn đề; bạn cần kết thúc danh sách con ở size-1. Là không dựa trên, phần tử cuối cùng của danh sách luôn có kích thước-1, không có phần tử nào ở vị trí kích thước, do đó xảy ra lỗi.



0

Tôi không thể thấy bất kỳ câu trả lời chính xác. Nếu bạn muốn có một bản sao sâu, bạn phải lặp lại và sao chép đối tượng theo cách thủ công (bạn có thể sử dụng một hàm tạo sao chép).


Đây là một trong số ít câu trả lời đúng ở đây. Thêm chi tiết: stackoverflow.com/questions/715650/ từ
cellepo

-2

Nếu bạn không muốn thay đổi trong một danh sách để tạo hiệu ứng cho danh sách khác, hãy thử điều này. Nó hoạt động với tôi
Hy vọng điều này sẽ giúp.

  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

Hàm subList là một thủ thuật, đối tượng trả về vẫn nằm trong danh sách ban đầu. Vì vậy, nếu bạn thực hiện bất kỳ thao tác nào trong danh sách con, nó sẽ gây ra ngoại lệ đồng thời trong mã của bạn, bất kể đó là luồng đơn hay đa luồng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.