Как использовать subList ()


79

У меня есть страница JSF, на которой отображается список файлов журнала Glassfish. Я использую ленивую загрузку для разбивки на страницы. Я храню список имен файлов журналов на Java List.

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

dataList = dataList.subList(firstRow, lastRow);

И вот в чем проблема. Например, у меня в каталоге 35 файлов. Когда я это сделаю

dataList = dataList.subList(5, 15);

Работает нормально. Но когда я это сделаю:

dataList = dataList.subList(30, 38);

Я получаю ошибку неправильного индекса, потому что хочу получить индекс вне списка. Как я могу, например, вернуть элементы списка от 30 до 35? Я хочу, если я хочу получить индекс от 30 до 40, но если есть только 35 индексов, чтобы получить только 5.


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

18
ИлиdataList.subList(30, Math.min(38, dataList.size())
Исмаил Бадави

1
@ pb2q похоже, что вы потеряли шанс ответить.
Луигги Мендоса

Если вы посмотрите на APIdoc, вы заметите, что он бросает IndexOutOfBoundsException - endpoint index value out of range (fromIndex < 0 || toIndex > size). Так что загляните в APIdoc за такими подсказками в будущем.
zeller

Ответы:


97

Использование subList(30, 38);не удастся, потому что максимальный индекс 38 недоступен в списке, поэтому это невозможно.

Единственным способом может быть перед запросом подсписка, вы явно определяете максимальный индекс с помощью метода list size ().

например, проверьте размер, который возвращает 35, поэтому вызовите sublist(30, size());

ИЛИ ЖЕ

Скопировано из комментария pb2q

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

6
Это также не сработает, если в списке меньше 30 элементов.
Haroldo_OK

@Haroldo_OK: Да, вы правы, но предполагалось, что в списке более 30 пунктов.
kosa

3
Я предпочитаюdataList = dataList.subList(30, Math.min(38, dataList.size()));
Бенни Боттема

46

Я реализовал и протестировал это; он должен охватывать большинство баз:

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
Это должен быть принятый ответ, единственный, кто потрудился протестировать свой код.
Эд Рэндалл

2
Очень полезно, спасибо. Разбить это на метод имеет больше смысла, чем пытаться обернуть логику в тернарных операторах, это становится слишком трудно читать таким образом.
Стив

43

Чтобы получить последний элемент, просто используйте размер списка в качестве второго параметра. Так, например, если у вас есть 35 файлов, и вам нужны последние пять, вы должны:

dataList.subList(30, 35);

Гарантированный безопасный способ сделать это:

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

4
Это также не сработает, если «первый» больше, чем размер списка.
Haroldo_OK

3
@Haroldo_OK: или если lastотрицательно!
Тагир Валеев

Также не получится, еслиfirst >= last
augurar

7

Вы можете использовать потоки в Java 8. Чтобы всегда получать не более 10 записей, вы можете:

dataList.stream().skip(5).limit(10).collect(Collectors.toList());
dataList.stream().skip(30).limit(10).collect(Collectors.toList());
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.