2009-11-30 54 views
7

Ok, do đó, tôi buộc phải lặp qua một ArrayList và loại bỏ một phần tử specefic. Tuy nhiên, tôi đang gặp một số rắc rối khi sử dụng cấu trúc For-Each. Khi tôi chạy mã sau:Đối với mỗi và con trỏ trong Java

ArrayList<String> arr = new ArrayList<String>(); 
//... fill with some values (doesn't really matter) 

for(String t : arr) 
{ 
    t = " some other value "; //hoping this would change the actual array 
} 

for(String t : arr) 
{ 
    System.out.println(t); //however, I still get the same array here 
} 

Câu hỏi của tôi, làm cách nào để tôi có thể thay đổi giá trị trong vòng lặp cho mỗi? Tôi biết tôi có thể lặp qua ArrayList bằng cách sử dụng một cấu trúc khác nhau, nhưng cái này trông rất sạch sẽ và dễ đọc, nó sẽ chỉ là tốt đẹp để có thể làm cho 't' một con trỏ.

Tất cả các nhận xét đều được đánh giá cao! Ngay cả khi bạn nói tôi chỉ nên hút nó lên và sử dụng một cấu trúc khác nhau.

+3

đây không phải là về vòng lặp foreach, đây là một sự hiểu lầm cơ bản hơn về cách thức hoạt động của java – skaffman

+2

Mặc dù ArrayList được hỗ trợ bởi một Array: ArrayList! = Array. Đừng nhầm lẫn bản thân bằng cách trộn các cụm từ (như trong nhận xét của bạn) –

+1

http://stackoverflow.com/questions/589433/understanding-for-each-loop-in-java –

Trả lời

16

Tôi nghĩ rằng phương pháp tốt nhất có thể được sử dụng một vòng lặp for.

ArrayList<String> arr = new ArrayList<String>(); 

    for (int i = 0; i < arr.size(); i++) { 

     String t = arr.get(i); 

     if (// your condition is met) { 
      arr.set(i, "your new value"); 
     } 
    } 
+0

Ứng dụng có hoạt động không? Không có ConcurrentModificationException theo cách này? –

+2

Tôi nghĩ bạn sẽ chỉ nhận được ngoại lệ đó nếu bạn thêm/xóa các mục khỏi mảng trong khi lặp –

+0

Có, chắc chắn, bạn không sử dụng trình lặp nữa, chỉ là vòng lặp bình thường. Không chú ý;) –

-5

Chuỗi không thay đổi. Nếu bạn có một loại có thể thay đổi như StringBuilder/Buffer, bạn có thể thay đổi chuỗi trong lần lặp của bạn. Bạn có tài liệu tham khảo, hãy nhớ.

+13

Điều này không liên quan gì đến 'Chuỗi' hoặc 'StringBuilder' hoặc bất biến, đây là cách tham chiếu đối tượng hoạt động trong Java. – skaffman

+3

câu trả lời này là 100% sai ... – TofuBeer

+0

Mã gán cho biến cục bộ 't', điều này sẽ không ảnh hưởng đến tham chiếu bên trong ArrayList. Để thay đổi điều đó, bạn cần gọi arr.set() theo câu trả lời của MB bên dưới. – SimonJ

1

Đối với mỗi loại không cung cấp cho bạn một con trỏ chỉ mục, vì vậy bạn không thể sử dụng nó để thay đổi giá trị bất biến.

Hoặc sử dụng cho vòng lặp với một chỉ số hoặc sử dụng một loại có thể thay đổi (như StringBuffer, không String)

0

Về cơ bản bạn muốn xóa chuỗi t khỏi danh sách arr. Chỉ cần làm một arr.remove (t) và bạn có thể được thực hiện. Nhưng bạn không thể làm điều đó trong khi lặp qua cùng một danh sách. Bạn sẽ nhận được một ngoại lệ nếu bạn cố gắng sửa đổi danh sách theo cách này.

Bạn có hai lựa chọn:

  1. bản sao danh sách của bạn, lặp qua các bản sao và loại bỏ các String 'cụ' từ danh sách ban đầu
  2. tạo một danh sách cho các ứng cử viên xóa, thêm tất cả Strings 'cụ thể' vào danh sách đó và, sau khi lặp qua danh sách ban đầu, hãy lặp lại qua thùng rác và xóa mọi thứ bạn đã thu thập ở đây khỏi danh sách gốc.

Lựa chọn 1 là easist, clone có thể được thực hiện như:

List<String> clone = new ArrayList<String>(arr); 
1

Một mảng của các đối tượng (như chuỗi) trong Java là một khối liền kề chứa một loạt lệnh của tài liệu tham khảo. Vì vậy, khi bạn có một mảng gồm 4 chuỗi, những gì bạn thực sự có là 4 tham chiếu được lưu trữ trong mảng, và 4 đối tượng chuỗi nằm ngoài mảng nhưng được tham chiếu bởi 4 phần tử của nó.

Cấu trúc cho mỗi công việc trong Java là tạo biến cục bộ và, cho mỗi lần lặp, sao chép vào biến cục bộ đó tham chiếu từ ô mảng tương ứng với lần lặp đó. Khi bạn đặt biến vòng lặp (t = " some other value"), bạn đang đặt tham chiếu đến một chuỗi mới, "some other value", vào biến cục bộ t, không phải vào mảng.

Tương phản với một số ngôn ngữ khác (như Perl) trong đó biến vòng lặp hoạt động như một bí danh cho chính phần tử mảng/danh sách.

+0

+1 để có giải thích tuyệt vời! – Hassan

0

Bạn có vẻ hiểu sai cách đối tượng/tham chiếu hoạt động trong Java, điều này khá cơ bản để sử dụng ngôn ngữ một cách hiệu quả.Tuy nhiên, mã này ở đây nên làm những gì bạn muốn (xin lỗi cho việc thiếu giải thích):

ArrayList<String> arr = new ArrayList<String>(); 
//... fill with some values (doesn't really matter) 

for(int i = 0; i < arr.size(); i++) 
{ 
    arr.set(i, " some other value "); // change the contents of the array 
} 

for(String t : arr) 
{ 
    System.out.println(t); 
} 
5

Vấn đề là bạn đang cố gắng để thay đổi vòng lặp-scoped tham khảot để cho nó trỏ đến một Ví dụ String mới. Điều này sẽ không hoạt động. Nó không tham chiếu mục nhập thực sự trong danh sách mảng. Bạn cần thay đổi giá trị thực tế của tham chiếu. Nếu String là có thể thay đổi và cung cấp một phương pháp set() do tưởng tượng cho điều đó, bạn có thể về mặt lý thuyết làm

for (String t : arr) { 
    t.set("some other value"); 
} 

hoặc lâu hơn, nhưng điều đó là không thể vì nó là không thay đổi. Tốt hơn có được một tay cầm của entrypoint trong mảng bản thân bằng cách sử dụng bình thường for loop:

for (int i = 0; i < arr.size(); i++) { 
    arr.set(i, "some other value"); 
} 

Nếu bạn nhấn mạnh trong việc sử dụng tăng cường for vòng, sau đó bạn cần phải thay thế String bởi StringBuilder, đó là có thể thay đổi:

for (StringBuilder t : arr) { 
    t.delete(0, t.length()).append("some other value"); 
} 

Hãy nhớ rằng, Java là giá trị theo từng giá trị, chứ không phải thông qua tham chiếu.

+0

Thậm chí tệ hơn - câu đầu tiên của ông cho chúng ta biết rằng ông muốn loại bỏ một cái gì đó (có ý nghĩa, dường như là sự phân công thực sự cho nhóm example.buab-user;)) nhưng mã của ông cho thấy một sự thay thế ... điều này sẽ là một đêm loooooong :) –

+0

Wtf, anh ấy muốn ** xóa ** nó. Ở đó bạn cần có Iterator thánh cho. – BalusC

1

Mã của bạn được viết lại bởi trình biên dịch như một cái gì đó như thế này:

ArrayList<String> arr = new ArrayList<String>(); 
//... fill with some values (doesn't really matter) 

for (final Iterator <String> i = arr.iterator(); i.hasNext();) { 
    String t; 

    t = i.next(); 
    t = " some other value "; // just changes where t is pointing 
} 

Để làm những gì bạn muốn, bạn sẽ phải viết các vòng lặp for như thế này:

for (final ListIterator<String> i = arr.iterator(); i.hasNext();) { 
    final String t; 

    t = i.next(); 
    i.set("some other value"); 
} 

Iterator làm không có phương thức set, chỉ ListIterator thực hiện.

0

Tôi tin rằng, điều này không liên quan đến bất biến hoặc có thể thay đổi.

t = " some other value "; //hoping this would change the actual array 

t không giữ tham chiếu đến đối tượng thực. Java sao chép giá trị từ arraylist và đặt giá trị đó vào t để giá trị danh sách mảng không bị ảnh hưởng.

HTH

+0

đó thực sự là nhiều hơn những gì tôi đã suy nghĩ ban đầu. Tôi đã tự hỏi liệu tôi có thể có được một tham chiếu đến đối tượng, nhưng vì nó không thay đổi, tôi đoán nó không quan trọng anyways. –

0

Điều này đã được giải đáp tốt. Vẫn còn đây là gợi ý của tôi. Vòng lặp bên trong var t chỉ hiển thị ở đó. Nó sẽ không được nhìn thấy bên ngoài vòng lặp. Bạn có thể làm t.set() nếu không phải là String.

0

Sử dụng StringBuffer thay vì chuỗi đơn giản. Bằng cách này, chuỗi bên trong có thể thay đổi.

Các vấn đề liên quan