2013-04-03 40 views
19

Đơn giản chỉ cần đặt, tôi có một phương thức với tham số ArrayList. Trong phương pháp tôi sửa đổi nội dung của ArrayList cho các mục đích chỉ liên quan đến những gì được trả về bởi phương thức. Do đó, tôi không muốn ArrayList đang được truyền như tham số bị ảnh hưởng ở tất cả (tức là không được chuyển làm tham chiếu).Chỉ truyền ArrayList làm giá trị và không tham chiếu

Mọi thứ tôi đã thử không đạt được hiệu quả mong muốn. Tôi cần phải làm gì để tôi có thể sử dụng bản sao của ArrayList trong chỉ phương thức, nhưng không có nó thay đổi biến thực sự?

+0

Bạn có thể vượt qua [ 'Collections # unmodifiable (yourList)'] (http://docs.oracle.com/javase/7/docs/api/java/util/ Collections.html # unmodifiableList (java.util.List)) để gửi một bản sao không thể sửa đổi của danh sách của bạn. –

+0

Bạn cũng có thể tạo một bản sao mới của 'ArrayList' trong phương thức đang sửa đổi nó. Mặc dù nó sẽ không ảnh hưởng đến 'ArrayList' đầu tiên, bất kỳ đối tượng nào bạn thay đổi bên trong sẽ vẫn bị thay đổi ... – MadProgrammer

+0

Bạn chỉ sửa đổi danh sách? Hoặc cũng có gì bên trong danh sách? –

Trả lời

30

Thậm chí nếu bạn có cách chuyển danh sách mảng dưới dạng bản sao chứ không phải bằng tham chiếu, nó sẽ chỉ là bản sao nông.

tôi sẽ làm một cái gì đó như:

void foo(final ArrayList list) { 

    ArrayList listCopy = new ArrayList(list); 
    // Rest of the code 

} 

Và chỉ làm việc trên các danh sách sao chép.

+0

Điều đó sẽ làm điều đó. Ban đầu tôi đã thử thiết lập danh sách nội bộ bằng tham số, nhưng điều đó không hiệu quả. Đây là giải pháp đơn giản nhất. – fvgs

+1

Thật vậy, có một khoảng thời gian chờ đợi bắt buộc trước khi có thể chấp nhận câu trả lời. – fvgs

3

Bạn có thể sử dụng phương pháp .clone hoặc CopyOnWriteArrayList để tạo bản sao, do đó không ảnh hưởng đến bản gốc.

+0

IMHO, có vẻ như quá mức, có gì sai với 'new ArrayList (list) '? – MadProgrammer

+0

@MadProgrammer Bạn có nghĩa là IMMO phải không? – Thihara

4

Bạn có thể vượt qua Collections#unmodifiableList(yourList) để gửi bản sao không thể sửa đổi danh sách của bạn. Nhân tiện, số List<Whatever> của bạn được chuyển theo giá trị từ Java always pass by value, lưu ý rằng trong phương thức foo(List<Whatever> list) bạn không thể sửa đổi giá trị list nhưng bạn có thể sửa đổi nội dung của nó.

public class MyClass { 

    List<Whatever> list = new ArrayList<Whatever>(); 

    public void bar() { 
     //filling list... 
     foo(Collections.unmodifiableList(list)); 
    } 

    public void foo(List<Whatever> list) { 
     //do what you want with list except modifying it... 
    } 
} 
1

Chỉ cần sao chép.

public ArrayList cloneArrayList(ArrayList lst){ 
    ArrayList list = new ArrayList(); 
    for (int i=0; i<lst.size(); i++){ 
     list.add(lst.get(i)); 
    } 
    return list; 
} 

Thêm gợi ý trong các ý kiến, bạn cũng có thể sử dụng

ArrayList copy = new ArrayList(original); 

và cũng

ArrayList copy = new ArrayList(); 
copy.addAll(original); 
+2

IMHO, có vẻ như quá mức, có gì sai với 'ArrayList (danh sách)' mới? – MadProgrammer

+1

Và tại sao không 'addAll'? – wchargin

+0

Tôi không biết sự tồn tại của 'new ArrayList (list) '. Lấy làm tiếc. –

13

Bạn có thể tạo một bản sao của ArrayList sử dụng bản sao constructor ArrayList của:

ArrayList copy = new ArrayList(original); 

Nhưng nếu các phần tử của danh sách cũng là các đối tượng, thì bạn phải biết rằng việc sửa đổi một thành viên của bản sao cũng sẽ sửa đổi thành viên đó trong bản gốc.

2

Hãy thử điều này trong phương pháp bạn:

void method(List<Integer> list) { 
     List copyList = new ArrayList<Integer>(); 
     copyList.addAll(list); // This will create a copy of all the emlements of your original list 
    } 
+0

Tốt hơn là hãy làm 'new ArrayList (list) ' –

1

Tôi không chắc chắn về lý do tại sao, ngay cả sau khi new ArrayList<MyObj>(old) đối tượng vẫn còn thay đổi tài liệu tham khảo ở những nơi nó đã không được phép. Vì vậy, tôi đã phải tạo một bản sao mới của các đối tượng bên trong.

tôi đã thực hiện một constructor sao chép như một trên ArrayList và đã làm như

newArray = new ArrayList<MyObj>(); 
     for (int i = 0; i < oldArray.size(); i++) { 
      newArray.add(new MyObj(ondArray.get(i))); 
     } 

Chỉ hy vọng sẽ giúp người khác nếu câu trả lời từ Avi là không đủ trong trường hợp của bạn, như tôi với một mã quá lộn xộn thậm chí có thể hiểu = P

0

Trên dòng câu trả lời hiện có nhưng sử dụng API ArrayList. Bạn có thể sử dụng phương thức subList(fromIndex, toIndex). Nó rõ ràng tạo ra một cái nhìn của danh sách chỉ với các phần tử mong muốn (tất nhiên, theo thứ tự).Ở đây, ngay cả khi bạn sửa đổi chế độ xem bằng các thao tác thêm/xóa vv, nó sẽ không thay đổi danh sách gốc. Nó giúp bạn tiết kiệm một cách rõ ràng khi tạo một bản sao.

Something như thế này:

public void recursiveMethod(List<Integer> list) { 
    if(base) 
     return; 
    recursiveCall(list); 

    // following will just create a tail list but will not actually modify the list 
    recursiveCall(list.subList(1, list.size()); 
} 
Các vấn đề liên quan