2009-11-04 31 views
196

Nếu tôi có một bộ sưu tập, chẳng hạn như Collection<String> strs, làm cách nào để có được mục đầu tiên? Tôi chỉ có thể gọi số Iterator, lấy số next() đầu tiên, sau đó ném Iterator. Có cách nào lãng phí hơn để làm điều đó không?Java: Nhận mặt hàng đầu tiên từ bộ sưu tập

+1

Tất nhiên có thể có cách tốt hơn để truy cập phần tử đầu tiên nếu bạn biết lớp chứa triển khai ... – Rooke

+0

Tổng quát cho bất kỳ chỉ mục nào: http://stackoverflow.com/questions/1047957/best-way-to- get-value-from-collection-by-index –

+1

Có vẻ như bạn cần Queue.peek() – Johannes

Trả lời

101

Iterables.get(yourC, indexYouWant)

Bởi vì thực sự, nếu bạn đang sử dụng bộ sưu tập, bạn nên sử dụng Google Bộ sưu tập .

+6

Điều tương tự, nó chỉ kiểm tra nếu nó là một danh sách đầu tiên, và được theo chỉ mục nếu nó được. Nó cũng có một số mã để cố gắng thất bại nhanh hơn trên một Bộ sưu tập thực tế (đó là nếu chỉ mục quá lớn, nó cố gắng tìm ra điều đó mà không cần lặp lại toàn bộ điều và ném ngoại lệ vào cuối). – Yishai

+1

Thành thật mà nói, hiệu suất-khôn ngoan nó có thể hơi chậm hơn c.iterator(). Next() - nhưng mã là rõ ràng hơn và đơn giản hơn để sửa đổi. – Carl

+2

Tôi chắc chắn đồng ý nó là sạch hơn, nhưng OP là về lãng phí, nhưng tôi đoán kể từ khi câu trả lời của bạn đã được chấp nhận đó là những gì đã được mong muốn. – Yishai

36

Không có mục nào là "đầu tiên" trong một số Collection vì nó là ... cũng chỉ đơn giản là một bộ sưu tập.

Từ phương pháp doc Java Collection.iterator():

Không có bảo đảm liên quan đến trật tự trong đó các phần tử được trả về ...

Vì vậy, bạn không thể.

Nếu bạn sử dụng khác giao diện như Danh sách, bạn có thể làm như sau:

String first = strs.get(0); 

Nhưng trực tiếp từ một Bộ sưu tập này là không thể.

+9

Tôi không nghĩ 'get (int n)' được xác định cho 'Bộ sưu tập' –

+1

Bạn nói đúng, tôi bỏ lỡ điểm đó. Tôi đã cập nhật câu trả lời. Bạn không thể! (trừ khi Bộ sưu tập được thực hiện bởi một số lớp lót cho phép cung cấp bảo lãnh) – OscarRyz

+0

nhận được không có trong giao diện Bộ sưu tập –

-2

Bạn có thể làm điều này:

String strz[] = strs.toArray(String[strs.size()]); 
String theFirstOne = strz[0]; 

Các javadoc cho Bộ sưu tập mang đến cho thứ tự wrt báo trước sau của các phần tử của mảng:

Nếu bộ sưu tập này làm cho bất kỳ sự bảo đảm như những gì đặt hàng của mình các phần tử được trả về bởi trình lặp của nó, phương thức này phải trả về các phần tử theo cùng thứ tự.

+2

Điều này tạo ra một mảng Chuỗi mới, đắt hơn nhiều so với việc tạo một trình lặp. –

+0

Vâng, tôi đã nghĩ về điều đó sau khi tôi đăng bài này. Bất kể phương thức được sử dụng, thứ tự phụ thuộc vào việc triển khai bên dưới của Bộ sưu tập. "Đầu tiên" sau đó trở thành một thuật ngữ tương đối. Tuy nhiên, cách lặp lại() để làm điều đó có lẽ tốt hơn trong hầu hết các trường hợp. –

+4

-1 vì đây là * không bao giờ * tốt hơn so với trình lặp(). Next(). –

313

Hình như đó là cách tốt nhất để làm điều đó:

String first = strs.iterator().next(); 

Great câu hỏi ... Lúc đầu, nó có vẻ như một giám sát cho giao diện Collection.

Lưu ý rằng "đầu tiên" không phải lúc nào cũng trả lại thứ đầu tiên bạn đưa vào bộ sưu tập và chỉ có thể có ý nghĩa đối với các bộ sưu tập được sắp xếp. Có lẽ đó là lý do tại sao không có một cuộc gọi get(item), vì thứ tự không nhất thiết phải được duy trì.

Trong khi nó có vẻ hơi lãng phí, nó có thể không tệ như bạn nghĩ. Iterator thực sự chỉ chứa thông tin lập chỉ mục vào bộ sưu tập chứ không phải bản sao của toàn bộ bộ sưu tập. Gọi phương thức này sẽ khởi tạo đối tượng Iterator, nhưng đó thực sự là chi phí duy nhất (không giống như sao chép tất cả các phần tử).

Ví dụ: xem loại trả về theo phương pháp ArrayList<String>.iterator(), chúng tôi thấy rằng đó là ArrayList::Itr. Đây là một lớp nội bộ chỉ truy cập trực tiếp vào các phần tử của danh sách, thay vì sao chép chúng.

+9

lạ rằng đây không phải là câu trả lời được chấp nhận –

+2

Điều quan trọng cần lưu ý là "mẹo" này chỉ hoạt động khi bộ sưu tập thực sự có nội dung. Nếu nó rỗng thì trình vòng lặp có thể trả về lỗi, trong đó người ta phải kiểm tra kích thước bộ sưu tập trước. – spaceemotion

+5

Đây phải là câu trả lời đúng. Tôi không hiểu tại sao câu trả lời luôn là "sử dụng thư viện khác!" . – Kuzeko

0

Nếu bạn biết rằng bộ sưu tập là hàng đợi thì bạn có thể đưa bộ sưu tập vào hàng đợi và dễ dàng lấy.

Có một số cấu trúc bạn có thể sử dụng để nhận đơn đặt hàng, nhưng bạn sẽ cần truyền đến nó.

+0

Tôi đồng ý, nếu bạn không muốn lặp lại, không sử dụng bộ sưu tập. Sử dụng một số giao diện cụ thể khác thay thế. –

+1

Tôi tự hỏi, mặc dù ... giả sử dữ liệu cơ bản thực tế là một SortedSet, vì vậy thứ tự có ý nghĩa, nhưng bạn chỉ có một khung nhìn Collection của nó (vì một lý do không ngớ ngẩn, giả sử); nếu bạn đưa Bộ sưu tập vào một Danh sách, Hàng đợi, v.v. và thử lấy/poll/etc, có xảy ra thảm họa không? Tương tự như vậy, nếu cấu trúc cơ bản là một Danh sách, v.v .. – Carl

+0

@Cal - Tôi chưa thử, nhưng nếu bạn chọn một bộ sưu tập thành một loại rất khác so với ban đầu thì bạn sẽ gặp lỗi, nhưng, tôi chưa thử nó, vì vậy tôi có thể sai. –

3

Nghe có vẻ như Bộ sưu tập của bạn muốn trở thành Danh sách giống như, vì vậy tôi muốn đề nghị:

List<String> myList = new ArrayList<String>(); 
... 
String first = myList.get(0); 
45

Trong java 8:

Optional<String> firstElement = collection.stream().findFirst(); 

Đối với phiên bản cũ của java, có một phương pháp getFirst trong ổi Iterables:

Iterables.getFirst(iterable, defaultValue) 
+3

Giải pháp java 8 đặc biệt hữu ích vì nó xử lý trường hợp bộ sưu tập trống trơn. – SpaceTrucker

+2

Không tốt. Bạn thêm chi phí của luồng() để có được một get (0) chỉ vì bạn đang lười biếng để viết 4 dòng mã. if (! CollectionUtils.isEmpty (productList)) { \t \t trả về Optional.of (productList.get (0)); } trả lại Tùy chọn.trống(); –

+1

Giải pháp tuyệt vời và đơn giản. Cảm ơn bạn. –

0

Nó hoàn toàn phụ thuộc vào đó thực hiện bạn đã sử dụng, cho dù linkedlist ArrayList hoặc các triển khai khác của tập hợp.

nếu được đặt thì bạn có thể trực tiếp lấy phần tử đầu tiên, có thể là vòng lặp lừa qua bộ sưu tập, tạo biến giá trị 1 và nhận giá trị khi giá trị cờ là 1 sau khi ngắt vòng lặp đó.

nếu thực hiện danh sách thì việc này dễ dàng bằng cách xác định số chỉ mục.

2

Trong Java 8 bạn có một số nhiều nhà khai thác sử dụng, ví dụ hạn

 /** 
* Operator that limit the total number of items emitted through the pipeline 
* Shall print 
* [1] 
* @throws InterruptedException 
*/ 
@Test 
public void limitStream() throws InterruptedException { 
    List<Integer> list = Arrays.asList(1, 2, 3, 1, 4, 2, 3) 
           .stream() 
           .limit(1) 
           .collect(toList()); 
    System.out.println(list); 
} 
+0

@Vitalii Câu trả lời của Fedorenko http://stackoverflow.com/a/18165855/1562662 là tốt hơn. –

2

Bạn có thể làm một cuộc casting. Ví dụ, nếu tồn tại một phương pháp với định nghĩa này, và bạn biết rằng phương pháp này đang trở lại một danh sách:

Collection<String> getStrings(); 

Và sau khi gọi nó, bạn cần các yếu tố đầu tiên, bạn có thể làm điều đó như thế này:

List<String> listString = (List) getStrings(); 
String firstElement = (listString.isEmpty() ? null : listString.get(0)); 
Các vấn đề liên quan