Java的Arrays.sort():排序算法與優化分析

文章目錄

  • 前言
  • 一、基本類型數組:雙軸快速排序
    • 關鍵優化策略
  • 二、對象數組:TimSort
    • 關鍵優化策略
  • 三、性能對比總結
  • 總結


前言

在Java中,Arrays.sort()是開發者最常用的排序方法之一。但你是否思考過它的底層實現?本文將基于OpenJDK 17源碼,深入分析其使用的排序算法和優化策略,涵蓋基本類型與對象數組的不同實現。


Arrays.sort()原理

一、基本類型數組:雙軸快速排序

源碼路徑:java.util.DualPivotQuicksort

核心算法
對于int[]、long[]等基本類型,Java使用雙軸快速排序(自Java 7引入),其核心思想是:

  1. 選擇兩個軸(Pivot)將數組分為三部分:
    • 左段:< P1
    • 中段:P1 ≤ & ≤ P2
    • 右段:> P2
  2. 遞歸排序三個子段

雙軸快速排序

關鍵優化策略

  1. 小數組插入排序:當數組長度 < 47 時,切換為插入排序
if (length < INSERTION_SORT_THRESHOLD) {insertionSort(a, low, high);return;
}
  1. 五取樣法選擇軸元素:通過取5個等距位置的元素,用中位數法確定雙軸
int e1 = a[k], e5 = a[n]; // 等距取5個點
// ... 中位數計算確保P1<P2
  1. 三向切分處理重復元素:分區時采用三向切分,高效處理重復值
while (k <= great) {if (ak < pivot1) { // 左段swap(a, k, left++);} else if (ak > pivot2) { // 右段while (a[great] > pivot2 && k < great) great--;swap(a, k, great--);}// 中段無需交換
}
  1. 大數組歸并排序兜底:當遞歸深度超過log2(n) × 2時,切換為歸并排序避免最壞情況
if (depth == 0) {heapSort(a, low, high); // 實際是歸并排序return;
}

二、對象數組:TimSort

TimSort 是一種自適應的混合排序算法,通過智能識別和擴展數組中的自然有序片段(Run),結合二分插入排序優化小段數據、歸并排序平衡合并有序段,并利用Galloping Mode加速歸并過程,從而在各類現實數據(尤其是部分有序或包含重復值的數據集)上實現高效穩定的排序,其時間復雜度為O(n log n),在最佳情況下可接近O(n)。

源碼路徑:java.util.TimSort
核心算法
對象數組(如String[])使用TimSort,這是一種混合排序:

  • 歸并排序為框架
  • 插入排序處理小片段

TimSort

關鍵優化策略

  1. 分段(Run)檢測:掃描數組,將自然有序片段(升序或嚴格降序)作為基礎單元
int runLen = countRunAndMakeAscending(a, lo, hi);
  1. 動態最小Run長度:根據數組大小動態計算最小Run長度(16~32),確保后續歸并效率。
int minRun = minRunLength(nRemaining);
  1. 二分插入排序擴展Run:若自然Run長度不足,用二分插入排序擴展到minRun。
binarySort(a, lo, hi, lo + initRunLen);
  1. 歸并棧(Stack)管理:維護待歸并Run的棧,確保棧內Run長度滿足。
    stack[n-2] > stack[n-1] + stack[n]
    stack[n-1] > stack[n]
while (stackSize > 1) {int n = stackSize - 2;if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) {mergeAt(n); // 歸并相鄰Run}
}
  1. 高效內存利用
    • 歸并時復制小Run到臨時數組(避免大數組復制)
    • Galloping Mode:當一方連續勝出時,指數搜索加速歸并

三、性能對比總結

數組類型算法時間復雜度優化重點
基本類型雙軸快速排序平均O(n log n)小數組插入、三向切分
對象數組TimSort最差O(n log n)自然Run利用、歸并棧

總結

Java的Arrays.sort()通過精妙的算法選擇和工程優化,實現了:

  • 基本類型:雙軸快排為主,插入/歸并兜底
  • 對象數組:TimSort最大化利用數據特性

這些設計使其在各類場景下保持高性能,成為Java集合框架的基石。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/83690.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/83690.shtml
英文地址,請注明出處:http://en.pswp.cn/web/83690.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

軟件測試質量的“防”與“治”

引言: 想象一下,你正在建造一座摩天大樓。你是愿意在打地基時就嚴格檢查材料規格和設計圖紙(主動防患),還是等到大樓封頂后才開始拿著錘子敲敲打打找裂縫(被動補救)?軟件世界亦是如此!今天,我們就來聊聊軟件測試這個“質量守護神”的兩大戰略思維和三大實戰招式,讓你…

TDengine 如何從 2.x 遷移到 3.0

本節講述如何通過 Explorer 界面創建數據遷移任務&#xff0c;從舊版 TDengine2 遷移數據到 TDengine 3.0 集群。 功能概述 taosX 通過 SQL 查詢源集群數據&#xff0c;并把查詢結果寫入到目標數據庫。具體實現上&#xff0c;taosX 以一個子表的一個時間段的數據作為查詢的基…

免下載蘋果 IPA 文件重簽名工具:快速更換應用名稱和 BID的教程

在iOS設備的使用和開發過程中&#xff0c;我們有時需要對IPA文件進行重簽名&#xff0c;以便更換應用名稱、Bundle ID&#xff08;軟件包標識符&#xff09;或其他相關信息。這一過程通常需要使用到特定的工具&#xff0c;然而&#xff0c;市面上的一些工具可能需要下載和安裝&…

Python全棧開發:前后端分離項目架構詳解

文章目錄 技術棧選擇后端技術棧前端技術棧 項目整體結構詳細目錄結構說明后端架構&#xff08;backend/&#xff09;1. 應用核心&#xff08;app/&#xff09;2. 數據層&#xff08;models/&#xff09;3. API模式層&#xff08;schemas/&#xff09;4. API路由層&#xff08;a…

微信小程序使用圖片實現紅包雨功能

微信小程序紅包雨功能實現&#xff1a;從組件封裝到頁面調用的完整實踐 先看示例截圖&#xff1a; 一、背景與技術選型 在微信小程序營銷活動中&#xff0c;紅包雨是一種極具吸引力的互動形式。實現紅包雨效果主要有 Canvas 和圖片兩種方案&#xff1a; &#xff08;1&…

Python day31

浙大疏錦行 數據拆分的基本框架&#xff0c;拆分后讓項目結構更加清晰

Chapter10-XXE

文章目錄 1.XXE介紹1.1 XXE產生的原因1.1.1 什么是XML&#xff1f;1.1.2 什么是XML實體1.1.3 什么是文檔類型定義&#xff08;document type definition&#xff09;1.1.4 什么是XML自定義實體1.1.5 什么是XML外部實體 2.XXE攻擊類型2.1 利用XXE檢索文件2.2 利用XXE執行SSRF攻擊…

Ribbon負載均衡實戰指南:7種策略選擇與生產避坑

引言&#xff1a;客戶端負載均衡的不可替代性 當面試官問你&#xff1a;“Ribbon 和 Nginx 有什么區別&#xff1f;”——Ribbon 是進程內 LB 這一句話值 20K 月薪。 作為微服務調用的核心樞紐&#xff0c;Ribbon 通過 ??本地服務清單動態分發請求??&#xff0c;避免中心化…

Webpack:現代前端構建工具的核心解析

Hi&#xff0c;我是布蘭妮甜 &#xff01;在前端工程化日益重要的今天&#xff0c;Webpack作為主流構建工具&#xff0c;已成為現代前端開發的核心基礎設施。它通過模塊化打包機制&#xff0c;優雅地解決了復雜應用中的資源管理問題&#xff0c;使開發者能夠專注于業務邏輯的實…

Elasticsearch索引wildcard查詢

在之前的文章 Elasticsearch索引的字段映射 中介紹過關于索引中字段查詢的多種方式。可以根據需要通過設置索引字段的type以及fields來實現分詞,精確匹配等多種方式的查詢。 elasticSearch中檢索核心類型大概可以分為:精準匹配檢索(Term-level queries)和基于分詞的全文匹…

1.3、SDH光接口類型

接口類型的命名遵循一個特定的代碼結構&#xff0c;格式通常為&#xff1a;應用代碼-速率等級.波長/距離代碼。 代碼的第一位字母表示應用場合&#xff1a;I 表示局內通信&#xff1b;S 表示短距離局間通信&#xff1b;L 表示長距離局間通信。字母橫杠后的第一位表示 STM 的速率…

淺析MySQL數據遷移與恢復:從SQLServer轉型到MySQL

文章目錄 前言一、MySQL與SQLServer數據管理方式對比1.1 文件結構差異&#xff1a;1.2 存儲引擎多樣性&#xff1a;1.3 備份恢復方式&#xff1a; 二、MySQL數據遷移方法與技術2.1 邏輯備份與恢復2.2 物理備份與恢復2.3 異構數據庫遷移(從SQLServer到MySQL) 三、MySQL數據恢復策…

HarmonyOS 5中UniApp的調試步驟

在 HarmonyOS 5 中調試 UniApp 應用的完整步驟如下&#xff0c;涵蓋環境配置、設備連接及調試方法&#xff1a; 一、環境準備 ?開發工具? 安裝 HBuilderX 4.64&#xff08;需啟用鴻蒙插件&#xff09;可選安裝 DevEco Studio 5.0.3&#xff08;用于真機調試&#xff09;配置 …

使用centos服務器和Let‘s Encypted配置SpingBoot項目的https證書

一、Centos安裝Certbot客戶端 yum install certbot 二、生成證書 certbot certonly --standalone -d 你的域名 執行該命令后會生成如下文件 privkey.pem : the private key for your certificate. fullchain.pem: the certificate file used in most server software. c…

AWS Well-Architected Framework詳解

一、六大支柱&#xff08;Well-Architected Framework&#xff09; AWS Well-Architected Framework 的實際操作可以通過其五大支柱&#xff08;或六大支柱&#xff0c;包括可持續性&#xff09;的具體實踐來證明。以下是每個支柱對應的實際操作示例&#xff1a; 卓越運營&am…

【特征工程】機器學習的特征構造和篩選

調研論文中&#xff0c;看到datafun的一篇agent文章“智能不夠&#xff0c;知識來湊”——知識驅動的金融決策智能體&#xff0c;里面提到了自動因子挖掘&#xff0c;感覺可以用來做機器學習的“特征工程”。 第一部分介紹如何“構造特征”&#xff0c;第二部分介紹如何“分析…

第21節 Node.js 多進程

Node.js本身是以單線程的模式運行的&#xff0c;但它使用的是事件驅動來處理并發&#xff0c;這樣有助于我們在多核 cpu 的系統上創建多個子進程&#xff0c;從而提高性能。 每個子進程總是帶有三個流對象&#xff1a;child.stdin, child.stdout和child.stderr。他們可能會共享…

【走進Golang】測試SDK環境搭建成功,配置path環境變量

[1]進入控制命令臺&#xff1a;win R -->cmd [2]證明SDK環境成功 1.此電腦 2.高級系統設置 3.環境變量 4.點擊環境變量&#xff0c;進入找到 path&#xff0c;點擊編輯 5.進入編輯,找到對應目錄&#xff0c;配置成功 添加完成后&#xff0c;點擊確定&#xff0c;確定&#…

LlamaIndex 工作流 并發執行

除了循環和分支之外&#xff0c;工作流還可以并發地執行步驟。當你有多個可以相互獨立運行的步驟&#xff0c;并且這些步驟中包含需要等待的耗時操作時&#xff0c;這種并發執行的方式就非常有用&#xff0c;因為它允許其他步驟并行運行。 觸發多個事件 到目前為止&#xff0…

精粹匯總:大廠編程規范(持續更新)

歡迎來到啾啾的博客&#x1f431;。 記錄學習點滴。分享工作思考和實用技巧&#xff0c;偶爾也分享一些雜談&#x1f4ac;。 有很多很多不足的地方&#xff0c;歡迎評論交流&#xff0c;感謝您的閱讀和評論&#x1f604;。 目錄 1 引言2 并發控制 (Concurrency Control)3 事務控…