2010-02-22 56 views
18

Tôi đang tìm kiếm triển khai nhanh queue trong Java. Tôi thấy rằng LinkedList triển khai giao diện Queue, nhưng nó sẽ chỉ nhanh như một quyền LinkedList? Có cách nào để có hàng đợi nhanh hơn, đặc biệt là đối với add (tôi chỉ cần poll, add và kiểm tra empty). Xuống dòng Tôi cũng có thể cần PriorityQueue nhưng chưa.Hàng đợi nhanh trong Java

+0

bạn đã xác minh rằng LinkedList sẽ không đủ nhanh chưa? Thêm phải nhanh trong danh sách được liên kết ... –

+0

'LinkedList' không đủ nhanh? Bạn đã cố gắng viết của riêng bạn để có được xung quanh bottelnecks 'LinkedList' (bất cứ điều gì họ có thể)? – FrustratedWithFormsDesigner

Trả lời

28

Tôi thấy rằng LinkedList thực hiện giao diện Hàng đợi, nhưng nó sẽ chỉ nhanh bằng quyền LinkedList?

Nhãn cầu mã nguồn, LinkedList là O (1) cho các hoạt động Queue.add, Queue.poll và Queue.peek.

Tôi hy vọng điều đó đủ nhanh.

+0

Tôi đã nghĩ LinkedList thêm sẽ là 'O (n)' vì một lý do nào đó. – Eqbal

+9

Đó sẽ là một thành tích cực kỳ ngu ngốc cho cấu trúc dữ liệu danh sách được liên kết. –

+2

Danh sách được liên kết thường là O (n) để tìm kiếm, nhưng nếu bạn đang sử dụng nó như một hàng đợi, nó sẽ không bao giờ xuất hiện. –

25

Nếu có nhiều chuỗi sẽ truy cập vào hàng đợi thì hãy cân nhắc sử dụng ArrayBlockingQueue. Nếu không, hãy xem ArrayDeque. Từ ArrayDeque API:

Lớp này có khả năng là nhanh hơn so với stack khi được sử dụng như một chồng, và nhanh hơn hơn LinkedList khi được sử dụng như một hàng đợi.

Cụ thể một thực hiện hàng đợi mảng dựa trên làm giảm sự cần thiết phải thay đổi kích thước các mảng tiềm ẩn nếu các mảng hiện có đủ năng lực, do đó làm cho bổ sung vào hàng đợi thường nhanh hơn so với LinkedList. Lưu ý rằng ArrayBlockingQueue là một triển khai bị ràng buộc trong khi ArrayDeque sẽ thay đổi kích thước theo yêu cầu.

Mặt trái là LinkedList thường sẽ cung cấp một đại diện nhỏ gọn hơn nhiều, đặc biệt trong trường hợp hàng đợi của bạn tăng lên và co lại theo số lượng lớn. Ví dụ: nếu bạn đã thêm 10.000.000 phần tử vào một số ArrayDeque và sau đó xóa 9,999,999 phần tử, mảng cơ bản sẽ vẫn có độ dài 10.000.000 trong khi một LinkedList sẽ không gặp phải vấn đề này.

Thực tế, đối với quyền truy cập một luồng vào hàng đợi không bị chặn, tôi có xu hướng ưu tiên LinkedList. Tôi tưởng tượng sự khác biệt hiệu suất là rất cẩu thả, bạn sẽ không nhận thấy sự khác biệt anyway.

+2

LinkedBlockingQueue thực sự nhanh hơn ArrayBlockingQueue. Vì vậy, nếu bạn đang sử dụng hàng đợi đồng thời đang chặn sử dụng hàng đợi đó. Khác sử dụng ConcurrentLinkedQueue nhanh hơn cả hai. –

+0

@JohnVint, bạn có một số nguồn mà ArrayBlockingQueue chậm hơn LinkedBlockingQueue không? Không nên ArrayBlockingQueue là nhanh hơn kể từ khi mảng sao lưu không bao giờ thay đổi kích cỡ trong suốt toàn bộ đời của đối tượng? – Pacerier

+0

@Adamski, không phải ArrayDeque tự động thu nhỏ kích thước của nó tại điểm bị xóa khi 'current_element_amt <0.5 * capacity'? – Pacerier

6

Nếu hiệu suất của danh sách được liên kết thực sự là vấn đề, thay thế sẽ là triển khai "hàng đợi hình tròn" trong một mảng, tức là hàng đợi nơi bắt đầu và điểm kết thúc khi mục nhập được thêm và xóa. Tôi có thể cung cấp thêm chi tiết nếu bạn quan tâm. Khi tôi đang sử dụng các ngôn ngữ không có thư viện sưu tập, đây là cách tôi luôn triển khai hàng đợi bởi vì nó dễ viết hơn một danh sách liên kết và nó nhanh hơn. Nhưng với các bộ sưu tập tích hợp, nỗ lực viết và gỡ lỗi bộ sưu tập của riêng tôi cho một trường hợp đặc biệt không đáng lo ngại 99% thời gian: Khi nó đã được viết, thực tế là tôi có thể viết nó theo cách khác nhanh hơn tôi có thể viết lại nó theo cách Java làm là một thực tế không liên quan. Và bất kỳ lợi ích hiệu suất nào cũng có thể quá nhỏ để có thể gây ra rắc rối. Tôi phụ loại hiện có bộ sưu tập để có được hành vi đặc biệt tôi cần bây giờ và sau đó, nhưng tôi khó ép để nghĩ về thời gian qua mà tôi đã viết một từ đầu.

+2

Upvoting vì đây là một lựa chọn tốt cho câu trả lời được lựa chọn nếu tốc độ hàng đợi được lược tả là một nút cổ chai hiệu suất. –

+1

Những gì bạn mô tả đã được thêm vào trong Java 6 và được gọi là java.util.ArrayDeque. –

3

Bạn có thể muốn xem http://java.dzone.com/articles/gaplist-%E2%80%93-lightning-fast-list giới thiệu GapList. Việc triển khai danh sách mới này kết hợp các điểm mạnh của cả hai ArrayListLinkedList.

Do đó, thực hiện giao diện Deque, nhưng cũng có thể được đặt trước như đã đề cập ở trên ArrayDeque. Ngoài ra, bạn cũng có được tất cả các khả năng của giao diện List miễn phí.

1

Bắt đầu với việc thực thi Hàng đợi xoay thực sự đơn giản với thái độ "C/C++ như" và kích thước cố định.

class SimpleQueue<E> 
{ 

int index = 0; 
int head = 0; 
int size = 100; 
int counter = 0; 
E[] data ; 


@SuppressWarnings("unchecked") 
SimpleQueue() 
{ 
    data = (E[]) new Object[size]; 
} 

public void add(E e) 
{ 
    data[index]=e; 
    index=(index+1)%size; 
    counter++; 
} 

public E poll() 
{ 
    E value = data[head]; 
    head=(head+1)%size; 
    counter--; 
    return value; 
} 

public boolean empty() 
{ return counter==0; } 

//Test 
public static void main(String[] args) 
{ 
    SimpleQueue<Integer> s = new SimpleQueue<Integer>(); 

    System.out.println(s.empty()); 

    for(int i=0; i< 10; i++) 
     s.add(i); 

    System.out.println(s.empty()); 

    for(int i=0; i<10; i++) 
     System.out.print(s.poll()+","); 

    System.out.println("\n"+s.empty()); 

} 
} 

Sau đó cải thiện.

+0

'ArrayDeque' là hàng đợi xoay. Tại sao tái tạo lại bánh xe khi nó nằm trong thư viện Java SE 6? – ThePyroEagle

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