Verwendung von subList ()

79

Ich habe eine JSF-Seite, auf der eine Liste der Glassfish-Protokolldateien angezeigt wird. Ich benutze Lazy Loading zur Paginierung. Ich behalte die Liste der Namen der Protokolldateien in Java List.

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

dataList = dataList.subList(firstRow, lastRow);

Und hier ist das Problem. Zum Beispiel habe ich 35 Dateien im Verzeichnis. Wenn ich das mache

dataList = dataList.subList(5, 15);

Es funktioniert gut. Aber wenn ich das mache:

dataList = dataList.subList(30, 38);

Ich erhalte einen falschen Index, weil ich einen Index außerhalb der Liste erhalten möchte. Wie kann ich beispielsweise Listenelemente von 30 bis 35 zurückgeben? Ich möchte, wenn ich einen Index von 30 bis 40 erhalten möchte, aber wenn es nur 35 Indizes gibt, um nur 5 zu erhalten.

user1285928
quelle
13
dataList = dataList.subList(30, 38 > dataList.size() ? dataList.size() : 38);
pb2q
18
OderdataList.subList(30, Math.min(38, dataList.size())
Ismail Badawi
1
@ pb2q sieht so aus, als hätten Sie die Chance auf eine Antwort verloren.
Luiggi Mendoza
Wenn Sie sich das APIdoc ansehen, werden Sie feststellen, dass es ausgelöst wird IndexOutOfBoundsException - endpoint index value out of range (fromIndex < 0 || toIndex > size). Schauen Sie sich also das APIdoc für solche Hinweise in der Zukunft an.
Zeller

Antworten:

96

Die Verwendung subList(30, 38);schlägt fehl, da der maximale Index 38 in der Liste nicht verfügbar ist und daher nicht möglich ist.

Nur wenn Sie nach der Unterliste fragen, können Sie den maximalen Index explizit mithilfe der list size () -Methode bestimmen.

Überprüfen Sie beispielsweise die Größe, die 35 zurückgibt. Rufen Sie also an sublist(30, size());

ODER

KOPIERT VON pb2q Kommentar

dataList = dataList.subList(30, 38 > dataList.size() ? dataList.size() : 38);
kosa
quelle
6
Das würde auch fehlschlagen, wenn die Liste weniger als 30 Elemente enthält.
Haroldo_OK
@Haroldo_OK: Ja, Sie sind korrekt, aber die Annahme, dass die Liste mehr als 30 Elemente enthält.
kosa
3
Ich bevorzugedataList = dataList.subList(30, Math.min(38, dataList.size()));
Benny Bottema
46

Ich habe diesen implementiert und getestet. es sollte die meisten Basen abdecken:

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
quelle
4
Dies sollte die akzeptierte Antwort sein, die einzige, die sich die Mühe machte, ihren Code zu testen.
Ed Randall
2
Sehr hilfreich, danke. Das Aufteilen in eine Methode ist sinnvoller als der Versuch, die Logik in ternären Operatoren zusammenzufassen. Es wird einfach zu schwierig, diese Methode zu lesen.
Steve
43

Um das letzte Element zu erhalten, verwenden Sie einfach die Größe der Liste als zweiten Parameter. Wenn Sie beispielsweise 35 Dateien haben und die letzten fünf möchten, würden Sie Folgendes tun:

dataList.subList(30, 35);

Ein garantierter sicherer Weg, dies zu tun, ist:

dataList.subList(Math.max(0, first), Math.min(dataList.size(), last) );
Joe K.
quelle
4
Das würde auch fehlschlagen, wenn 'first' größer als die Listengröße ist.
Haroldo_OK
3
@Haroldo_OK: oder wenn lastnegativ ist!
Tagir Valeev
Auch wird scheitern, wennfirst >= last
Augurar
7

Sie können Streams in Java 8 verwenden. Um immer höchstens 10 Einträge zu erhalten, können Sie Folgendes tun:

dataList.stream().skip(5).limit(10).collect(Collectors.toList());
dataList.stream().skip(30).limit(10).collect(Collectors.toList());
Stefan Haberl
quelle