2015-06-05 23 views
6

Tôi có một vòng lặp foreach trong Java (phiên bản đơn giản ở đây)Refactor foreach để cho vòng lặp

List<String> names = getNames(); 
for(String name:names) { 
    doSomething(name); 
} 

Có một cách tự động để cấu trúc lại này cho một người for loop truyền thống?

tôi biết làm thế nào để làm điều đó bằng tay

List<String> names = getNames(); 
for(int i=0; i<names.size(); i++) { 
    String name = names.get(i); 
    doSomething(name); 
} 

Như bạn thấy, có một chút gõ cần thiết trong for tuyên bố bản thân cũng như giới thiệu các biến name một lần nữa và gán cho nó giá trị names.get(i). Tổng cộng, chỉnh sửa thủ công quá dễ bị lỗi đối với tôi.

Tại sao tôi muốn thực hiện việc này? Tôi phải sửa lỗi và sửa lỗi là bắt đầu từ chỉ mục 1 thay vì chỉ mục 0 và kết thúc tại chỉ mục n-1 thay vì kết thúc (tiếc là tôi không thể khắc phục đầu vào ngay lập tức, tôi cần phải chờ cập nhật thư viện nếu điều đó được công nhận là lỗi).

Tôi đã thử gì? Tôi nhấp chuột phải vào từ khóa for và nhấp vào "Refactor", nhưng theo như tôi có thể nhận được từ các mục trình đơn ngữ cảnh, không có gì trong đó sẽ làm công việc cho tôi.

Tại sao tôi nghĩ điều này về lý thuyết có thể hoạt động? Bởi vì chức năng tương tự tồn tại trong Resharper cho Visual Studio (C#).

FYI: Tôi đang sử dụng Eclipse Luna SR 2 (4.4.2)

+1

Có thể giới thiệu một phương pháp mới thay vì 'getNames' trả về danh sách mà không đầu tiên và mục cuối cùng? –

+0

@DevBlanked: tất nhiên về mặt kỹ thuật sẽ có thể, nhưng điều đó không có nghĩa là tôi viết một vòng lặp sao chép tất cả mọi thứ ngoại trừ mục đầu tiên và mục cuối cùng? –

+0

không thực sự, bạn có thể xóa mục đầu tiên và cuối cùng cung cấp chỉ mục của họ, https://docs.oracle.com/javase/7/docs/api/java/util/List.html#remove(int). –

Trả lời

9

di chuột của các for tuyên bố, nhấn chuột phải, Quick sửa chữa (Ctrl +), chuyển đổi để lặp được lập chỉ mục.

Nên hoạt động!

+3

"Sửa nhanh", tên # * $ §! Không có gì để sửa. OMG ... –

+1

Sau đó gọi nó là hành động 'ctrl + 1'… btw, bạn không cần đánh dấu câu lệnh' for', có con trỏ bên cạnh nó là đủ. – Holger

+0

@Thomas, chính xác Eclipse cung cấp "sửa lỗi nhanh" để sửa lỗi (lỗi/cảnh báo) và "hỗ trợ nhanh" cho các sửa đổi điển hình khác. Chuyển đổi vòng lặp là "hỗ trợ nhanh". Chỉ để thuận tiện là cả hai hành động bị ràng buộc với 'ctrl-1'. –

0

Hãy cẩn thận với việc tái cấu trúc này.

Lý do là cho một danh sách liên kết truyền thống, xây dựng for vòng thứ hai của bạn là O (N * N) kể từ khi bạn phải đi qua các danh sách liên kết để đánh giá names.get(i);. Điều đó có thể trở nên đắt đỏ.

Hãy xem xét các tác động hiệu suất khi di chuyển từ for(String name:names) {. Có thể có cách tốt hơn để sửa lỗi ngay lập tức của bạn và giữ lại "Big O" hiện tại.

for(String name : names.subList(1, names.size() - 1)) {

là một cách như vậy (Thừa nhận @JB Nizet).

+0

Dù đúng về nguyên tắc, không có lập trình viên sane nào sử dụng 'LinkedList'. Chính lợi thế của chi phí chèn O O (1) 'chỉ trả tiền ở những danh sách lớn như vậy mà bất lợi của nó về mức tiêu thụ bộ nhớ của mỗi phần tử cao hơn làm cho nó không sử dụng được. – Holger

6

Trong nhật thực của tôi (Kepler RC2) nó hoạt động để chọn từ khóa for và thể sử dụng sửa chữa nhanh chóng từ menu ngữ cảnh hoặc nhấn tổ hợp phím CTRL + cho các phím tắt. Eclipse sau đó cung cấp cho tôi "Convert to indexed" cho 'loop' hoặc "Convert to Iterator-based 'cho' loop".

Screenshot of quick fix options

+0

Cảm ơn. Cũng hoạt động cho Luna 4.4.2. –

7
List<String> names = getNames(); 
names = names.subList(1, names.size() - 1); 
for(String name : names) { 
    doSomething(name); 
} 

Tất nhiên, bạn có thể đặt đó vào một phương pháp tái sử dụng nếu bạn cần phải làm điều đó nhiều lần:

public static List<String> fixList(List<String> names) { 
    return names.subList(1, names.size() - 1); 
} 

và sau đó sử dụng nó như

List<String> names = fixList(getNames()); 
for(String name : names) { 
    doSomething(name); 
} 
+1

Ok, không chính xác những gì tôi yêu cầu, nhưng chắc chắn tốt đẹp bởi vì nếu tôi nhận được bản cập nhật thư viện, tôi chỉ cần loại bỏ một dòng mã (sửa lỗi). –

+1

Điều này giải quyết vấn đề bạn sẽ có nếu bạn có câu trả lời bạn đang tìm kiếm :) Tôi sẽ thay đổi 'fixList' thành' trimList' và thêm đối số 'beginIndex' và' endIndex' làm cho hàm có thể sử dụng lại nhiều hơn. – Ian2thedv

-2

Khi sử dụng java 8 bạn có thể sử dụng luồng api

names.stream().skip(1).reverse().skip(1).reverse().foreach(
    name -> do something(name) 
); 

S omething như thế này ...

+2

Không có phương thức reverse() trên Stream. –

+0

Bên cạnh đó đây không phải là những gì người hỏi yêu cầu; không có phương thức 'reverse' trên' Stream' và 'forEach' không tôn trọng thứ tự nguồn, do đó' forEachOrdered' là cần thiết. – Holger

1

Bạn có thể sử dụng một trong hai:

names = names.subList(1, names.size()-1); 
for (String name : names) { 
    doSomething(name); 
} 

hoặc bằng tay:

for (int i = 1; i < names.size()-1; i++) { 
    String name = names.get(i); 
    doSomething(name); 
} 

Nhưng người đầu tiên tôi thích sử dụng.

0

Đừng đi lặp lại được lập chỉ mục! Điều này không hoạt động tốt với tất cả việc triển khai List.

Nó là tốt hơn để đi cho một Iterator và để cho các JIT tối ưu hóa Iterator lập tức nếu mã này là nóng.

Vì vậy, hoặc viết này:

List<String> names = getNames(); 
for (String name : names.subList(1, names.size() - 1)) { 
    doSomething(name); 
} 

Hoặc đó (một phân bổ ít hơn):

Iterator<String> it = getNames().iterator(); 
it.next(); // You seem to be sure there is more than one element in the list 
while (it.hasNext()) { 
    String name = it.next(); 
    doSomething(name); 
} 
Các vấn đề liên quan