当前位置: 首页 > 知识库问答 >
问题:

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

杜阳炎
2023-03-14

给定一个< code>java.util.List和< code>n个元素以及一个期望的页面大小< code>m,我想将它转换成一个包含< code>n/m n%m个元素的映射。每个地图元素应包含< code>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));

使用Java 8,这是可能的吗?

共有3个答案

澹台俊达
2023-03-14

如注释中所述,如果列表不是自然的整数序列,这也有效。然后,您必须使用生成的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"}

我们从表示列表索引的<code>IntStream</code>开始。

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

映射将映射函数应用于元素,然后收集它们。映射是必需的,因为联接仅接受 CharSequence。联接本身通过使用任意分隔符联接元素。

徐俊人
2023-03-14

使用Guava:com.google.common.collect.Lists#partition的简单解决方案:

    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)));
曾飞雨
2023-03-14

您可以将 IntStream.iteratetoMap 收集器和 List 上的子列表方法结合使用(感谢 Duncan 的简化)。

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()))));
}

首先计算映射中所需的键数。这是由 (list.size() pageSize - 1) / pageSize 给出的(这将是流的限制)。

然后您创建一个Stream,该Stream创建序列0、page大小、2*page大小、…

现在,对于每个值i,您获取相应的subList,这将是我们的值(您需要对最后一个subList进行额外检查以避免越界),您为其映射相应的键,这将是您除以page大小以获得自然序列0,1,2,…的序列0/page大小,page大小/page大小,2*page大小/page大小

管道可以安全地并行运行(您可能需要改用toCon

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

因此,与您的示例(包含 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(","))

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

 类似资料:
  • 问题内容: 给定一个with 元素和所需的页面大小,我想将其转换为包含元素的地图。每个地图元素应包含元素。 这是一个整数示例: 使用Java 8可以吗? 问题答案: 您可以将其与收集器和方法结合使用(感谢Duncan的简化)。 首先,您需要计算地图中所需的键数。这是通过(这是流的限制)给出的。 然后,您创建一个创建序列的Stream 。 现在,对于每个值,您将抓住对应的值,这将是我们的值(您需要对

  • 我有一个对象列表(文件夹)。该列表中的每个对象A都有一个对象B(合作伙伴)列表,对象B也有一个对象C(人员)列表。对象C包含一个属性代码,我想用它来使用Java8进行过滤。 我试过下面的代码,但它似乎不工作: 你们知道我如何使用FlatMap从

  • 我有“MainClass”类的对象列表,它包含“Question”类的对象列表,它包含Option类的对象列表。如何按“Id”对“MainClass”类列表进行排序,以及按“Id”对“Option”类列表进行排序? 假设,

  • 问题内容: 我有一个对象列表,列表很大。对象是 现在,我必须在列表中搜索对象的特定值。假设 我必须返回那些对象(我的搜索并不总是基于value3) 清单是 有效的方法是什么? 谢谢。 问题答案: 您可以尝试使用Apache Commons Collections。 有一个CollectionUtils类,允许您通过自定义谓词选择或过滤项目。 您的代码将如下所示: 更新: 在 java8中 ,使用

  • 我有一个对象列表,列表很大。对象是 现在我必须在列表中搜索一个对象的特定值。假设我必须返回这些对象(我的搜索不总是基于value3) 该列表为

  • 我有一个过程对象列表,如下所示 我的程序课就像 我想基于以下条件对对象进行排序和分组。 应根据过程名称对所有过程进行分组。 过程必须按过程日期降序排列。[日期列表中的第一个元素,即 分组在一起的相同过程应按日期降序排列。 最终结果必须是, 我能够使用比较器和旧的Java代码实现这一点。是否可以使用java8流、收集器和分组来实现相同的功能?