Java開發(fā)中的常見常用算法詳解
總結(jié)
Java 作為一門工業(yè)級(jí)編程語(yǔ)言,其強(qiáng)大的標(biāo)準(zhǔn)庫(kù)和生態(tài)系統(tǒng)內(nèi)置了大量高效、穩(wěn)定的算法。同時(shí),理解并能夠?qū)崿F(xiàn)經(jīng)典算法是程序員的核心能力。本文將從 “直接用” 和 “自己寫” 兩個(gè)維度,系統(tǒng)梳理 Java 開發(fā)中的常見算法。
第一部分:開箱即用 — JDK 內(nèi)置算法
Java 標(biāo)準(zhǔn)庫(kù) (java.util 和 java.util.Arrays) 提供了許多現(xiàn)成的算法,它們經(jīng)過高度優(yōu)化和嚴(yán)格測(cè)試,是日常開發(fā)的首選。
1. 排序算法 (Sorting)
核心類: java.util.Collections, java.util.Arrays
Collections.sort(List<T> list)用途: 對(duì)
List集合(如ArrayList,LinkedList) 進(jìn)行升序排序。底層實(shí)現(xiàn): 對(duì)于對(duì)象集合,它使用一種優(yōu)化的、穩(wěn)定的歸并排序變體 (TimSort)。穩(wěn)定性意味著相等元素的相對(duì)順序在排序后保持不變。
時(shí)間復(fù)雜度: 保證 O(n log n)。
Arrays.sort(int[] a)用途: 對(duì)基本類型數(shù)組(如
int[],double[]) 進(jìn)行排序。底層實(shí)現(xiàn): 使用雙軸快速排序 (Dual-Pivot Quicksort)。該算法是對(duì)經(jīng)典快排的改進(jìn),在實(shí)踐中效率極高。
Arrays.sort(T[] a)用途: 對(duì)對(duì)象數(shù)組(如
String[],Integer[]) 進(jìn)行排序。底層實(shí)現(xiàn): 同樣使用 TimSort 算法,保證穩(wěn)定性和高性能。
示例代碼:
import java.util.*;
// 1. 對(duì)List排序
List<Integer> numbersList = new ArrayList<>(Arrays.asList(23, 5, 42, -1, 99));
Collections.sort(numbersList);
System.out.println("Sorted List: " + numbersList); // 輸出: Sorted List: [-1, 5, 23, 42, 99]
// 2. 對(duì)數(shù)組排序
int[] numbersArray = {23, 5, 42, -1, 99};
Arrays.sort(numbersArray);
System.out.println("Sorted Array: " + Arrays.toString(numbersArray)); // 輸出: Sorted Array: [-1, 5, 23, 42, 99]
// 3. 自定義排序規(guī)則(使用Comparator)
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// 按字符串長(zhǎng)度排序
Collections.sort(names, (a, b) -> a.length() - b.length());
// 或使用方法引用:Collections.sort(names, Comparator.comparingInt(String::length));
System.out.println("Sorted by length: " + names); // 輸出: Sorted by length: [Bob, Alice, David, Charlie]2. 搜索算法 (Searching)
核心類: java.util.Collections, java.util.Arrays
Collections.binarySearch(List, Key)/Arrays.binarySearch(array, key)用途: 在已排序的列表或數(shù)組中,使用二分查找算法快速定位元素。
重要前提: 集合或數(shù)組必須是有序的(通常是升序),否則結(jié)果不可預(yù)測(cè)。
返回值: 如果找到,返回元素的索引;如果未找到,返回一個(gè)負(fù)值,表示應(yīng)插入的位置
(-(insertion point) - 1)。時(shí)間復(fù)雜度: O(log n)。
示例代碼:
List<Integer> sortedList = Arrays.asList(10, 20, 30, 40, 50);
int index1 = Collections.binarySearch(sortedList, 30);
System.out.println("Index of 30: " + index1); // 輸出: 2 (找到了)
int index2 = Collections.binarySearch(sortedList, 25);
System.out.println("Index of 25: " + index2); // 輸出: -3 (未找到。插入點(diǎn)應(yīng)為 2, 所以返回 -2-1 = -3)
int[] sortedArray = {10, 20, 30, 40, 50};
int index3 = Arrays.binarySearch(sortedArray, 40);
System.out.println("Index of 40 in array: " + index3); // 輸出: 33. 洗牌、填充與工具算法
核心類: java.util.Collections
Collections.shuffle(List)用途: 隨機(jī)打亂列表中元素的順序(洗牌)。
底層實(shí)現(xiàn): 使用 Fisher-Yates shuffle 算法的高效變體,能產(chǎn)生均勻的隨機(jī)排列。
Collections.reverse(List): 反轉(zhuǎn)列表。Collections.fill(List, obj): 用指定對(duì)象填充列表的所有元素。Collections.copy(destList, srcList): 復(fù)制列表。Collections.max(Collection)/Collections.min(Collection): 根據(jù)自然順序查找最大/最小元素。Collections.frequency(Collection, Object): 計(jì)算某元素出現(xiàn)的頻率。
示例代碼:
List<Integer> cards = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
cards.add(i);
}
System.out.println("Original deck: " + cards);
Collections.shuffle(cards);
System.out.println("Shuffled deck: " + cards);
// 其他工具方法
Collections.reverse(cards);
System.out.println("Reversed deck: " + cards);
int max = Collections.max(cards);
int frequencyOfFive = Collections.frequency(cards, 5);
System.out.println("Max card: " + max + ", Frequency of 5: " + frequencyOfFive);第二部分:核心基礎(chǔ) — 需要掌握的經(jīng)典算法
雖然 JDK 提供了強(qiáng)大的工具,但許多算法思想需要開發(fā)者自己實(shí)現(xiàn)來解決特定問題。
1. 排序與搜索基礎(chǔ)
理解這些基礎(chǔ)算法的實(shí)現(xiàn)有助于深入理解算法思想。
冒泡排序 (Bubble Sort)
思想: 重復(fù)遍歷列表,比較相鄰元素,如果順序錯(cuò)誤就交換它們。
復(fù)雜度: O(n²)。(僅用于教學(xué),實(shí)際開發(fā)切勿使用!)
public static void bubbleSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// 交換 arr[j] 和 arr[j+1]
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}線性搜索 (Linear Search)
思想: 從頭到尾遍歷每個(gè)元素,直到找到目標(biāo)。
復(fù)雜度: O(n)。適用于小規(guī)?;蛭磁判虻臄?shù)據(jù)。
public static int linearSearch(int[] arr, int target) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
return i; // 找到,返回索引
}
}
return -1; // 未找到
}2. 遞歸與分治 (Recursion & Divide and Conquer)
許多高效算法基于此思想。
經(jīng)典案例:斐波那契數(shù)列 (Fibonacci Sequence)
問題: F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2) (n>=2)。
// 簡(jiǎn)單遞歸(效率極低,存在大量重復(fù)計(jì)算)
public static int fibonacciRecursive(int n) {
if (n <= 1) return n;
return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2);
}
// 使用動(dòng)態(tài)規(guī)劃(迭代+記憶化,高效)
public static int fibonacciDP(int n) {
if (n <= 1) return n;
int[] dp = new int[n + 1];
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}3. 圖算法 (Graph Algorithms)
Java 標(biāo)準(zhǔn)庫(kù)沒有圖結(jié)構(gòu),需要自行建模(使用鄰接表或鄰接矩陣)并實(shí)現(xiàn)算法。
圖的表示:
// 使用鄰接表(最常用)
// 1. 使用 Map 和 List
Map<Integer, List<Integer>> graph = new HashMap<>();
// 2. 或創(chuàng)建一個(gè) Node 類
class GraphNode {
int val;
List<GraphNode> neighbors;
GraphNode(int x) { val = x; neighbors = new ArrayList<>(); }
}
// 使用二維數(shù)組(鄰接矩陣)表示帶權(quán)圖
int[][] graphMatrix;廣度優(yōu)先搜索 (BFS) - 尋找最短路徑(無權(quán)圖)
思想: 層層擴(kuò)散,使用隊(duì)列輔助。
public int bfsShortestPath(Map<Integer, List<Integer>> graph, int start, int end) {
Queue<Integer> queue = new LinkedList<>();
Set<Integer> visited = new HashSet<>();
Map<Integer, Integer> distance = new HashMap<>(); // 記錄到起點(diǎn)的距離
queue.offer(start);
visited.add(start);
distance.put(start, 0);
while (!queue.isEmpty()) {
int currentNode = queue.poll();
if (currentNode == end) {
return distance.get(currentNode);
}
for (int neighbor : graph.getOrDefault(currentNode, new ArrayList<>())) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
distance.put(neighbor, distance.get(currentNode) + 1);
}
}
}
return -1; // 未找到路徑
}4. 動(dòng)態(tài)規(guī)劃 (Dynamic Programming)
通過存儲(chǔ)子問題的解來避免重復(fù)計(jì)算,從而高效解決復(fù)雜問題。
經(jīng)典案例:爬樓梯問題
問題: 每次可以爬 1 或 2 個(gè)臺(tái)階,爬到 n 階有多少種不同方法?
狀態(tài)轉(zhuǎn)移方程:
dp[i] = dp[i-1] + dp[i-2]
public int climbStairs(int n) {
if (n <= 2) return n;
int[] dp = new int[n + 1];
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
// 可以進(jìn)一步優(yōu)化空間復(fù)雜度到 O(1),只保留前兩個(gè)狀態(tài)總結(jié)與實(shí)踐建議
| 場(chǎng)景 | 推薦做法 |
|---|---|
| 對(duì)集合/數(shù)組排序 | 永遠(yuǎn)優(yōu)先使用 Collections.sort() 或 Arrays.sort()。 |
| 在有序數(shù)據(jù)中查找 | 使用 binarySearch()。 |
| 需要隨機(jī)順序 | 使用 Collections.shuffle()。 |
| 解決特定領(lǐng)域問題 (如最短路徑、背包問題) | 1. 首先尋找優(yōu)秀的第三方庫(kù) (如 JGraphT for 圖算法)。 2. 其次再考慮自己實(shí)現(xiàn)經(jīng)典算法。 |
| 面試與學(xué)習(xí) | 必須掌握如何從零實(shí)現(xiàn)各類經(jīng)典算法 (快排、歸并、BFS/DFS、DP等)。 |
| 性能優(yōu)化 | 理解算法復(fù)雜度 (Big O),這是選擇合適算法和數(shù)據(jù)結(jié)構(gòu)的根本依據(jù)。 |
核心思想:
不要重復(fù)造輪子。 在日常業(yè)務(wù)開發(fā)中,最大限度地利用 JDK 和成熟第三方庫(kù)提供的穩(wěn)定高效的算法實(shí)現(xiàn)。你的精力應(yīng)該集中在正確地建模業(yè)務(wù)問題和選擇最合適的工具(算法/數(shù)據(jù)結(jié)構(gòu)) 上,而不是重新實(shí)現(xiàn)一個(gè)可能更差的排序算法。然而,深入理解這些輪子是如何造出來的,是你在遇到復(fù)雜問題、需要進(jìn)行底層優(yōu)化或通過技術(shù)面試時(shí)的必備能力。
到此這篇關(guān)于Java開發(fā)中的常見常用算法詳解的文章就介紹到這了,更多相關(guān)Java常見算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java數(shù)據(jù)結(jié)構(gòu)和算法中數(shù)組的簡(jiǎn)單入門
在本文里小編給大家整理了關(guān)于java數(shù)據(jù)結(jié)構(gòu)和算法中數(shù)組的簡(jiǎn)單入門知識(shí)點(diǎn)整理,需要的朋友們學(xué)習(xí)下。2019-06-06
Spring實(shí)現(xiàn)默認(rèn)標(biāo)簽解析流程
這篇文章主要為大家詳細(xì)介紹了Spring實(shí)現(xiàn)默認(rèn)標(biāo)簽解析流程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
Java編程實(shí)現(xiàn)的模擬行星運(yùn)動(dòng)示例
這篇文章主要介紹了Java編程實(shí)現(xiàn)的模擬行星運(yùn)動(dòng),涉及java基于swing組建繪制動(dòng)態(tài)效果及數(shù)值運(yùn)算相關(guān)操作技巧,并總結(jié)分析了java面向?qū)ο蟮南嚓P(guān)特性,需要的朋友可以參考下2018-04-04
RocketMQ生產(chǎn)者一個(gè)應(yīng)用不能發(fā)送多個(gè)NameServer消息解決
這篇文章主要為大家介紹了RocketMQ生產(chǎn)者一個(gè)應(yīng)用不能發(fā)送多個(gè)NameServer消息原因及解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
解決springboot項(xiàng)目找不到resources目錄下的資源問題
這篇文章主要介紹了解決springboot項(xiàng)目找不到resources目錄下的資源問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
Java OpenCV實(shí)現(xiàn)圖像鏡像翻轉(zhuǎn)效果
這篇文章主要為大家詳細(xì)介紹了Java OpenCV實(shí)現(xiàn)圖像鏡像翻轉(zhuǎn)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07

