Java 将整数列表分组到分区中

Java 将整数列表分组到分区中,java,java-8,java-stream,Java,Java 8,Java Stream,是否有一种简单的方法可以在流中执行以下操作: public static void main(String[] args) { List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); System.out.print(partitioningValues(integerList, 3)); } private static Map<Integer, List<In

是否有一种简单的方法可以在流中执行以下操作:

public static void main(String[] args) {
    List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    System.out.print(partitioningValues(integerList, 3));
}

private static Map<Integer, List<Integer>> partitioningValues(List<Integer> integerList, int numberOfPartitions) {

    Map<Integer, List<Integer>> integerListMap = new HashMap<>();
    BigDecimal limit = BigDecimal.valueOf(integerList.size() / (double) numberOfPartitions);
    int limitRounded = limit.setScale(0, BigDecimal.ROUND_UP).intValue();

    for (int i = 0; i < numberOfPartitions; i++) {

        int toIndex = ((i + 1) * limitRounded) > integerList.size() ? integerList.size() : (i + 1) * limitRounded;
        integerListMap.put(i, integerList.subList(i * limitRounded, toIndex));
    }

    return integerListMap;
}
publicstaticvoidmain(字符串[]args){
List integerList=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
系统输出打印(分区值(整数列表,3));
}
私有静态映射分区值(List integerList,int numberOfPartitions){
Map integerListMap=新HashMap();
BigDecimal limit=BigDecimal.valueOf(integerList.size()/(double)numberOfPartitions);
int limitRounded=limit.setScale(0,BigDecimal.ROUND_UP).intValue();
for(int i=0;iintegerList.size()?integerList.size():(i+1)*limitRounded;
integerListMap.put(i,integerList.subList(i*limitRounded,toIndex));
}
返回整数列表图;
}
结果:

{0=[1,2,3,4],1=[5,6,7,8],2=[9,10]}


您可以使用
groupingBy
进行拆分

如果流需要按元素值拆分

int split = 4;
Map<Integer, List<Integer>> map2 = integerList.stream().collect(Collectors.groupingBy(i -> (i-1) / split));
System.out.println(map2);

我建议您使用这种方法:它从
0
迭代到
numberOfPartitions
,在每一步它都创建一个子列表
batchLength
元素(只有最后一步的元素可能少于
batchLength
元素)并在
HashMap
中收集子列表,其中键是当前步骤,值是当前步骤的子列表

public static Map<Integer, List<Integer>> partitioningValues(List<Integer> integerList, int numberOfPartitions) {
    int size = integerList.size();
    BigDecimal limit = BigDecimal.valueOf(size / (double) numberOfPartitions);
    int batchLength =  limit.setScale(0, BigDecimal.ROUND_UP).intValue();
    AtomicInteger step = new AtomicInteger();
    return IntStream.range(0, numberOfPartitions)
            .boxed()
              .collect(
                Collectors.toMap(
                   s -> step.getAndIncrement(), 
                   s -> integerList.subList(s * batchLength, Math.min((s+1)*batchLength, size)))
              );
}
publicstaticmap分区值(List integerList,int numberOfPartitions){
int size=integerList.size();
BigDecimal limit=BigDecimal.valueOf(size/(double)numberOfPartitions);
int batchLength=limit.setScale(0,BigDecimal.ROUND_UP).intValue();
AtomicInteger步骤=新的AtomicInteger();
返回IntStream.range(0,numberOfPartitions)
.boxed()
.收集(
汤姆(
s->step.getAndIncrement(),
s->integerList.subList(s*batchLength,数学最小值((s+1)*batchLength,size)))
);
}
按版本分组(非常类似于@Saravana的第二个解决方案):

。。。
AtomicInteger pos=新的AtomicInteger(0);
AtomicInteger拆分=新的AtomicInteger(batchLength);
Map Map=integerList.stream()
.collect(收集器.groupingBy(e->Integer.valueOf(pos.getAndIncrement()/split.get()));

如果您不想改变共享变量来跟踪索引,并且希望流保持可并行,您仍然可以使用替代策略来实现这一点。

分区大小是单个分区中的最大整数数。在所有代码片段中,让我们定义
partitionSize
,如下所示:

int partitionSize = (list.size() - 1) / partitions + 1;
  IntStream.rangeClosed(0, list.size() / partitionSize)
           .mapToObj(i -> list.subList(i * partitionSize, Math.min((i+1) * partitionSize, list.size())))
           .collect(toList());
这里我们使用简洁的-1/+1符号表示天花板,而不是
Math.ceil

一个简单简单的简单方法是找到要分组的索引:

list.stream().collect(groupingBy(i -> list.indexOf(i) / partitionSize));
但是如果您关心性能,那么您希望找到更好的方法来处理索引

一种直观的方法可以是首先生成所有索引位置,然后迭代它们并收集子列表。这将为您提供类似这样的内容,将所有分区合并到一个
列表中:

其中
Math.min
用于在我们接近列表末尾时找到正确的间隔结束边界

但是,您可以将索引计算和循环结合起来,如下所示:

int partitionSize = (list.size() - 1) / partitions + 1;
  IntStream.rangeClosed(0, list.size() / partitionSize)
           .mapToObj(i -> list.subList(i * partitionSize, Math.min((i+1) * partitionSize, list.size())))
           .collect(toList());
注意,结果是一个
列表
,其中每个列表索引映射到分区的子列表上

如果你真的想要一张带有0,1,2键的地图,,。。。您可以将数据收集到地图:

Map<Integer, List<List<Integer>>> result =
      IntStream.rangeClosed(0, list.size() / partitionSize)
               .mapToObj(i -> list.subList(i * partitionSize, Math.min((i + 1) * partitionSize, list.size())))
               .collect(Collectors.groupingBy(l -> l.get(0) / partitionSize));
示例。

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

int partitions = 4;
int partitionSize = (list.size() - 1) / partitions + 1; //ceil

List<List<Integer>> result = IntStream.rangeClosed(0, list.size() / partitionSize)
                                      .mapToObj(i -> list.subList(i * partitionSize, Math.min((i+1) * partitionSize, list.size())))
                                      .collect(toList());

System.out.println(result);
List List=Arrays.asList(1,2,3,4,5,6,7,8,9,10);
int=4;
int partitionSize=(list.size()-1)/partitions+1//(用熟石膏、木板等)装天花板
List result=IntStream.rangeClosed(0,List.size()/partitionSize)
.mapToObj(i->list.subList(i*partitionSize,Math.min((i+1)*partitionSize,list.size()))
.collect(toList());
系统输出打印项次(结果);
结果:[[1,2,3],[4,5,6],[7,8,9],[10]]


第一个解决方案没有拆分原始列表。是的,错过了
地图
对不起,我的朋友,但这其中没有一个代表解决方案。。尝试另一个输入:
List integerList=Arrays.asList(10,22,23,4,25,6,27,8,9,10)
{0=[10,22,23,4],1=[25,6,27,8],2=[9,10]}
在第二个解决方案中,我在回答中添加了描述,所以问题没有提到如何按值或索引拆分流,这就是为什么在第二个解决方案中添加了这两个解决方案,顺便说一句,我有一个对象数组来保存索引,但这是一个不好的做法,应该避免,它不会在并行流中工作
Map<Integer, List<List<Integer>>> result =
      IntStream.rangeClosed(0, list.size() / partitionSize)
               .mapToObj(i -> list.subList(i * partitionSize, Math.min((i + 1) * partitionSize, list.size())))
               .collect(Collectors.groupingBy(l -> l.get(0) / partitionSize));
Lists.partition(integerList, 3);
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

int partitions = 4;
int partitionSize = (list.size() - 1) / partitions + 1; //ceil

List<List<Integer>> result = IntStream.rangeClosed(0, list.size() / partitionSize)
                                      .mapToObj(i -> list.subList(i * partitionSize, Math.min((i+1) * partitionSize, list.size())))
                                      .collect(toList());

System.out.println(result);