【问题标题】:Merging two ArrayLists to one ArrayList parallelly?将两个 ArrayList 并行合并为一个 ArrayList?
【发布时间】:2025-11-29 12:55:01
【问题描述】:

我需要将两个 ArrayList 合并到一个 ArrayList 中,但我需要非常快地完成它,因为执行此操作的函数被调用了很多次。这是我的函数版本:

  public ArrayList<Pair<String, Integer>> mergeIdWithGrade(ArrayList<String> id, ArrayList<Integer> grades) {

    ArrayList<Pair<String, Integer>> list = new ArrayList<>();
    for(int i = 0; i< id.size(); i++)
    {
        list.add(new Pair<String,Integer>(id.get(i), grades.get(i)));
    }
    return list;
}

作为函数参数的两个 ArrayList,它们的大小相同,ArrayList&lt;String&gt; id 的索引i 处的元素对应于ArrayList&lt;Integer&gt; grades 的索引i 处的元素(它们正在配对)。 该函数的复杂度显然是 O(n),但我想知道这可以使用 parallelStreams 来完成,还是通常使用我的 CPU 的所有内核并行完成?

【问题讨论】:

  • 列表中有多少个元素?在这种情况下,除非有数百万个元素,否则多线程可能会使您的代码变慢
  • 列表中有 cca​​ 1000 个元素,但该函数也被调用了 1000 次。
  • 启动线程会增加开销,它们之间的必要同步也是如此。您可以尝试 Stepan 的回答建议的并行 IntStream 方法,但考虑到您拥有的单个映射操作微不足道,我不确定 1000 个元素是否足以看到任何好处。但是,您可以对代码进行基准测试(使用 JMH)以查看多线程是否可以提高性能。
  • “合并”是什么意思?您是指传统意义上的“合并”,其中两个给定列表按某种顺序排序,最终“合并”列表也必须按相同顺序排序?我不知道有什么有效的方法可以并行化,因为算法必须在每一步比较每个给定列表中的“下一个”条目。另一方面,如果您只想连接这两个列表,那么您可能有两个线程,每个线程将成员从两个给定数组之一复制到最终数组中的适当位置.
  • 学习编程最重要的一点是,过早的优化是万恶之源。

标签: java multithreading arraylist parallel-processing


【解决方案1】:

我同意其他 cmets 的观点,即并行执行可能没有帮助。 不过,试试这段代码,看看并行是否对您有益

    public List<Pair<String, Integer>> mergeIdWithGrade(List<String> id, List<Integer> grades) {
      return IntStream
            .range(0, Math.min(id.size(), grades.size()))
            .parallel() // try with and without it
            .mapToObj(i -> new Pair(id.get(i), grades.get(i)))
            .collect(Collectors.toList());
    }

注意,这里只是映射在不同的线程中完成。结果将由主线程收集。

【讨论】:

  • 谢谢解答,这个功能我试过了,比旧的好不了多少。我测试了我拥有的整个程序,它比原来慢了大约 0.9 秒 :( 我认为在我的情况下,毕竟没有办法改进这一点。
  • @therealsowho 一种优化可能是创建具有非默认初始容量的ArrayList(例如new ArrayList&lt;&gt;(id.size()))。这有助于防止在ArrayList 中进行不必要的调整大小操作(这涉及分配新数组并复制元素)。不过,同样,1000 个元素可能不足以看到显着差异。如前所述,避免过早优化。基准测试和分析代码以查看瓶颈在哪里。
【解决方案2】:

这里的多线程是个坏主意,因为您无法确定原始列表的状态。 确保它是线程安全的。

【讨论】: