如何从50000行CSV生成Java Enum以创建EnumSet?
从CSV自动生成Java枚举类以创建EnumSet的解决方案
由于Java枚举是编译期确定的静态类型,无法在运行时动态生成新的枚举常量,所以要实现从CSV生成50000行枚举且保留EnumSet支持,最靠谱的方案是在编译前自动生成枚举类源码。以下是具体实现步骤:
一、核心思路
编写一个简单的代码生成工具,读取CSV文件内容后直接输出符合Java语法的枚举类源码,再将该工具集成到项目构建流程中,确保编译前自动完成枚举类的生成。
二、具体实现步骤
1. 准备CSV文件
假设你的CSV格式(带表头)如下:
code,name,population PARIS,巴黎,2161000 LONDON,伦敦,9002488 ...
其中code列对应枚举常量名(需符合Java标识符规则:无特殊字符、以字母开头),其余列为枚举的属性字段。
2. 编写枚举生成工具
可以用原生Java或Apache Commons CSV(更适合处理复杂CSV格式)实现,以下是示例代码:
依赖(若用Apache Commons CSV)
如果用Maven,在pom.xml中添加:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-csv</artifactId> <version>1.10.0</version> </dependency>
生成工具代码
import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; import java.io.BufferedWriter; import java.io.FileWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Paths; public class VilleEnumGenerator { public static void main(String[] args) throws Exception { // 1. 配置参数 String csvPath = "src/main/resources/ville.csv"; String targetPackage = "com.example.city"; String targetEnumName = "Ville"; String outputPath = "src/main/java/com/example/city/Ville.java"; // 2. 读取CSV并构建枚举内容 StringBuilder enumContent = new StringBuilder(); // 生成包声明和类定义 enumContent.append(String.format("package %s;\n\n", targetPackage)); enumContent.append(String.format("public enum %s {\n", targetEnumName)); // 解析CSV try (CSVParser parser = CSVParser.parse( Paths.get(csvPath), StandardCharsets.UTF_8, CSVFormat.DEFAULT.withHeader().withTrim() )) { int lineCount = 0; for (CSVRecord record : parser) { String enumConstName = record.get("code"); String cityName = record.get("name"); int population = Integer.parseInt(record.get("population")); // 生成枚举常量行 enumContent.append(String.format(" %s(\"%s\", %d)", enumConstName, cityName, population)); // 最后一行不加逗号 if (lineCount != parser.getRecordNumber() - 2) { enumContent.append(","); } enumContent.append("\n"); lineCount++; } } // 生成构造方法和Getter enumContent.append(";\n\n"); enumContent.append(" private final String name;\n"); enumContent.append(" private final int population;\n\n"); enumContent.append(String.format(" %s(String name, int population) {\n", targetEnumName)); enumContent.append(" this.name = name;\n"); enumContent.append(" this.population = population;\n"); enumContent.append(" }\n\n"); enumContent.append(" public String getName() {\n"); enumContent.append(" return name;\n"); enumContent.append(" }\n\n"); enumContent.append(" public int getPopulation() {\n"); enumContent.append(" return population;\n"); enumContent.append(" }\n"); enumContent.append("}\n"); // 3. 写入目标文件 try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath))) { writer.write(enumContent.toString()); } } }
3. 集成到构建流程(自动生成)
为了避免每次手动运行工具,可以将其集成到Maven/Gradle的构建阶段,确保编译前自动生成枚举类。
Maven集成示例
在pom.xml中添加exec-maven-plugin,让它在generate-sources阶段执行生成工具:
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>generate-ville-enum</id> <phase>generate-sources</phase> <goals> <goal>java</goal> </goals> <configuration> <mainClass>com.example.city.VilleEnumGenerator</mainClass> </configuration> </execution> </executions> </plugin> </plugins> </build>
执行mvn compile时,工具会自动运行并生成枚举类,之后正常编译即可使用。
三、注意事项
- 确保CSV中的
code列符合Java标识符规则,若不符合需在工具中添加转换逻辑(比如将空格替换为下划线、特殊字符转义)。 - 50000行枚举会生成较大的类文件,但Java对枚举类大小没有硬性限制,只要编译环境内存足够即可。
- 若需要更新枚举内容,只需修改CSV文件,重新构建项目即可自动更新枚举类。
内容的提问来源于stack exchange,提问作者Apage
相关产品推荐
相关产品推荐

