könnten Sie IntStream.iterate
mit dem toMap
Sammler kombiniert verwenden und die subList
Methode auf List
(dank Duncan für die Vereinfachungen).
import static java.util.stream.Collectors.toMap;
import static java.lang.Math.min;
...
static Map<Integer, List<Integer>> partition(List<Integer> list, int pageSize) {
return IntStream.iterate(0, i -> i + pageSize)
.limit((list.size() + pageSize - 1)/pageSize)
.boxed()
.collect(toMap(i -> i/pageSize,
i -> list.subList(i, min(i + pageSize, list.size()))));
}
Sie zuerst die Anzahl der Schlüssel berechnen Sie in der Karte benötigen. Dies wird durch (list.size() + pageSize - 1)/pageSize
angegeben (dies ist die Grenze des Streams). Dann erstellen Sie einen Stream, der die Sequenz 0, pageSize, 2* pageSize, ...
erstellt.
nun für jeden Wert i
Sie die entsprechenden subList
greifen, die unser Wert sein wird (Sie müssen eine zusätzliche Kontrolle für die letzte subList
für nicht außerhalb der Grenzen bekommen), für die Sie die entsprechende Taste zuordnen, die die Folge sein wird 0/pageSize, pageSize/pageSize, 2*pageSize/pageSize
dass Sie teilen durch pageSize
, um die natürliche Sequenz 0, 1, 2, ...
zu erhalten.
Die Pipeline kann sicher parallel betrieben werden (möglicherweise müssen Sie stattdessen den Kollektor toConcurrentMap
verwenden). Als Brian Goetz kommentierte (danke, dass er mich daran erinnert hat), iterate
ist es nicht wert, wenn du den Stream parallelisieren willst, also hier ist eine Version mit range
.
return IntStream.range(0, (list.size() + pageSize - 1)/pageSize)
.boxed()
.collect(toMap(i -> i ,
i -> list.subList(i * pageSize, min(pageSize * (i + 1), list.size()))));
So wie bei Ihrem Beispiel (eine Liste von 10 Elementen mit einer Seitengröße von 3), erhalten Sie die folgende Sequenz erhalten:
0, 3, 6, 9, 12, 15, ...
, die Sie (10 + 3 - 1)/3 = 12/3 = 4
begrenzen, die lassen die Sequenz 0, 3, 6, 9
. Nun wird jeder Wert auf seine entsprechenden sublist abgebildet:
0/pageSize = 0 -> list.subList(0, min(0 + pageSize, 10)) = list.subList(0, 3);
3/pageSize = 1 -> list.subList(3, min(3 + pageSize, 10)) = list.subList(3, 6);
6/pageSize = 2 -> list.subList(6, min(6 + pageSize, 10)) = list.subList(6, 9);
9/pageSize = 3 -> list.subList(9, min(9 + pageSize, 10)) = list.subList(6, 10);
^
|
this is the edge-case for the last sublist to
not be out of bounds
Wenn Sie wirklich wollen ein
Map<Integer, String>
Sie den Wert Mapperfunktion mit
import static java.util.stream.Collectors.joining;
...
i -> list.subList(i, min(i + pageSize, list.size()))
.stream()
.map(Object::toString)
.collect(joining(","))
ersetzen könnte, die nur die durch ein Komma getrennt Elemente sammeln in ein einzelner String.
Was Sie bisher versucht haben? Bitte lesen Sie [Wie stelle ich eine gute Frage?] (Http://stackoverflow.com/help/how-to-ask). – DavidPostill
Also habe ich in Collectors :: partitioningBy geschaut, aber das teilt eine Liste mit einem Prädikat auf. Ich habe das gefragt, weil ich nicht weiß, wo ich in Java 8 anfangen soll, um das zu erreichen. – adragomir
@ user3030447 Sind Sie sicher, dass Sie eine 'Map' und nicht eine 'Map >' wollen? Sie können die Liste während einer Präsentationsphase immer in eine commited Zeichenfolge umwandeln ... –