【问题标题】:Java 8 split a list into chunk for processing and merge it back before returning result [duplicate]Java 8将列表拆分为块进行处理并在返回结果之前将其合并回来[重复]
【发布时间】:2020-02-24 16:44:02
【问题描述】:

我开始在 java 8 中使用流,我想做一些感觉应该是可能的,但不知何故似乎无法完成的事情。

我必须从我的服务调用外部服务,该服务最多可以处理 500 个唯一 ID 和给定时间。我的服务可以在给定时间接收任意数量的此类信息。

我正在寻找一种简短而精确的方法来将传入的 id 列表拆分为 500 的大小,调用外部服务并在返回结果之前合并它们(如果我们可以并行执行此操作,则奖励)

private List<ServiceReply> makeServiceCallByBatch(List<Long> ids,AuthToken authToken){
 //make external call and get reply
}

public List<ServiceReply> makeServiceCall(List<Long> ids,AuthToken authToken){
  private int BATCH_SIZE = 500;
  if(ids.size() > BATCH_SIZE){
      //split by batch and process each batch and merge it all
  } else{
      return makeServiceCallByBatch(ids,authToken)
  }
}    

【问题讨论】:

  • 您是否考虑过使用subList 视图并执行操作?乍一看不太确定,“全部合并” 是什么意思!您可能希望在您的服务实现中使用batchCall 以使其更干净。
  • 根据我对流的了解,可能是它的收集功能。让我们说有 1400 个 id。分3批500,500,400处理,合并所有1400的回复后再发回。
  • 那么你是不是很喜欢(0,500),(500,1000),(1000,1400)?看到那里的模式来拆分列表?为这些视图调用您的服务可能只会返回特定结果,然后您可以在开始处理之前将 addAll 初始化为空的 List&lt;ServiceReply&gt;
  • 确实如此。那里有几件事。 1)这是这样做的基本方法。 2)我认为这可能是使用流和并行化外部调用的好地方。完全披露我没有充分利用流,可能会过度设计它

标签: java java-8 java-stream


【解决方案1】:

List 有一个sublist(int fromIndex, int toIndex) 方法,它允许您在更大的List 中获取特定范围内的对象的List。您可以使用它以500 为间隔从完整的List 中提取Lists。所以像-

int index = 0;
int batchSize = 500;
while (index < ids.size()) {
    //used made up method name for doing whatever processing you need to do...
    processBatch(ids.sublist(index, Math.min(index + batchSize, ids.size())), authToken);
    index += batchSize;
}

【讨论】:

  • toIndex 参数更改为使用Math.min 以防止IndexOutOfBoundsException
【解决方案2】:

这是一种方法:

new ArrayList inputArrayList;

//Write your array to inputArrayList here

while (!inputArrayList.isEmpty()){
    ArrayList newArrayList = new ArrayList();

    for (int i = 0; i < 500 ; i++){
        newArrayList.add(inputArray.lastIndexOf());
        inputArray.remove(inputArray.lastIndexOf());
    }

    // at this point in the while loop, your array of 500 items (newArrayList) should be full. be sure to process it
    // or move it to another array now, or it will be overwritten in the next iteration of the while loop.
}

此代码仅用于显示流程。它写得很快,因此需要调整以适应您的应用程序。

【讨论】:

    【解决方案3】:

    我会选择基于 Stream API 的解决方案:

    List<ServiceReply> allReplies = 
        IntStream.iterate(0,                   // start from 0 
                          i -> i < ids.size(), // process until the last element
                          i -> i + BATCH_SIZE) // iterate by BATCH_SIZE
                 // extract the sublist from the initial one
                 .mapToObj(i -> ids.subList(i, Math.min(i + BATCH_SIZE, ids.size()))
                 // make the actual service call
                 .map(ids -> makeServiceCallByBatch(ids, authToken))
                 // flatten the results into a single stream
                 .flatMap(List::stream)
                 // collect all the replies into one single list
                 .collect(toList());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-25
      • 1970-01-01
      • 2016-08-15
      • 2020-12-07
      • 1970-01-01
      • 1970-01-01
      • 2016-01-03
      相关资源
      最近更新 更多