2016-11-24 33 views
1

有一种简单的方法来做到以流下列:分组整数表向分区

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

结果:

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

回答

1

您可以使用groupingBy进行拆分。

如果流需要。如果流需要按位置划分要由元素值

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

分裂

int[] pos = { -1 }; 
Map<Integer, List<Integer>> map = integerList.stream().peek(e -> pos[0]++).collect(Collectors.groupingBy(e -> pos[0]/split)); 
System.out.println(map); 

输出

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

第一溶液不拆分原始列表。 – user6904265

+0

是的,错过了'map' – Saravana

+0

对不起,我的朋友,但没有一个代表一个解决方案..尝试与另一个输入:'列表 integerList = Arrays.asList(10,22,23,4,25,6,27,8 ,9,10);' – user6904265

0

我建议你这种方法:它从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))) 
      ); 
} 

分组的版本(非常类似于@Saravana的第二个解决方案):

... 
AtomicInteger pos = new AtomicInteger(0); 
AtomicInteger split = new AtomicInteger(batchLength); 
Map<Integer, List<Integer>> map = integerList.stream() 
     .collect(Collectors.groupingBy(e -> Integer.valueOf(pos.getAndIncrement()/split.get()))); 
0

如果你不想发生变异的共享变量来跟踪指标,并希望保留该流可以并行化,您仍然可以通过使用替代策略来实现。

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

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

在这里我们使用了简洁-1/+ 1个符号来代替天花板的Math.ceil

一个简单幼稚的方法将是找到索引组:

list.stream().collect(groupingBy(i -> list.indexOf(i)/partitionSize)); 

但是,如果你关心性能,你想找到更好的方法来处理指标。

直观的方法可能是首先生成所有的索引位置,然后遍历它们并收集子列表。这会给你这样的事情,所有分区的List<List<Integer>>结合:

int[] indexes = IntStream.iterate(0, i -> i + partitionSize).limit(partitions+1).toArray(); 

IntStream.range(0, indexes.length - 1) 
     .mapToObj(i -> list.subList(indexes[i], Math.min(indexes[i + 1], list.size()))) 
     .collect(toList()); 

Math.min用于查找的情况下,间隔的正确结束边界,我们接近列表的末尾。

但是,您可以结合指数计算和循环如下:这个结果是List<List<Integer>>

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

或者,如果你不介意使用外部库,例如番石榴具有

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

结果:[[1,2,3],[4,5,6],[7,8,9],[10]]