Как использовать 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.

user1285928
источник
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);
}
Haroldo_OK
источник
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());
Стефан Хаберль
источник