Java编程常用函数深入精讲教程(附案例源码)
一、函数基础概念
1. 函数组成要素
public class FunctionBasics {
// 访问修饰符:public(公开访问)
// 静态修饰符:static(类方法)
// 返回类型:int(返回整数)
// 函数名:calculateSum(动词+名词)
// 参数列表:(int a, int b) - 形式参数
public static int calculateSum(int a, int b) {
int result = a + b; // 函数体:执行计算
return result; // 返回值:返回计算结果
}
public static void main(String[] args) {
int num1 = 10; // 实际参数1
int num2 = 20; // 实际参数2
// 函数调用:使用实际参数
int sum = calculateSum(num1, num2);
System.out.println("计算结果: " + sum); // 输出:计算结果: 30
}
}
2. 参数传递机制
public class ParameterPassing {
// 值传递示例(基本数据类型)
public static void modifyValue(int value) {
value *= 2; // 修改形参值
System.out.println("函数内修改值: " + value); // 输出:20
}
// 引用传递示例(对象类型)
public static void modifyArray(int[] arr) {
arr[0] = 100; // 修改数组元素
System.out.println("函数内数组: " + Arrays.toString(arr)); // 输出:[100, 2, 3]
}
public static void main(String[] args) {
// 值传递测试
int num = 10;
modifyValue(num);
System.out.println("main函数值: " + num); // 输出:10(原始值未变)
// 引用传递测试
int[] numbers = {1, 2, 3};
modifyArray(numbers);
System.out.println("main函数数组: " + Arrays.toString(numbers)); // 输出:[100, 2, 3]
}
}
二、函数分类精讲
1. 递归函数
public class RecursionDemo {
// 递归计算阶乘
// 时间复杂度:O(n) 空间复杂度:O(n)(调用栈深度)
public static int factorial(int n) {
if (n < 0) throw new IllegalArgumentException("负数无阶乘"); // 参数校验
if (n == 0 || n == 1) return 1; // 递归基线条件
return n * factorial(n - 1); // 递归调用
}
// 递归生成斐波那契数列
// 时间复杂度:O(2^n)(指数级,实际应用需优化)
public static int fibonacci(int n) {
if (n <= 0) return 0; // 处理非法输入
if (n == 1 || n == 2) return 1; // 基线条件
return fibonacci(n-1) + fibonacci(n-2); // 双递归调用
}
public static void main(String[] args) {
System.out.println("5的阶乘: " + factorial(5)); // 输出:120
System.out.println("斐波那契第7项: " + fibonacci(7)); // 输出:13
}
}
2. 高阶函数(函数作为参数)
import java.util.function.Function;
public class HigherOrderFunctions {
// 接受函数作为参数
public static Integer operation(Function<Integer, Integer> func, int value) {
return func.apply(value); // 执行传入的函数
}
// 返回函数
public static Function<Integer, Integer> getMultiplier(int factor) {
return x -> x * factor; // 返回lambda表达式(函数)
}
public static void main(String[] args) {
// 1. 函数作为参数
Integer doubled = operation(x -> x * 2, 5); // 传入lambda表达式
System.out.println("双倍值: " + doubled); // 输出:10
// 2. 函数工厂模式
Function<Integer, Integer> tripler = getMultiplier(3);
System.out.println("三倍值: " + tripler.apply(7)); // 输出:21
}
}
三、经典算法函数实现
1. 排序算法
import java.util.Arrays;
public class SortingAlgorithms {
// 快速排序(分治策略)
// 时间复杂度:平均O(n log n),最差O(n²)
public static void quickSort(int[] arr, int low, int high) {
if (low < high) {
int pi = partition(arr, low, high); // 获取分区点
quickSort(arr, low, pi - 1); // 递归排序左分区
quickSort(arr, pi + 1, high); // 递归排序右分区
}
}
private static int partition(int[] arr, int low, int high) {
int pivot = arr[high]; // 选择最右元素作为基准
int i = low - 1; // 小于基准的指针
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
// 交换元素
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// 将基准放到正确位置
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i + 1;
}
// 测试排序
public static void main(String[] args) {
int[] data = {10, 80, 30, 90, 40, 50, 70};
System.out.println("排序前: " + Arrays.toString(data));
quickSort(data, 0, data.length - 1);
System.out.println("快速排序后: " + Arrays.toString(data));
}
}
2. 查找算法
public class SearchAlgorithms {
// 二分查找(要求有序数组)
// 时间复杂度:O(log n)
public static int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // 防止整数溢出
if (arr[mid] == target) {
return mid; // 找到目标
} else if (arr[mid] < target) {
left = mid + 1; // 搜索右半区
} else {
right = mid - 1; // 搜索左半区
}
}
return -1; // 未找到
}
// 线性查找(通用)
// 时间复杂度:O(n)
public static int linearSearch(int[] arr, int target) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) return i;
}
return -1;
}
public static void main(String[] args) {
int[] sortedData = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
System.out.println("二分查找位置: " + binarySearch(sortedData, 23)); // 输出:5
int[] unsortedData = {45, 12, 78, 23, 56, 89, 34};
System.out.println("线性查找位置: " + linearSearch(unsortedData, 56)); // 输出:4
}
}
四、实用工具函数
1. 字符串处理
public class StringUtils {
// 反转字符串
public static String reverse(String input) {
return new StringBuilder(input).reverse().toString(); // 使用StringBuilder高效反转
}
// 统计字符出现次数
public static int countCharOccurrences(String str, char target) {
int count = 0;
for (char c : str.toCharArray()) {
if (c == target) count++;
}
return count;
}
// 检查回文(忽略大小写和空格)
public static boolean isPalindrome(String str) {
String cleanStr = str.replaceAll("\\s", "").toLowerCase();
int left = 0, right = cleanStr.length() - 1;
while (left < right) {
if (cleanStr.charAt(left++) != cleanStr.charAt(right--))
return false;
}
return true;
}
public static void main(String[] args) {
System.out.println("反转结果: " + reverse("Java")); // avaJ
System.out.println("字符统计: " + countCharOccurrences("programming", 'm')); // 2
System.out.println("回文检测: " + isPalindrome("A man a plan a canal Panama")); // true
}
}
2. 数学计算
public class MathUtils {
// 计算最大公约数(欧几里得算法)
public static int gcd(int a, int b) {
if (b == 0) return Math.abs(a); // 处理负数
return gcd(b, a % b); // 递归求解
}
// 矩阵乘法
public static int[][] matrixMultiply(int[][] A, int[][] B) {
int rowsA = A.length;
int colsA = A[0].length;
int colsB = B[0].length;
if (colsA != B.length)
throw new IllegalArgumentException("矩阵维度不匹配");
int[][] result = new int[rowsA][colsB];
for (int i = 0; i < rowsA; i++) {
for (int j = 0; j < colsB; j++) {
for (int k = 0; k < colsA; k++) {
result[i][j] += A[i][k] * B[k][j]; // 点积计算
}
}
}
return result;
}
public static void main(String[] args) {
System.out.println("GCD(48, 18): " + gcd(48, 18)); // 6
int[][] matrixA = {{1, 2}, {3, 4}};
int[][] matrixB = {{5, 6}, {7, 8}};
int[][] product = matrixMultiply(matrixA, matrixB);
System.out.println("矩阵乘法结果: " + Arrays.deepToString(product));
// 输出:[[19, 22], [43, 50]]
}
}
五、函数设计最佳实践
1. 函数设计原则
public class BestPractices {
// 好示例:单一职责,清晰命名
public static double calculateCircleArea(double radius) {
validateRadius(radius); // 参数校验
return Math.PI * radius * radius; // 明确计算
}
private static void validateRadius(double radius) {
if (radius <= 0)
throw new IllegalArgumentException("半径必须为正数");
}
// 避免:过长函数(>30行)
// 避免:副作用(修改外部状态)
public static int pureFunctionExample(int a, int b) {
// 无副作用,输出仅依赖输入
return a * b + (a + b);
}
// 文档注释示例
/**
* 计算身体质量指数(BMI)
*
* @param weight 体重(千克)
* @param height 身高(米)
* @return BMI值
* @throws IllegalArgumentException 参数非法时抛出
*/
public static double calculateBMI(double weight, double height) {
if (weight <= 0 || height <= 0)
throw new IllegalArgumentException("参数必须为正数");
return weight / (height * height);
}
// 函数式接口应用
public static void processNumbers(int[] numbers, IntConsumer processor) {
for (int num : numbers) {
processor.accept(num); // 对每个元素执行操作
}
}
public static void main(String[] args) {
// 使用函数式接口
int[] values = {1, 2, 3, 4, 5};
processNumbers(values, n -> System.out.println("处理值: " + n * 2));
}
}
六、性能优化技巧
1. 递归优化(记忆化)
import java.util.HashMap;
import java.util.Map;
public class RecursionOptimization {
// 传统斐波那契(效率低)
public static long fibNaive(int n) {
if (n <= 1) return n;
return fibNaive(n-1) + fibNaive(n-2);
}
// 使用记忆化优化
private static Map<Integer, Long> memo = new HashMap<>();
public static long fibMemoized(int n) {
if (n <= 1) return n;
if (memo.containsKey(n)) return memo.get(n); // 返回缓存结果
long result = fibMemoized(n-1) + fibMemoized(n-2);
memo.put(n, result); // 缓存计算结果
return result;
}
// 迭代法(最佳性能)
public static long fibIterative(int n) {
if (n <= 1) return n;
long a = 0, b = 1;
for (int i = 2; i <= n; i++) {
long temp = a + b;
a = b;
b = temp;
}
return b;
}
public static void main(String[] args) {
int n = 45;
long start = System.currentTimeMillis();
System.out.println("记忆化结果: " + fibMemoized(n));
System.out.println("耗时: " + (System.currentTimeMillis()-start) + "ms");
start = System.currentTimeMillis();
System.out.println("迭代结果: " + fibIterative(n));
System.out.println("耗时: " + (System.currentTimeMillis()-start) + "ms");
}
}
七、函数调试技巧
public class DebuggingTechniques {
// 使用断言验证中间结果
public static double calculateDiscount(double price, double rate) {
assert price > 0 : "价格必须为正数"; // 启用断言需加VM参数:-ea
assert rate >= 0 && rate <= 1 : "折扣率应在0-1之间";
double discounted = price * (1 - rate);
System.out.println("折扣计算中间值: " + discounted); // 临时输出
// 条件断点示例:当discounted < 50时暂停
return discounted;
}
// 日志调试
public static void processData(int[] data) {
System.out.println("开始处理数组,长度: " + data.length);
for (int i = 0; i < data.length; i++) {
// 使用日志记录关键步骤
if (data[i] < 0) {
System.err.println("警告:发现负数索引 " + i);
}
data[i] *= 2;
}
System.out.println("处理完成: " + Arrays.toString(data));
}
public static void main(String[] args) {
calculateDiscount(100, 0.2); // 正常调用
// calculateDiscount(-50, 0.3); // 触发断言
processData(new int[]{1, -2, 3, 0, 5});
}
}
划重点!!!!!!
-
函数设计原则:
- 单一职责(一个函数只做一件事)
- 合理命名(动词+名词,如calculateTax)
- 参数控制(≤5个参数)
- 避免副作用(减少修改外部状态)
-
性能考量:
- 递归函数需注意栈溢出风险
- 时间复杂度敏感场景避免嵌套循环
- 大数据处理优先选择迭代而非递归
-
代码可读性:
- 添加清晰的文档注释(使用Javadoc)
- 保持函数长度适中(20-30行)
- 使用工具函数封装重复逻辑
-
异常处理:
- 函数开头进行参数校验
- 使用明确的异常类型
- 避免在函数内吞没异常
所有案例均基于Java 17,可直接复制使用。建议通过修改参数、添加边界测试和性能分析来深化理解。实际开发中应结合具体场景选择合适实现方式。
&spm=1001.2101.3001.5002&articleId=149661934&d=1&t=3&u=94fdd698bac348c8803a8b698d94488b)
8289

被折叠的 条评论
为什么被折叠?



