2010-05-21 18 views
9

Hiệu suất khôn ngoan, có thực sự là một sự khác biệt lớn giữa việc sử dụng:Bất kỳ sự khác biệt lớn nào giữa việc sử dụng chứa hoặc lặp qua danh sách?

  • ArrayList.contains (o) vs foreach | iterator
  • LinkedList.contains (o) vs foreach | iterator

Trong số Tất nhiên, đối với vòng lặp foreach | vòng lặp, tôi sẽ phải so sánh rõ ràng các phương thức và trả về true hoặc false cho phù hợp.

Đối tượng tôi so sánh là đối tượng trong đó equals()hashcode() đều được ghi đè chính xác.

EDIT: Bạn không cần phải biết về containsValue, xin lỗi về điều đó. Và vâng, tôi ngu ngốc ... Tôi nhận ra câu hỏi ngu ngốc của tôi là về containKey vs foreach, không bao giờ nghĩ về điều đó, tôi không biết mình đang nghĩ gì. Tôi về cơ bản muốn biết về những điều trên (chỉnh sửa những người khác).

+0

Không phải lo lắng - đó là một câu hỏi thú vị hơn theo cách này. :) – CPerkins

+1

Một lý do khác để sử dụng '.contains (o)' so với vòng lặp là, như đã thấy trong câu trả lời, cách vòng lặp của bạn phụ thuộc vào loại Bộ sưu tập trong khi chứa() hoạt động cho bất kỳ Bộ sưu tập nào. Bạn không quan tâm nếu đó là một ArrayList hoặc một LinkedList, hoặc thậm chí một Danh sách ở tất cả; tuy nhiên bạn vẫn bị mắc kẹt với sự phân đôi '.containsKey (k)' hoặc 'containsValue (v)' với Bản đồ. –

+3

Đối với 'LinkedList',' contains' nhanh hơn gấp đôi so với mỗi (xem http://stackoverflow.com/questions/2804250/linkedlist-contains-execution-speed/) – polygenelubricants

Trả lời

9

CHỈNH SỬA:

Với dạng câu hỏi mới không còn bao gồm HashMap và TreeMap, câu trả lời của tôi hoàn toàn khác. Bây giờ tôi nói không.

Tôi chắc chắn rằng những người khác đã trả lời câu hỏi này, nhưng trong cả LinkedList và ArrayList, chứa() chỉ cần gọi indexOf(), nó lặp qua bộ sưu tập.

Có thể có sự khác biệt nhỏ về hiệu suất, giữa LinkedList và ArrayList, và giữa chứa và foreach, không có bất kỳ sự khác biệt lớn nào về số lớn.

+0

HashMap và TreeMap không phải là danh sách, bên cạnh đó bạn có thể lặp qua các giá trị hoặc khóa – stacker

+0

@stacker, OP đã chỉnh sửa câu hỏi sao cho nó không còn đề cập đến HashMap hoặc TreeMap (bản gốc đã làm). Tôi sẽ chỉnh sửa câu trả lời của mình để có liên quan đến hình thức câu hỏi hiện tại khi tôi về nhà. – CPerkins

+0

xin lỗi OP thay đổi, điều này xảy ra đôi khi – stacker

3

Không có điểm chuẩn, nên chứa nhanh hơn hoặc giống nhau trong mọi trường hợp.

Đối với 1 và 2, không cần gọi các phương thức của trình lặp. Nó có thể lặp trong nội bộ. Cả hai ArrayList và LinkedList thực hiện chứa trong indexOf

  1. ArrayList - indexOf là kiểu C cho vòng lặp trên mảng sao lưu.
  2. LinkedList - indexOf dẫn danh sách được liên kết theo kiểu C cho vòng lặp.

Đối với 3 và 4, bạn phải phân biệt giữa containsKey và containsValue.

3.   HashMap, containsKey là O (1). Nó hoạt động bằng cách băm khóa, lấy thùng liên kết, sau đó đi bộ danh sách liên kết. containsValue là O (n) và hoạt động bằng cách kiểm tra mọi giá trị trong mỗi nhóm trong một vòng lặp lồng nhau.

4.   TreeMap, containsKey là O (log n). Nó kiểm tra xem nó có trong phạm vi không, sau đó tìm kiếm cây đỏ-đen. containsValue, là O (n), sử dụng đi bộ theo trật tự của cây.

+0

Điều gì làm cho nó nhanh hơn? Tôi đã cố gắng xem mã để xem cách chứa() đã được thực hiện nhưng tùy chọn "hướng đến nguồn" của Netbeans chỉ cho tôi thấy giao diện chứ không phải triển khai thực tế ... Tôi mặc dù chứa() sẽ hoạt động giống như một vòng lặp và gọi bằng nhưng tôi đã quyết định hỏi ... –

+0

Nó không phải khởi tạo một phiên bản Iterator, vì nó đã có quyền truy cập vào các giá trị bên trong. Và vâng, đó chính xác là cách nó hoạt động (xem câu trả lời của tôi). (Vâng, thực sự cho ArrayList bạn có thể sử dụng một truy cập int, và l.get (i) mà chỉ nhận được giá trị tại chỉ số i từ mảng, do đó, không có nhiều chi phí nếu bạn làm điều đó như thế). –

0

Tôi nghĩ việc sử dụng chứa có hiệu quả hơn vì thường việc triển khai thư viện hiệu quả hơn so với triển khai thủ công giống nhau. Kiểm tra nếu bạn có thể trong quá trình xây dựng đối tượng hoặc sau đó vượt qua một phương pháp so sánh mà bạn đã viết mà sẽ chăm sóc của bạn bằng tùy chỉnh và thực hiện hashcode.

Cảm ơn, Krishna

0

Vượt qua container với foreach/iterator luôn là O (n) thời gian. Tìm kiếm ArrayList/LinkedList cũng là O (n).

HashMap.containsKey() là thời gian O (1) amortized.

TreeMap.containsKey() là thời gian O (log n).

Đối với cả HashMap và TreeMap containsValue() là O (n), nhưng có thể có các triển khai được tối ưu hóa cho containsValue() nhanh bằng hàm containsKey().

2

ArrayList.contains không

return indexOf(o) >= 0; 

nơi

public int indexOf(Object o) { 
if (o == null) { 
    for (int i = 0; i < size; i++) 
    if (elementData[i]==null) 
     return i; 
} else { 
    for (int i = 0; i < size; i++) 
    if (o.equals(elementData[i])) 
     return i; 
} 
return -1; 
} 

Nó tương tự như đối với LinkedList, chỉ có nó sử dụng .next() để lặp qua các yếu tố, vì vậy không có nhiều sự khác biệt đó.

public int indexOf(Object o) { 
    int index = 0; 
    if (o==null) { 
     for (Entry e = header.next; e != header; e = e.next) { 
      if (e.element==null) 
       return index; 
      index++; 
     } 
    } else { 
     for (Entry e = header.next; e != header; e = e.next) { 
      if (o.equals(e.element)) 
       return index; 
      index++; 
     } 
    } 
    return -1; 
} 

HashMap.containKey sử dụng hàm băm của khóa để lấy tất cả khóa bằng băm đó (nhanh) và sau đó chỉ sử dụng trên các khóa đó, vì vậy có cải thiện ở đó; nhưng containsValue() đi qua các giá trị với một for.

TreeMap.containsKey dường như thực hiện tìm kiếm thông báo bằng cách sử dụng bộ so sánh để tìm Key nhanh hơn, vì vậy vẫn tốt hơn; nhưng chứaValue vẫn có vẻ đi qua toàn bộ ba cho đến khi nó tìm thấy một giá trị.

Nói chung tôi nghĩ bạn nên sử dụng các phương pháp, vì chúng dễ viết hơn làm vòng lặp mỗi lần :).

6

Điều này làm cho không differency từ chứa (o) gọi indexOf (o) mà chỉ đơn giản lặp như thế này:

for (int i = 0; i < size; i++) 
    if (o.equals(elementData[i])) 
     return i; 

(Kiểm tra trong ArrayList)

+0

Cũng đúng trong LinkedList. – CPerkins

+2

+1 Vâng, sự khác biệt là có() làm việc, trong khi tôi một lần trong một thời gian nhìn thấy các lập trình nhận được vòng lặp đơn giản sai (lỗi off-by-1 cổ điển ;-)). – helpermethod

+2

@Helper điểm tốt. Câu hỏi của OP là về hiệu suất, nhưng nó có giá trị nhấn mạnh giá trị của sự rõ ràng. – CPerkins

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