Nếu tôi có một bộ sưu tập, chẳng hạn như Collection<String> strs
, làm thế nào tôi có thể lấy ra món đồ đầu tiên? Tôi chỉ có thể gọi một Iterator
, lấy nó trước next()
, sau đó ném Iterator
đi. Có một cách ít lãng phí để làm điều đó?
Nếu tôi có một bộ sưu tập, chẳng hạn như Collection<String> strs
, làm thế nào tôi có thể lấy ra món đồ đầu tiên? Tôi chỉ có thể gọi một Iterator
, lấy nó trước next()
, sau đó ném Iterator
đi. Có một cách ít lãng phí để làm điều đó?
Câu trả lời:
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.
Có vẻ như đó là cách tốt nhất để làm điều đó:
String first = strs.iterator().next();
Câu hỏi tuyệt vời ... Lúc đầu, nó có vẻ như là một sự giám sát cho Collection
giao diện.
Lưu ý rằng "đầu tiên" sẽ không luôn trả lại điều đầu tiên bạn đặt trong bộ sưu tập và chỉ có thể có ý nghĩa đối với các bộ sưu tập được đặt hàng. Có lẽ đó là lý do tại sao không có get(item)
cuộc gọi, vì đơn hàng không nhất thiết phải được bảo tồn.
Mặc dù nó có vẻ hơi lãng phí, nhưng nó có thể không tệ như bạn nghĩ. Thực Iterator
sự chỉ chứa thông tin lập chỉ mục vào bộ sưu tập, thường không phải là 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 Iterator
đối tượng, 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ụ, nhìn vào kiểu được trả về bởi ArrayList<String>.iterator()
phương thức, chúng ta thấy rằng nó là ArrayList::Itr
. Đây là một lớp nội bộ chỉ truy cập trực tiếp các phần tử của danh sách, thay vì sao chép chúng.
Chỉ cần chắc chắn rằng bạn kiểm tra sự trở lại của iterator()
nó vì nó có thể trống hoặc null
tùy thuộc vào việc thực hiện.
Trong java 8:
Optional<String> firstElement = collection.stream().findFirst();
Đối với các phiên bản cũ hơn của java, có một phương thức getFirst trong Guava Iterables :
Iterables.getFirst(iterable, defaultValue)
getFirst
sẵn phương pháp. Có get
và getLast
phương pháp
Không có thứ gọi là "đầu tiên" trong một Collection
vì nó chỉ là một bộ sưu tập.
Từ phương thức Collection.iterator () của tài liệu Java :
Không có gì đảm bảo về thứ tự các phần tử được trả về ...
Vì vậy, bạn không thể.
Nếu bạn sử dụng một 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ừ Bộ sưu tập này là không thể.
get(int n)
là được định nghĩa choCollection
Có vẻ như Bộ sưu tập của bạn muốn giống như Danh sách, vì vậy tôi đề xuất:
List<String> myList = new ArrayList<String>();
...
String first = myList.get(0);
Trong Java 8, bạn có một số toán tử để sử dụng, ví dụ như giới 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);
}
Quả ổi cung cấp một onlyElement
Collector
, nhưng chỉ sử dụng nó nếu bạn mong muốn bộ sưu tập có chính xác một yếu tố.
Collection<String> stringCollection = ...;
String string = collection.stream().collect(MoreCollectors.onlyElement())
Nếu bạn không chắc có bao nhiêu yếu tố, hãy sử dụng findFirst
.
Optional<String> optionalString = collection.stream().findFirst();
Bạn có thể làm một buổi casting. Ví dụ: nếu tồn tại một phương thức với định nghĩa này và bạn biết rằng phương thức này đang trả về Danh sách:
Collection<String> getStrings();
Và sau khi gọi nó, bạn cần phần tử đầu tiên, bạn có thể làm như thế này:
List<String> listString = (List) getStrings();
String firstElement = (listString.isEmpty() ? null : listString.get(0));
Nếu bạn biết rằng bộ sưu tập là một hàng đợi thì bạn có thể chuyển bộ sưu tập thành một hàng đợi và lấy nó dễ dàng.
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 phải sử dụng nó.
Nó hoàn toàn phụ thuộc vào việc bạn đã sử dụng triển khai nào, cho dù danh sách liên kết danh sách mảng, hoặc các triển khai khác của tập hợp.
nếu nó được đặt thì bạn có thể trực tiếp lấy phần tử đầu tiên, chúng có thể là vòng lặp lừa trên bộ sưu tập, tạo biến có giá trị 1 và nhận giá trị khi giá trị cờ là 1 sau khi phá vỡ vòng lặp đó.
nếu đó là việc thực hiện danh sách thì thật dễ dàng bằng cách xác định số chỉ mục.
Cách chức năng:
public static <T> Optional<T> findFirst(List<T> result) {
return Optional.ofNullable(result)
.map(List::stream)
.flatMap(Stream::findFirst);
}
đoạn mã trên bảo tồn từ NullPulumException và IndexOutOfBoundException
List<T>
bạn không thỏa mãn điều kiện là nó sẽ hoạt động cho một Collection<String>
, nhưng tất nhiên có thể được sửa bằng cách sử dụng Collection<T>
, với sự thay đổi bổ sung : .map(Collection::stream)
.
Bạn có thể làm điều này:
String strz[] = strs.toArray(String[strs.size()]);
String theFirstOne = strz[0];
Javadoc cho Bộ sưu tập đưa ra thứ tự wrt caveat sau đây về các thành phần của mảng:
Nếu bộ sưu tập này đảm bảo bất kỳ thứ tự nào các phần tử của nó đượ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 một thứ tự.