Cách sử dụng subList ()


79

Tôi có một trang JSF hiển thị danh sách các tệp nhật ký Glassfish. Tôi sử dụng tải lười biếng để phân trang. Tôi giữ danh sách các tên tệp nhật ký trong Java List.

private List<directoryListObj> dataList = new ArrayList<>();

dataList = dataList.subList(firstRow, lastRow);

Và đây là vấn đề. Ví dụ, tôi có 35 tệp trong thư mục. Khi tôi làm điều này

dataList = dataList.subList(5, 15);

Nó hoạt động tốt. Nhưng khi tôi làm điều này:

dataList = dataList.subList(30, 38);

Tôi gặp lỗi chỉ mục sai vì tôi muốn lấy chỉ mục bên ngoài Danh sách. Làm cách nào để tôi có thể trả về ví dụ các phần tử Danh sách từ 30 đến 35? Tôi muốn nếu tôi muốn nhận được chỉ số từ 30 đến 40 nhưng nếu chỉ có 35 chỉ số chỉ nhận được 5.


13
dataList = dataList.subList(30, 38 > dataList.size() ? dataList.size() : 38);
pb2q

18
HoặcdataList.subList(30, Math.min(38, dataList.size())
Ismail Badawi

1
@ pb2q có vẻ như bạn đã mất cơ hội có câu trả lời.
Luiggi Mendoza

Nếu bạn nhìn vào APIdoc, bạn sẽ nhận thấy rằng nó ném IndexOutOfBoundsException - endpoint index value out of range (fromIndex < 0 || toIndex > size). Vì vậy, hãy xem APIdoc để biết những gợi ý như vậy trong tương lai.
zeller

Câu trả lời:


97

Việc sử dụng subList(30, 38);sẽ không thành công vì chỉ số tối đa 38 không có sẵn trong danh sách, vì vậy không thể thực hiện được.

Cách duy nhất có thể là trước khi yêu cầu danh sách con, bạn xác định rõ ràng chỉ mục tối đa bằng cách sử dụng phương thức list size ().

ví dụ: kiểm tra kích thước, trả về 35, vì vậy hãy gọi sublist(30, size());

HOẶC LÀ

ĐÃ SAO CHÉP TỪ nhận xét pb2q

dataList = dataList.subList(30, 38 > dataList.size() ? dataList.size() : 38);

6
Điều đó cũng sẽ không thành công nếu danh sách có ít hơn 30 mục.
Haroldo_OK

@Haroldo_OK: Đúng, bạn đúng, nhưng giả định là danh sách có hơn 30 mục.
kosa

3
Tôi thích hơndataList = dataList.subList(30, Math.min(38, dataList.size()));
Benny Bottema 12/09/18

46

Tôi đã triển khai và thử nghiệm cái này; nó sẽ bao gồm hầu hết các cơ sở:

public static <T> List<T> safeSubList(List<T> list, int fromIndex, int toIndex) {
    int size = list.size();
    if (fromIndex >= size || toIndex <= 0 || fromIndex >= toIndex) {
        return Collections.emptyList();
    }

    fromIndex = Math.max(0, fromIndex);
    toIndex = Math.min(size, toIndex);

    return list.subList(fromIndex, toIndex);
}

4
Đây phải là câu trả lời được chấp nhận, người duy nhất bận tâm kiểm tra mã của họ.
Ed Randall

2
Rất hữu ích, cảm ơn. Việc chia nhỏ điều này thành một phương thức có ý nghĩa hơn việc cố gắng gói gọn logic trong các toán tử bậc ba, thật khó để đọc theo cách đó.
Steve

43

Để lấy phần tử cuối cùng, chỉ cần sử dụng kích thước của danh sách làm tham số thứ hai. Vì vậy, ví dụ: nếu bạn có 35 tệp và bạn muốn năm tệp cuối cùng, bạn sẽ làm:

dataList.subList(30, 35);

Một cách an toàn được đảm bảo để làm điều này là:

dataList.subList(Math.max(0, first), Math.min(dataList.size(), last) );

4
Điều đó cũng sẽ không thành công nếu 'đầu tiên' lớn hơn kích thước danh sách.
Haroldo_OK

3
@Haroldo_OK: hoặc nếu lastlà tiêu cực!
Tagir Valeev

Cũng sẽ thất bại nếufirst >= last
augurar

7

Bạn có thể sử dụng các luồng trong Java 8. Để luôn nhận được tối đa 10 mục nhập, bạn có thể làm:

dataList.stream().skip(5).limit(10).collect(Collectors.toList());
dataList.stream().skip(30).limit(10).collect(Collectors.toList());
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.