Як використовувати 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.