2015-01-14 13 views

Trả lời

3

Biểu mẫu đầu tiên có thể sẽ phải chịu một số hình phạt về hiệu suất, vì việc đánh giá nó sẽ yêu cầu, trước iflt, một aload, arraylengthiload; trong khi thứ hai chỉ có hai số iload s.

@ajp đúng đề cập rằng myArray có thể thay đổi; do đó, rất cao không thể rằng trình biên dịch sẽ tối ưu hóa biểu mẫu đầu tiên thành biểu mẫu thứ hai cho bạn (trừ khi, có thể, myArrayfinal).

Tuy nhiên, JIT, khi nó đá vào, có lẽ là đủ thông minh để nếu myArray không thay đổi, nó sẽ biến biểu mẫu đầu tiên thành thứ hai.

Chỉ trong trường hợp, dù sao, hãy sử dụng biểu mẫu thứ hai (đây là những gì tôi luôn làm, nhưng đó chỉ là thói quen). Lưu ý rằng bạn luôn có thể javap tệp lớp được tạo để xem mã byte được tạo và so sánh.


Nhân tiện, Wikipedia có very handy page listing all of a JVM's bytecodes. Như bạn có thể thấy, khá nhiều người trong số họ được dành riêng cho mảng!

+0

Downvoter vui lòng giải thích. – fge

+0

'mảnglength' là hướng dẫn để tải chiều dài của mảng,' iload' là lệnh tải giá trị của biến cục bộ. Có một hướng dẫn (mặc dù được đặt tên khác nhau) để được đánh giá theo một trong hai cách. Đối với thực tế là mảng có thể thay đổi, tốt ... vì vậy có thể một biến địa phương. – Dima

+0

Và? Điều đó không biện minh cho donwvote cả. Đọc nhận xét về nhận xét trước của bạn và câu trả lời đã chỉnh sửa. – fge

4

bất myArray.length chỉ là một lĩnh vực do đó không có gì để đánh giá

mảng Java là đã dài như public final int nên nó được khởi tạo một lần và khi bạn đề cập đến nó không có thực thi mã giống như một lời gọi phương thức

Độ dài trường cuối cùng công khai, chứa số thành phần của mảng. độ dài có thể là positive or zero.

+0

Uhm, không hoàn toàn đúng. Có một lệnh bytecode để lấy chiều dài của một mảng ('mảnglength'). Vì vậy, có, có cái gì đó để đánh giá ... – fge

+0

Nó có thể là giá trị chỉ ra, tuy nhiên, biểu thức được đánh giá, có nghĩa là, có chiều dài là một phương pháp/chức năng, nó thực sự sẽ được gọi cho mỗi lần lặp. – DusteD

+0

có nhưng không phải khi bạn đề cập đến nó, chỉ khi bạn khởi tạo nó –

2

Vâng, biểu thức chấm dứt được đánh giá mỗi lần. Vì vậy, bạn phải lưu trữ độ dài một lần có thể là một sự gia tăng hiệu suất nhỏ. Nhưng quan trọng hơn, nó thay đổi logic, có thể tạo ra sự khác biệt nếu myArray được gán lại.

for (int i = 0; i < myArray.length; i++) { 
    if (something-something-something) { 
     myArray = appendToMyArray(myArray, value); // sets myArray to a new, larger array 
    } 
} 

Bây giờ, điều này tạo sự khác biệt lớn cho dù bạn lưu trữ độ dài mảng trong biến trước.

Bạn sẽ không thường thấy mã như thế này với một mảng. Nhưng với một bộ sưu tập arrayList hoặc bộ sưu tập khác có kích thước có thể tăng (hoặc giảm) trong phần thân của vòng lặp, nó tạo ra sự khác biệt lớn lớn cho dù bạn tính toán kích thước một lần hoặc mỗi lần. Thành ngữ này hiển thị trong các thuật toán nơi bạn giữ "Danh sách việc cần làm".Ví dụ: đây là thuật toán một phần để tìm tất cả những người được kết nối trực tiếp hoặc gián tiếp với một số người:

ArrayList<Person> listToCheck = new ArrayList<>(KevinBacon); 
for (int i = 0; i < listToCheck.size(); i++) { 
    List<Person> connections = allConnections(listToCheck.get(i)); 
    for (Person p : connections) { 
     if ([p has not already been checked]) { 
      listToCheck.add(p); // increases listToCheck.size()!!! 
     } 
    } 
} 
+2

Phát hiện tốt về "mảng có thể thay đổi" nhưng từ của tôi, nếu bạn thấy mã như vậy, bạn nên chạy đi: p – fge

+0

nếu bạn xóa các phần tử khỏi danh sách, arraylist không giảm kích thước của nó theo như tôi biết –

+0

@KickButtowski uh, nó không, nó vi phạm hợp đồng phương thức '.size()'! – fge

0

Không thực sự. Cả hai trường hợp đều so sánh giá trị ở hai địa chỉ bộ nhớ với mỗi lần lặp lại, ngoại trừ bạn đang thực hiện gán không cần thiết khi bạn sử dụng biến số len. Sự khác biệt về hiệu suất có thể rất nhỏ và dòng đầu tiên dễ đọc hơn, vì vậy tôi sẽ sử dụng cách đầu tiên vì nó dễ đọc hơn. Nếu bạn muốn thậm chí có thể đọc được và hiệu quả hơn, hãy sử dụng vòng lặp for-each nếu bạn chỉ định thực hiện một phép lặp tuyến tính thông qua mảng của bạn. For-each vòng tìm kiếm công việc như thế này:

int [] myArray = {1,2,3}; 
for(int i:myArray){ 
System.out.print(i); 
} 

sẽ in:

1 
2 
3 

như tôi được thiết lập để mỗi phần tử của mảng. Mỗi vòng lặp có thể được sử dụng cho nhiều đối tượng và là một tính năng tốt để tìm hiểu. Đây là hướng dẫn giải thích nó.

https://www.udemy.com/blog/for-each-loop-java/

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