Java高级程序设计

Awesome Java

Awesome

Awesome lists about all kinds of interesting topics.

See contents at

https://github.com/sindresorhus/awesome

Awesome Java

https://github.com/akullpp/awesome-java

A curated list of awesome frameworks, libraries and software for the Java programming language.

The meaning of curated is carefully chosen and thoughtfully organized or presented.

JVM and JDK

  • Eclipse Temurin (AdoptOpenJDK) - Community-driven OpenJDK builds, including both HotSpot and OpenJ9.
  • Graal - Polyglot embeddable JVM. (GPL-2.0-only WITH Classpath-exception-2.0)
  • Open JDK - Open JDK community home. (GPL-2.0-only WITH Classpath-exception-2.0)
  • Zulu - OpenJDK builds for Windows, Linux, and macOS. (GPL-2.0-only WITH Classpath-exception-2.0)
  • ...

GUI

Game Development

Web Frameworks

Workflow Orchestration Engines

  • Cadence - Stateful code platform from Uber.
  • flowable - Compact and efficient workflow and business process management platform.
  • Temporal - Microservice orchestration platform, forked from Cadence but gRPC based.

Database

H2 示例:内存数据库

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class H2Example {
    public static void main(String[] args) {
        // 需要在构建工具中引入 H2 依赖,例如 Maven:
        // <dependency>
        //   <groupId>com.h2database</groupId>
        //   <artifactId>h2</artifactId>
        //   <version>2.2.224</version>
        // </dependency>

        String url = "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1"; // JVM 存活期间一直保留
        try (
            Connection conn = DriverManager.getConnection(url, "sa", "");
            Statement stmt = conn.createStatement()
        ) {
            // 1. 创建表
            stmt.execute("CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50))");

            // 2. 插入数据
            stmt.executeUpdate("INSERT INTO users VALUES (1, 'Alice')");
            stmt.executeUpdate("INSERT INTO users VALUES (2, 'Bob')");

            // 3. 查询数据
            try (ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
                while (rs.next()) {
                    System.out.println(rs.getInt("id") + ": " + rs.getString("name"));
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

ORM

Machine Learning

Bytecode Manipulation

Javassist 示例:动态修改类

import javassist.*;

public class JavassistExample {
    public static void main(String[] args) throws Exception {
        // 1. 获取类池
        ClassPool pool = ClassPool.getDefault();
        
        // 2. 加载目标类
        CtClass cc = pool.get("com.example.User");
        
        // 3. 添加新方法
        CtMethod newMethod = CtNewMethod.make(
            "public void sayHello() { " +
            "    System.out.println(\"Hello from Javassist!\"); " +
            "}",
            cc
        );
        cc.addMethod(newMethod);
        
        // 4. 修改现有方法(添加日志)
        CtMethod method = cc.getDeclaredMethod("getName");
        method.insertBefore("System.out.println(\"Getting name...\");");
        
        // 5. 生成修改后的类
        cc.writeFile(".");
        
        // 6. 使用修改后的类
        Class<?> clazz = cc.toClass();
        Object user = clazz.newInstance();
        clazz.getMethod("sayHello").invoke(user);
    }
}

ASM 示例:方法调用统计

import org.objectweb.asm.*;

public class MethodCounter extends ClassVisitor {
    private int methodCount = 0;
    
    public MethodCounter() {
        super(Opcodes.ASM9);
    }
    
    @Override
    public MethodVisitor visitMethod(
        int access, String name, String descriptor,
        String signature, String[] exceptions) {
        methodCount++;
        return super.visitMethod(access, name, descriptor, signature, exceptions);
    }
    
    public int getMethodCount() {
        return methodCount;
    }
}

// 使用示例
public class ASMExample {
    public static void main(String[] args) throws Exception {
        ClassReader cr = new ClassReader("com.example.User");
        MethodCounter counter = new MethodCounter();
        cr.accept(counter, 0);
        System.out.println("方法数量: " + counter.getMethodCount());
    }
}

Code Generators

Lombok 示例:减少样板代码

不使用 Lombok(传统方式)

public class User {
    private String name;
    private int age;
    
    public User() {}
    
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age && Objects.equals(name, user.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
    
    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }
}

使用 Lombok(简洁方式)

import lombok.*;

@Data                    // 生成 getter/setter、equals、hashCode、toString
@AllArgsConstructor      // 生成全参构造函数
@NoArgsConstructor       // 生成无参构造函数
@Builder                 // 生成建造者模式
public class User {
    private String name;
    private int age;
}

// 使用示例
User user = User.builder()
    .name("张三")
    .age(25)
    .build();

效果:从 50+ 行代码减少到 10 行!

Compiler-compiler

  • ANTLR - Complex full-featured framework for top-down parsing.

Terence Parr is the maniac behind ANTLR and has been working on language tools since 1989. He is a professor of computer science at the University of San Francisco.

https://www.bilibili.com/video/BV1n441137ex

ANTLR 示例:简单计算器

1. 定义语法(Calc.g4)

grammar Calc;

expr:   expr '+' term    # Add
    |   expr '-' term    # Sub
    |   term             # TermValue
    ;

term:   term '*' factor  # Mul
    |   term '/' factor  # Div
    |   factor           # FactorValue
    ;

factor: NUMBER           # Number
    |   '(' expr ')'    # Parens
    ;

NUMBER: [0-9]+ ('.' [0-9]+)?;
WS: [ \t\r\n]+ -> skip;

2. Java 代码使用

import org.antlr.v4.runtime.*;

public class Calculator {
    public static void main(String[] args) {
        String input = "3 + 4 * 2";
        CharStream stream = CharStreams.fromString(input);
        CalcLexer lexer = new CalcLexer(stream);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        CalcParser parser = new CalcParser(tokens);
        
        CalcParser.ExprContext tree = parser.expr();
        System.out.println("结果: " + evaluate(tree));
    }
    
    private static int evaluate(CalcParser.ExprContext ctx) {
        // 实现表达式求值逻辑
        // ...
    }
}

Computer Vision

JavaCV 示例:读取摄像头

import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.Mat;

public class WebcamExample {
    public static void main(String[] args) throws FrameGrabber.Exception {
        // 1. 打开摄像头
        FrameGrabber grabber = FrameGrabber.createDefault(0);
        grabber.start();
        
        // 2. 创建窗口显示
        CanvasFrame canvas = new CanvasFrame("摄像头");
        canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
        
        // 3. 循环读取帧
        while (canvas.isVisible()) {
            Frame frame = grabber.grab();
            if (frame != null) {
                canvas.showImage(frame);
            }
        }
        
        // 4. 释放资源
        grabber.stop();
        canvas.dispose();
    }
}

图像处理示例

import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_imgcodecs.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*;

public class ImageProcessing {
    public static void main(String[] args) {
        // 1. 读取图像
        Mat image = imread("input.jpg");
        
        // 2. 转换为灰度图
        Mat gray = new Mat();
        cvtColor(image, gray, COLOR_BGR2GRAY);
        
        // 3. 高斯模糊
        Mat blurred = new Mat();
        GaussianBlur(gray, blurred, new Size(15, 15), 0);
        
        // 4. 保存结果
        imwrite("output.jpg", blurred);
    }
}

Constraint Satisfaction Problem Solver

  • Choco - Off-the-shelf constraint satisfaction problem solver that uses constraint programming techniques.
  • JaCoP - Includes an interface for the FlatZinc language, enabling it to execute MiniZinc models. (AGPL-3.0)
  • OptaPlanner - Business planning and resource scheduling optimization solver.

Choco Solver 示例:数独求解器

数独是一个经典的约束满足问题(CSP),需要满足以下约束:

  1. 每行包含 1-9 的数字,且不重复
  2. 每列包含 1-9 的数字,且不重复
  3. 每个 3x3 宫格包含 1-9 的数字,且不重复

Choco Solver 调用 solve() 方法求解

  • Model:定义约束问题的模型
  • IntVar:整数变量,表示需要求解的未知值
  • 约束:使用 allDifferent()arithm() 等方法添加约束条件

使用 Choco Solver 求解

package com.example.csp;

import org.chocosolver.solver.Model;
import org.chocosolver.solver.Solver;
import org.chocosolver.solver.variables.IntVar;

public class SudokuSolver {
    public static void main(String[] args) {
        // 定义数独谜题(0 表示空白)
        int[][] puzzle = {
            {5, 3, 0, 0, 7, 0, 0, 0, 0},
            {6, 0, 0, 1, 9, 5, 0, 0, 0},
            {0, 9, 8, 0, 0, 0, 0, 6, 0},
            {8, 0, 0, 0, 6, 0, 0, 0, 3},
            {4, 0, 0, 8, 0, 3, 0, 0, 1},
            {7, 0, 0, 0, 2, 0, 0, 0, 6},
            {0, 6, 0, 0, 0, 0, 2, 8, 0},
            {0, 0, 0, 4, 1, 9, 0, 0, 5},
            {0, 0, 0, 0, 8, 0, 0, 7, 9}
        };

        int[][] solution = solveSudoku(puzzle);
        // 输出解...
    }

    public static int[][] solveSudoku(int[][] puzzle) {
        Model model = new Model("Sudoku");
        
        // 创建变量:9x9 网格,每个单元格值范围 1-9
        IntVar[][] grid = new IntVar[9][9];
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                grid[i][j] = model.intVar("cell[" + i + "," + j + "]", 1, 9);
            }
        }

        // 约束1:已给定的数字
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (puzzle[i][j] != 0) {
                    model.arithm(grid[i][j], "=", puzzle[i][j]).post();
                }
            }
        }

        // 约束2:每行数字都不相同
        for (int i = 0; i < 9; i++) {
            model.allDifferent(grid[i]).post();
        }

        // 约束3:每列数字都不相同
        for (int j = 0; j < 9; j++) {
            IntVar[] column = new IntVar[9];
            for (int i = 0; i < 9; i++) {
                column[i] = grid[i][j];
            }
            model.allDifferent(column).post();
        }

        // 约束4:每个 3x3 宫格数字都不相同
        for (int boxRow = 0; boxRow < 3; boxRow++) {
            for (int boxCol = 0; boxCol < 3; boxCol++) {
                IntVar[] box = new IntVar[9];
                int index = 0;
                for (int i = boxRow * 3; i < boxRow * 3 + 3; i++) {
                    for (int j = boxCol * 3; j < boxCol * 3 + 3; j++) {
                        box[index++] = grid[i][j];
                    }
                }
                model.allDifferent(box).post();
            }
        }

        // 求解
        Solver solver = model.getSolver();
        if (solver.solve()) {
            int[][] solution = new int[9][9];
            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    solution[i][j] = grid[i][j].getValue();
                }
            }
            return solution;
        }
        return null;
    }
}

Document Processing

  • Apache POI - Supports OOXML (XLSX, DOCX, PPTX) as well as OLE2 (XLS, DOC or PPT).
  • documents4j - API for document format conversion using third-party converters such as MS Word.
  • docx4j - Create and manipulate Microsoft Open XML files.
  • fastexcel - High performance library to read and write large Excel (XLSX) worksheets.

Apache POI 示例:Excel 操作

写入 Excel

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;

public class ExcelWriter {
    public static void main(String[] args) throws Exception {
        // 1. 创建工作簿
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("学生成绩");
        
        // 2. 创建表头
        Row headerRow = sheet.createRow(0);
        headerRow.createCell(0).setCellValue("姓名");
        headerRow.createCell(1).setCellValue("成绩");
        
        // 3. 写入数据
        Row row1 = sheet.createRow(1);
        row1.createCell(0).setCellValue("张三");
        row1.createCell(1).setCellValue(95);
        
        Row row2 = sheet.createRow(2);
        row2.createCell(0).setCellValue("李四");
        row2.createCell(1).setCellValue(88);
        
        // 4. 保存文件
        FileOutputStream out = new FileOutputStream("成绩单.xlsx");
        workbook.write(out);
        workbook.close();
    }
}

读取 Excel

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;

public class ExcelReader {
    public static void main(String[] args) throws Exception {
        // 1. 读取文件
        FileInputStream fis = new FileInputStream("成绩单.xlsx");
        Workbook workbook = new XSSFWorkbook(fis);
        Sheet sheet = workbook.getSheetAt(0);
        
        // 2. 遍历行
        for (Row row : sheet) {
            for (Cell cell : row) {
                System.out.print(cell.getStringCellValue() + "\t");
            }
            System.out.println();
        }
        
        workbook.close();
    }
}

Others

Apache Lucene 示例:全文搜索

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.store.*;

public class LuceneExample {
    public static void main(String[] args) throws Exception {
        // 1. 创建索引目录
        Directory directory = new RAMDirectory();
        IndexWriterConfig config = new IndexWriterConfig(new StandardAnalyzer());
        IndexWriter writer = new IndexWriter(directory, config);
        
        // 2. 添加文档到索引
        Document doc1 = new Document();
        doc1.add(new TextField("title", "Java编程指南", Field.Store.YES));
        doc1.add(new TextField("content", "这是一本关于Java编程的书籍", Field.Store.YES));
        writer.addDocument(doc1);
        
        Document doc2 = new Document();
        doc2.add(new TextField("title", "Python数据分析", Field.Store.YES));
        doc2.add(new TextField("content", "学习Python进行数据分析", Field.Store.YES));
        writer.addDocument(doc2);
        
        writer.close();
        
        // 3. 搜索
        IndexReader reader = DirectoryReader.open(directory);
        IndexSearcher searcher = new IndexSearcher(reader);
        
        Query query = new TermQuery(new Term("content", "Java"));
        TopDocs results = searcher.search(query, 10);
        
        // 4. 显示结果
        for (ScoreDoc scoreDoc : results.scoreDocs) {
            Document doc = searcher.doc(scoreDoc.doc);
            System.out.println("标题: " + doc.get("title"));
            System.out.println("内容: " + doc.get("content"));
        }
        
        reader.close();
    }
}