【问题标题】:How to iterate over every n elements with java?如何用java迭代每n个元素?
【发布时间】:2017-01-02 07:33:13
【问题描述】:

我有一个名为计算的方法,它需要很长时间才能完成。所以我决定将我的信息列表对象部分发送到这个方法。如何遍历每 n 个元素?

public static void main(String [] args){
    Map<String, Long> info....;  //my info Map

    //I want to call method like 
    for(int i = 0; i<info.size(); i+=5)
       calculate(info.submap(i,i+5)); 
}


public static boolean calculate(Map<String, Long> info){
    //Some calculations

}

【问题讨论】:

  • 您只是添加和删除堆栈帧info.size()/5 次。
  • 我只想发送 5 到 5 个信息对象来计算方法。我不明白你的意思。
  • 在java8中可以使用并行流
  • @hellzone:我的意思是,通过这种方式发送部分数据,您不会在时间性能方面获得任何收益。
  • @Azodious 计算方法将此列表发送到 Web 服务,但此 Web 服务存在问题。当我发送 100 条信息时,它会在 1 小时后回复,而当我发送 5 条信息时,它会在 1 秒内回复。

标签: java java-8


【解决方案1】:

您可以使用以下代码

class SomeClass {

    private final int BUFFER_SIZE = 5;    

    public static void main(String[] args) {
        Map<String, Long> info = new HashMap<>();

        LongStream.range(0, 30).boxed().forEach(i -> info.put("key" + i, i)); // for test

        IntStream.range(0, info.size() / BUFFER_SIZE)
                .boxed()
                .parallel()
                .map(i -> Arrays.copyOfRange(info.keySet().toArray(), BUFFER_SIZE * i, BUFFER_SIZE * (i + 1)))
                .map(Arrays::asList)
                .map(keys -> info.entrySet().stream()
                        .filter(x -> keys.contains(x.getKey()))
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)))
                .forEach(SomeClass::calculate);
    }

    public static boolean calculate(Map<String, Long> info) {
        System.out.println("calculation for " + info.toString());
        return true;
    }
}

【讨论】:

    【解决方案2】:

    听起来您想要做的是为您的Map&lt;String, Long&gt; info 实例表示的数据实现一种batch processing。然后,您可以为这些批次创建一个generator 作为Stream:这在某种程度上与Stream.flatMap(...) 系列方法相反,但具有讽刺意味的是,there doesn't seem to be any idiomatic functional way of doing this 因此您可能必须自己创建批次以命令的方式——例如:

    private static <T> Stream<Stream<T>> createBatchStreams(final Iterator<T> iter, final int maxBatchSize) {
        final Stream.Builder<Stream<T>> resultBuilder = Stream.builder();
        {
            // NOTE: This logic could also be encapsulated in a Collector class
            // in order to make it less imperative style
            Stream.Builder<T> currentBatchBuilder = Stream.builder();
            int currentBatchSize = 0;
    
            while (iter.hasNext()) {
                final T next = iter.next();
                if (currentBatchSize == maxBatchSize) {
                    resultBuilder.add(currentBatchBuilder.build());
                    // Start building a new batch
                    currentBatchBuilder = Stream.builder();
                    currentBatchSize = 0;
                }
                currentBatchBuilder.add(next);
                currentBatchSize++;
            }
            // Check if there is a non-empty Stream to add (e.g. if there was a
            // final batch which was smaller than the others)
            if (currentBatchSize > 0) {
                resultBuilder.add(currentBatchBuilder.build());
            }
        }
        return resultBuilder.build();
    }
    

    使用此方法,您可以创建一批地图数据的生成器,然后将其提供给您的 calculate(...) 函数(尽管签名略有不同):

    public static void main(final String[] args) {
        final Map<String, Long> info = LongStream.range(0, 10).boxed()
                .collect(Collectors.toMap(value -> "key" + value, Function.identity())); // Test data
        final Stream<Stream<Entry<String, Long>>> batches = createBatchStreams(info.entrySet().iterator(), 5);
        batches.forEach(batch -> {
            calculate(batch);
            // Do some other stuff after processing each batch
        });
    }
    
    private static boolean calculate(final Stream<Entry<String, Long>> info) {
        // Some calculations
    }
    

    【讨论】:

      猜你喜欢
      • 2023-01-11
      • 1970-01-01
      • 2012-09-25
      • 2021-12-14
      • 2015-02-24
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      相关资源
      最近更新 更多