java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java常见算法

Java开发中的常见常用算法详解

作者:禹曦a

在Java编程中掌握常用的算法对于高效解决问题至关重要,下面这篇文章主要介绍了Java开发中常见常用算法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

总结

Java 作为一门工业级编程语言,其强大的标准库和生态系统内置了大量高效、稳定的算法。同时,理解并能够实现经典算法是程序员的核心能力。本文将从 “直接用” 和 “自己写” 两个维度,系统梳理 Java 开发中的常见算法。

第一部分:开箱即用 — JDK 内置算法

Java 标准库 (java.util 和 java.util.Arrays) 提供了许多现成的算法,它们经过高度优化和严格测试,是日常开发的首选。

1. 排序算法 (Sorting)

核心类: java.util.Collectionsjava.util.Arrays

示例代码:

import java.util.*;

// 1. 对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. 对数组排序
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. 自定义排序规则(使用Comparator)
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// 按字符串长度排序
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.Collectionsjava.util.Arrays

示例代码:

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 (未找到。插入点应为 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); // 输出: 3

3. 洗牌、填充与工具算法

核心类: java.util.Collections

示例代码:

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);

第二部分:核心基础 — 需要掌握的经典算法

虽然 JDK 提供了强大的工具,但许多算法思想需要开发者自己实现来解决特定问题。

1. 排序与搜索基础

理解这些基础算法的实现有助于深入理解算法思想。

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;
            }
        }
    }
}
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)

许多高效算法基于此思想。

// 简单递归(效率极低,存在大量重复计算)
public static int fibonacciRecursive(int n) {
    if (n <= 1) return n;
    return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2);
}

// 使用动态规划(迭代+记忆化,高效)
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 标准库没有图结构,需要自行建模(使用邻接表或邻接矩阵)并实现算法。

// 使用邻接表(最常用)
// 1. 使用 Map 和 List
Map<Integer, List<Integer>> graph = new HashMap<>();
// 2. 或创建一个 Node 类
class GraphNode {
    int val;
    List<GraphNode> neighbors;
    GraphNode(int x) { val = x; neighbors = new ArrayList<>(); }
}

// 使用二维数组(邻接矩阵)表示带权图
int[][] graphMatrix;
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<>(); // 记录到起点的距离

    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. 动态规划 (Dynamic Programming)

通过存储子问题的解来避免重复计算,从而高效解决复杂问题。

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];
}
// 可以进一步优化空间复杂度到 O(1),只保留前两个状态

总结与实践建议

场景推荐做法
对集合/数组排序永远优先使用 Collections.sort() 或 Arrays.sort()
在有序数据中查找使用 binarySearch()
需要随机顺序使用 Collections.shuffle()
解决特定领域问题 (如最短路径、背包问题)1. 首先寻找优秀的第三方库 (如 JGraphT for 图算法)。
2. 其次再考虑自己实现经典算法。
面试与学习必须掌握如何从零实现各类经典算法 (快排、归并、BFS/DFS、DP等)。
性能优化理解算法复杂度 (Big O),这是选择合适算法和数据结构的根本依据。

核心思想:

不要重复造轮子。 在日常业务开发中,最大限度地利用 JDK 和成熟第三方库提供的稳定高效的算法实现。你的精力应该集中在正确地建模业务问题选择最合适的工具(算法/数据结构) 上,而不是重新实现一个可能更差的排序算法。然而,深入理解这些轮子是如何造出来的,是你在遇到复杂问题、需要进行底层优化或通过技术面试时的必备能力。

到此这篇关于Java开发中的常见常用算法详解的文章就介绍到这了,更多相关Java常见算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文