java 分页对象合并,如何在Java 8中对对象列表进行分页?

这篇博客探讨了如何使用Java 8的Stream API将一个对象列表按指定的页面大小分页,并将其转换为Map。通过IntStream.iterate或IntStream.range结合toMap收集器和List的subList方法,可以实现列表的分页。示例展示了如何将一个包含10个元素的列表以页面大小3进行分页,并生成相应的Map。

Given a java.util.List with n elements and a desired page size m, I want to transform it to a map containing n/m+n%m elements. Each map element shall contain m elements.

Here's an example with integers:

List 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> 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));

Is this possible, using Java 8?

解决方案

You could use IntStream.iterate combined with the toMap collector and the subList method on List (thanks to Duncan for the simplifications).

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

import static java.lang.Math.min;

...

static Map> partition(List 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()))));

}

You first calculate the numbers of keys you need in the map. This is given by (list.size() + pageSize - 1) / pageSize (this will be the limit of the stream).

Then you create a Stream that creates the sequence 0, pageSize, 2* pageSize, ....

Now for each value i you grab the corresponding subList which will be our value (you need an additional check for the last subList for not getting out of bounds) for which you map the corresponding key which will be the sequence 0/pageSize, pageSize/pageSize, 2*pageSize/pageSize that you divide by pageSize to get the natural sequence 0, 1, 2, ....

The pipeline can be safely run in parallel (you may need to use the toConcurrentMap collector instead). As Brian Goetz commented (thanks for reminding me that), iterate is not worth if you want to parallelize the stream, so here's a version with 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 as with your example (a list of 10 elements with a page size of 3), you'll get the following sequence:

0, 3, 6, 9, 12, 15, ... that you limit to (10 + 3 - 1) / 3 = 12 / 3 = 4, which let the sequence 0, 3, 6, 9. Now each value is mapped to its corresponding sublist:

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

If you really want a Map you could replace the value mapper function with

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

...

i -> list.subList(i, min(i + pageSize, list.size()))

.stream()

.map(Object::toString)

.collect(joining(","))

which just collect the elements separated by a comma into a single String.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值