如何在Java8中对对象列表进行分页?

如何在Java8中对对象列表进行分页?,java,list,java-8,partition,Java,List,Java 8,Partition,给定一个包含n元素和所需页面大小m的java.util.List,我想将其转换为包含n/m+n%m元素的映射。每个地图元素应包含m元素 下面是一个整数示例: List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // What is the equivalent Java 8 code to create the map below from my list? Map<I

给定一个包含
n
元素和所需页面大小
m
java.util.List
,我想将其转换为包含
n/m+n%m
元素的映射。每个地图元素应包含
m
元素

下面是一个整数示例:

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

    // What is the equivalent Java 8 code to create the map below from my list?

    Map<Integer, List<Integer>> map = new HashMap<>();
    map.put(0, Arrays.asList(1,2,3));
    map.put(1, Arrays.asList(4,5,6));
    map.put(2, Arrays.asList(7,8,9));
    map.put(3, Arrays.asList(10));
List List=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
//从我的列表中创建以下映射的等效Java 8代码是什么?
Map Map=newhashmap();
map.put(0,Arrays.asList(1,2,3));
map.put(1,Arrays.asList(4,5,6));
map.put(2,array.asList(7,8,9));
map.put(3,array.asList(10));

这是否可能,使用Java 8?

您可以使用
IntStream.iterate
toMap
收集器和
列表上的
子列表
方法相结合(感谢您的简化)


因此,与您的示例一样(一个包含10个元素的列表,页面大小为3),您将获得以下序列:

0,3,6,9,12,15,…
限制为
(10+3-1)/3=12/3=4
,这使得序列
0,3,6,9
。现在,每个值都映射到其相应的子列表:

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

如果您确实需要
映射
,可以将值映射器函数替换为

import static java.util.stream.Collectors.joining;

...

i -> list.subList(i, min(i + pageSize, list.size()))
         .stream()
         .map(Object::toString)
         .collect(joining(","))

它只是将逗号分隔的元素收集到一个字符串中

如注释中所述,如果列表不是一个自然的整数序列,这也适用。您必须使用生成的
IntStream
,然后按索引引用列表中的元素

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Map<Integer, String> map = IntStream
    .range(0, list.size())
    .boxed()
    .collect(groupingBy(
        i -> i / 3, //no longer i-1 because we start with 0
        mapping(i -> list.get((int) i).toString(), joining(","))
        ));

//result: {0="1,2,3", 1="4,5,6", 2="7,8,9", 3="10"}
List List=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Map=IntStream
.range(0,list.size())
.boxed()
.收集(分组)(
i->i/3,//不再是i-1,因为我们从0开始
映射(i->list.get((int)i.toString(),连接(“,”)
));
//结果:{0=“1,2,3”,1=“4,5,6”,2=“7,8,9”,3=“10”}
我们从表示列表索引的
IntStream
开始

groupingBy
通过一些分类器对元素进行分组。在您的情况下,它将每页x个元素分组


mapping
将映射函数应用于元素,然后收集它们。映射是必需的,因为
连接
只接受
字符序列
<代码>连接
本身通过使用任意分隔符连接元素。

使用番石榴的简单解决方案:

List partition=Lists.partition(List,3);//得到(i));

到目前为止,您尝试了什么?请阅读。所以,我查看了Collectors::partitioningBy,但这会在给定谓词的情况下拆分列表。我问这个问题是因为我不知道在Java 8中从何处开始来实现这一点。@user3030447您确定要
映射而不是
映射吗?在演示阶段,你总是可以将列表转换为一个逗号字符串…看…@Alexis C:这不是一个完全相同的字符串,因为集合成了一个
Map
,但是链接问题将有助于未来的搜索者。这是第一个版本的输出{0=[1,2,3],1=[4,5,6],2=[7,8,9],3=[10]}。亚历克西斯,你真是个好孩子,谢谢你给我看。我会理解代码并提高我的知识:)祝你一切顺利best@user3030447我在相应的示例中添加了它的行为。很好的解决方案。您可以将限制简化为:
.limit((list.size()+pageSize-1)/pageSize)
,因为这两个值都是正值(请参阅)。值映射方法还可以简化为
i->list.subList(i,Math.min(i+pageSize,list.size())
您可以并行运行它,但使用IntStream.iterate()启动管道将破坏您获得的任何并行性(这是一个基本上连续的源代码)。使用IntStream.range要好得多,它与您的迭代做相同的事情,并且分割得更好。那么你就不需要使用limit,因为limit基本上依赖于遭遇顺序,所以它的并行性也很差。如果你在列表中有一个自然的序列,那么它可以很好地工作,但是假设列表[1,-1,5,2]和页面大小为2,你就不会得到想要的结果。@AlexisC。没错,但是在这种情况下,您可以使用生成的
IntStream
,并按索引引用原始列表。但算法不会改变。@zeroflagL您可以删除
.limit(list.size())
,因为
range
已经生成了一个有限流:-)。另外,如果基础列表是
LinkedList
get
将降低整体性能(尽管我不确定这是否是一个大问题)。@AlexisC。当然我以前用过
iterate
。谢谢。@zeroflagL与其编辑您的答案来指出第一部分已损坏,不如删除第一部分并向我们展示您的最佳解决方案。
import static java.util.stream.Collectors.joining;

...

i -> list.subList(i, min(i + pageSize, list.size()))
         .stream()
         .map(Object::toString)
         .collect(joining(","))
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Map<Integer, String> map = IntStream
    .range(0, list.size())
    .boxed()
    .collect(groupingBy(
        i -> i / 3, //no longer i-1 because we start with 0
        mapping(i -> list.get((int) i).toString(), joining(","))
        ));

//result: {0="1,2,3", 1="4,5,6", 2="7,8,9", 3="10"}
    List<List<Integer>> partition = Lists.partition(list, 3); //<- here
    Map map = IntStream.range(0, partition.size()).boxed().collect(Collectors.toMap(
                    Function.identity(),
                    i -> partition.get(i)));