How to subdivide a list into multiple lists while processing in Java stream? [duplicate]

问题: This question already has an answer here: Is there a common Java utility to break a list into batches? 8 answers Split list into multiple lists with fi...

问题:

I have the following API call

cloudwatchClient.deleteInsightRules(
    new DeleteInsightRulesRequest().withRuleNames(existingRuleNames));

which fails because

 [exec] Exception in thread "main" com.amazonaws.services.cloudwatch.model.MissingRequiredParameterException: BATCH_REQUEST_TOO_LARGE: Batch size cannot exceed 20 items. (Service: AmazonCloudWatch; Status Code: 400; Error Code: MissingRequiredParameterException; Request ID: 0f820dc2-38b8-11e9-8465-3718764429f1)

Now I understand that I have to make multiple calls to deleteInsight rules for cloudwatch in chunks of 20.

So conceptually I am looking for

existingRuleNames
   .stream().
   .chunkIntoSizeOf(20)          // This is an imaginary method, i need to convert it into something concrete
   .foreach(chunk -> cloudwatchClient.deleteInsightRules(
        new DeleteInsightRulesRequest().withRuleNames(chunk));

Now I cant find anything in the java 8 streams api that allows me to divide and process my lists into chunks. Kind of like the scala grouped functionality Split list into multiple lists with fixed number of elements.

Can anyone help me out with this? Thanks. I can of course use an imperative style and use sublists, but I prefer to avoid that if I can.


回答1:

In the forEach below you can do whatever you want to do with the chunk:

//my list of 30 strings that needs to be processed (existingRuleNames in your case):
List<String> list = IntStream.range(0, 30).mapToObj(String::valueOf).collect(Collectors.toList());

AtomicInteger prev = new AtomicInteger(0);
IntStream.range(1, (int) (20 * (Math.ceil(Math.abs(list.size() / 20.0)))))
        .filter(i -> i % 20 == 0 || i == list.size())
        .forEach(i -> {
            List<String> chunk = list.subList(prev.get(), i);
            System.out.println("Processing " + chunk);
            prev.set(i);
        });

Output:

Processing [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
Processing [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]

So your code should look something like:

List<String> existingRuleNames = ...;

AtomicInteger prev = new AtomicInteger(0);
IntStream.range(1, (int) (20 * (Math.ceil(Math.abs(existingRuleNames.size() / 20.0)))))
        .filter(i -> i % 20 == 0 || i == existingRuleNames.size())
        .forEach(i -> {
            List<String> chunk = existingRuleNames.subList(prev.get(), i);
            cloudwatchClient.deleteInsightRules(
                    new DeleteInsightRulesRequest().withRuleNames(chunk));
            prev.set(i);
        });
  • 发表于 2019-02-26 14:52
  • 阅读 ( 216 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除