【问题标题】:Why don't I get StackOverflowError while using Arrays.sort(Object[] a) on large array?为什么在大型数组上使用 Arrays.sort(Object[] a) 时不会出现 StackOverflowError?
【发布时间】:2015-09-26 14:05:28
【问题描述】:

每个递归函数调用都会占用线程堆栈上的空间。 在 Java 中,Arrays.sort(Object[] a) 使用归并排序。使用递归调用函数进行合并排序。为什么我们不会得到大型数组列表的 StackOverflowError?

我搜索了一下,在哪种情况下我应该使用递归或堆栈,但我没有找到明确的答案?

【问题讨论】:

  • 因为 2147483647 的 log(base 2) 大约是 31,真的没那么深?
  • 堆栈溢出(即Errors)在堆栈溢出时由JVM 抛出。您更有可能使用太大的数组超出堆。

标签: java arrays mergesort


【解决方案1】:

Arrays.sort 不使用合并排序的经典教科书版本,而是基于 TimSort as you can read here 的更复杂的版本。

此外,在 Java 中,堆栈大小不是固定限制,而是可以设置为 JVM 的选项。

如果您尝试,您可以非常容易地生成 OutOfMemory 异常或堆栈限制错误,但(谢天谢地)库函数旨在尝试避免它。

【讨论】:

  • 我在这个链接上看到了 Arrays.sort(Object[] a) 实现:grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
  • 我认为您的参考来自 Java6。更新后的代码如下:
  • public static void sort(Object[] var0) { if(Arrays.LegacyMergeSort.userRequested) { legacyMergeSort(var0); } else { ComparableTimSort.sort(var0, 0, var0.length, (Object[])null, 0, 0); } }
【解决方案2】:

典型的 Java 堆栈大小至少为 64k。由于合并排序的想法是每一步将数组拆分为 2,因此您至少需要说 3000 次拆分才能获得堆栈溢出。假设您有一个大小为 32 位(即大约 40 亿)元素的对象数组,它仍然比 64k 小得多。所以 Arrays.sort 不容易发生堆栈溢出。

【讨论】:

    猜你喜欢
    • 2023-02-15
    • 2011-01-15
    • 1970-01-01
    • 2020-02-24
    • 2018-07-25
    • 2017-12-21
    • 2021-09-28
    • 1970-01-01
    • 2014-09-17
    相关资源
    最近更新 更多