跳到主要内容Java 常用算法详解:从集合框架到并发编程 | 极客日志Javajava算法
Java 常用算法详解:从集合框架到并发编程
Java 算法涵盖集合框架、Stream API、排序搜索、数值统计、字符串处理、并发并行及图算法实现。文章通过代码示例展示了 Collections 工具类用法、Lambda 表达式应用、二分查找、KMP 匹配、Fork/Join 框架及策略模式等核心知识点,旨在帮助开发者掌握 Java 高效编程技巧。
技术博主2 浏览 一、Java 算法生态:集合框架与流式编程
1.1 Java 算法的演进历程
Java 算法设计经历了三个重要阶段:
- JDK 1.2:Collections Framework 引入,奠定算法基础
- JDK 5:泛型、并发集合、增强 for 循环
- JDK 8:Stream API、Lambda 表达式、函数式编程革命
1.2 集合框架中的算法
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6);
Collections.sort(numbers);
Collections.sort(numbers, Collections.reverseOrder());
Collections.shuffle(numbers);
int index = Collections.binarySearch(numbers, 5);
int freq = Collections.frequency(numbers, 1);
Integer max = Collections.max(numbers);
Integer min = Collections.min(numbers);
List<Integer> unmodifiable = Collections.unmodifiableList(numbers);
Set<Integer> singleton = Collections.singleton(42);
List<Integer> nCopies = Collections.nCopies(5, 0);
二、Stream API:声明式算法编程
2.1 Stream 操作的三阶段
List<Integer> result = numbers.stream()
.filter(n -> n % == )
.map(n -> n * n)
.sorted((a, b) -> b - a)
.distinct()
.limit()
.collect(Collectors.toList());
numbers.parallelStream()
.filter(n -> isPrime(n))
.count();
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
2
0
3
long
count
=
2.2 高级 Stream 操作
Map<String, List<Employee>> byDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
Map<Boolean, List<Employee>> partitioned = employees.stream()
.collect(Collectors.partitioningBy(e -> e.getSalary() > 50000));
IntSummaryStatistics stats = employees.stream()
.mapToInt(Employee::getSalary)
.summaryStatistics();
String names = employees.stream()
.map(Employee::getName)
.collect(Collectors.joining(", ", "[", "]"));
Optional<Integer> total = numbers.stream()
.reduce((a, b) -> a + b);
Integer sum = numbers.stream()
.reduce(0, Integer::sum);
Collector<Employee, ?, Map<String, Double>> avgSalaryByDept =
Collectors.groupingBy(
Employee::getDepartment,
Collectors.averagingDouble(Employee::getSalary)
);
三、排序与搜索算法
3.1 对象排序的多种方式
class Person implements Comparable<Person> {
private String name;
private int age;
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
}
Comparator<Person> byName = Comparator.comparing(Person::getName);
Comparator<Person> byAge = Comparator.comparingInt(Person::getAge);
Comparator<Person> byNameThenAge =
Comparator.comparing(Person::getName)
.thenComparingInt(Person::getAge);
List<Person> sorted = people.stream()
.sorted(Comparator
.comparing(Person::getLastName)
.thenComparing(Person::getFirstName)
.reversed())
.collect(Collectors.toList());
Comparator<Person> nullsFirst =
Comparator.nullsFirst(Comparator.naturalOrder());
3.2 搜索算法实现
int[] sortedArray = {1, 3, 5, 7, 9, 11, 13};
int index = Arrays.binarySearch(sortedArray, 7);
public static <T> int binarySearch(List<? extends T> list, T key,
Comparator<? super T> c) {
int low = 0;
int high = list.size() - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
T midVal = list.get(mid);
int cmp = c.compare(midVal, key);
if (cmp < 0) {
low = mid + 1;
} else if (cmp > 0) {
high = mid - 1;
} else {
return mid;
}
}
return -(low + 1);
}
List<String> words = Arrays.asList("apple", "banana", "cherry", "date");
int pos = Collections.binarySearch(words, "cherry");
四、数值计算与统计
4.1 基本数值算法
double sqrt = Math.sqrt(16.0);
double pow = Math.pow(2, 10);
double sin = Math.sin(Math.PI / 2);
long round = Math.round(3.14159);
Random random = new Random();
int randomInt = random.nextInt(100);
double randomDouble = random.nextDouble();
SecureRandom secureRandom = new SecureRandom();
byte[] randomBytes = new byte[16];
secureRandom.nextBytes(randomBytes);
BigInteger bigInt = new BigInteger("12345678901234567890");
BigInteger result = bigInt.multiply(new BigInteger("2"));
BigDecimal decimal1 = new BigDecimal("10.50");
BigDecimal decimal2 = new BigDecimal("3.75");
BigDecimal division = decimal1.divide(decimal2, 4, RoundingMode.HALF_UP);
4.2 统计与聚合算法
public class Statistics {
public static double mean(double[] values) {
return Arrays.stream(values).average().orElse(0.0);
}
public static double median(double[] values) {
double[] sorted = values.clone();
Arrays.sort(sorted);
int n = sorted.length;
if (n % 2 == 0) {
return (sorted[n/2 - 1] + sorted[n/2]) / 2.0;
} else {
return sorted[n/2];
}
}
public static double standardDeviation(double[] values) {
double mean = mean(values);
double variance = Arrays.stream(values)
.map(x -> Math.pow(x - mean, 2))
.average().orElse(0.0);
return Math.sqrt(variance);
}
}
DoubleSummaryStatistics stats = Arrays.stream(new double[]{1.0, 2.0, 3.0, 4.0})
.summaryStatistics();
public static double[] movingAverage(double[] data, int window) {
double[] result = new double[data.length - window + 1];
double sum = 0;
for (int i = 0; i < window; i++) {
sum += data[i];
}
result[0] = sum / window;
for (int i = window; i < data.length; i++) {
sum = sum - data[i - window] + data[i];
result[i - window + 1] = sum / window;
}
return result;
}
五、字符串处理算法
5.1 字符串匹配与操作
public class KMP {
public static int search(String text, String pattern) {
int[] lps = computeLPS(pattern);
int i = 0, j = 0;
while (i < text.length()) {
if (text.charAt(i) == pattern.charAt(j)) {
i++;
j++;
if (j == pattern.length()) {
return i - j;
}
} else {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
return -1;
}
private static int[] computeLPS(String pattern) {
int[] lps = new int[pattern.length()];
int len = 0, i = 1;
while (i < pattern.length()) {
if (pattern.charAt(i) == pattern.charAt(len)) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
}
public static int editDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 0; i <= m; i++) dp[i][0] = i;
for (int j = 0; j <= n; j++) dp[0][j] = j;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = 1 + Math.min(
dp[i - 1][j - 1],
Math.min(
dp[i - 1][j],
dp[i][j - 1]
)
);
}
}
}
return dp[m][n];
}
public static String reverseString(String s) {
return new StringBuilder(s).reverse().toString();
}
public static boolean isPalindrome(String s) {
String cleaned = s.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
return cleaned.equals(new StringBuilder(cleaned).reverse().toString());
}
六、并发与并行算法
6.1 并行流与 Fork/Join 框架
long sum = LongStream.rangeClosed(1, 10_000_000)
.parallel()
.sum();
class SumTask extends RecursiveTask<Long> {
private static final int THRESHOLD = 10_000;
private final long[] array;
private final int start, end;
SumTask(long[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if (end - start <= THRESHOLD) {
long sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
int mid = (start + end) / 2;
SumTask left = new SumTask(array, start, mid);
SumTask right = new SumTask(array, mid, end);
left.fork();
long rightResult = right.compute();
long leftResult = left.join();
return leftResult + rightResult;
}
}
}
ForkJoinPool pool = new ForkJoinPool();
long[] numbers = new long[100_000];
SumTask task = new SumTask(numbers, 0, numbers.length);
long result = pool.invoke(task);
6.2 并发集合算法
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.compute("key", (k, v) -> v == null ? 1 : v + 1);
map.merge("key", 1, Integer::sum);
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("item1");
list.addIfAbsent("item1");
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);
new Thread(() -> {
try {
for (int i = 0; i < 100; i++) {
queue.put(i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
new Thread(() -> {
try {
while (true) {
Integer item = queue.take();
System.out.println("Consumed: " + item);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
七、图算法实现
7.1 图的表示与遍历
class Graph {
private final int V;
private final List<List<Integer>> adj;
public Graph(int V) {
this.V = V;
adj = new ArrayList<>(V);
for (int i = 0; i < V; i++) {
adj.add(new ArrayList<>());
}
}
public void addEdge(int v, int w) {
adj.get(v).add(w);
}
public void dfs(int start) {
boolean[] visited = new boolean[V];
Stack<Integer> stack = new Stack<>();
stack.push(start);
while (!stack.isEmpty()) {
int v = stack.pop();
if (!visited[v]) {
visited[v] = true;
System.out.print(v + " ");
for (int neighbor : adj.get(v)) {
if (!visited[neighbor]) {
stack.push(neighbor);
}
}
}
}
}
public void bfs(int start) {
boolean[] visited = new boolean[V];
Queue<Integer> queue = new LinkedList<>();
visited[start] = true;
queue.offer(start);
while (!queue.isEmpty()) {
int v = queue.poll();
System.out.print(v + " ");
for (int neighbor : adj.get(v)) {
if (!visited[neighbor]) {
visited[neighbor] = true;
queue.offer(neighbor);
}
}
}
}
}
public class Dijkstra {
public static int[] dijkstra(int[][] graph, int src) {
int V = graph.length;
int[] dist = new int[V];
boolean[] sptSet = new boolean[V];
Arrays.fill(dist, Integer.MAX_VALUE);
dist[src] = 0;
for (int count = 0; count < V - 1; count++) {
int u = minDistance(dist, sptSet);
sptSet[u] = true;
for (int v = 0; v < V; v++) {
if (!sptSet[v] && graph[u][v] != 0 &&
dist[u] != Integer.MAX_VALUE &&
dist[u] + graph[u][v] < dist[v]) {
dist[v] = dist[u] + graph[u][v];
}
}
}
return dist;
}
private static int minDistance(int[] dist, boolean[] sptSet) {
int min = Integer.MAX_VALUE, minIndex = -1;
for (int v = 0; v < dist.length; v++) {
if (!sptSet[v] && dist[v] <= min) {
min = dist[v];
minIndex = v;
}
}
return minIndex;
}
}
八、设计模式在算法中的应用
8.1 策略模式实现排序算法
interface SortStrategy {
void sort(int[] array);
}
class BubbleSortStrategy implements SortStrategy {
@Override
public void sort(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
for (int j = 0; j < array.length - i - 1; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
}
class QuickSortStrategy implements SortStrategy {
@Override
public void sort(int[] array) {
quickSort(array, 0, array.length - 1);
}
private void quickSort(int[] array, int low, int high) {
if (low < high) {
int pi = partition(array, low, high);
quickSort(array, low, pi - 1);
quickSort(array, pi + 1, high);
}
}
private int partition(int[] array, int low, int high) {
int pivot = array[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (array[j] < pivot) {
i++;
swap(array, i, j);
}
}
swap(array, i + 1, high);
return i + 1;
}
private void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
class Sorter {
private SortStrategy strategy;
public Sorter(SortStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(SortStrategy strategy) {
this.strategy = strategy;
}
public void sort(int[] array) {
strategy.sort(array);
}
}
public class StrategyPatternDemo {
public static void main(String[] args) {
int[] array = {5, 2, 8, 1, 9, 3};
Sorter sorter = new Sorter(new BubbleSortStrategy());
sorter.sort(array);
System.out.println("Bubble sort: " + Arrays.toString(array));
sorter.setStrategy(new QuickSortStrategy());
sorter.sort(array);
System.out.println("Quick sort: " + Arrays.toString(array));
}
}
Java 算法生态的丰富性使得开发者可以根据具体场景选择最合适的工具。从传统的集合框架到现代的 Stream API,从单线程算法到并发编程,Java 提供了完整的算法工具箱。掌握这些算法不仅能够提高代码效率,还能写出更优雅、更易维护的程序。