提问者:小点点

从CSV文件生成枚举


我的目标是生成一个枚举以创建一个EnumSet。如果我编写枚举,这部分就可以工作。我不想编写50000行的枚举,而是想CSV导入50000行。当我尝试用CSV导入替换我编写的枚举时,麻烦就开始了。

package VilleEnumSet;

public class VilleEnumSet {
    
    
    //ENUM SANS CSV
    enum Ville {
        Paris("FR", "75000", "Paris", "Ile de France", "Paris", "75", "Paris", "751", "48.8534", "2.3488"),
        Lyon("FR", "69000", "Lyon", "Auvergne-Rhone-Alpes", "Rhone", "69", "Lyon", "691", "45.7485", "4.8467"),
        Marseille("FR", "13000", "Marseille", "Provence-Alpes-Cote d'Azure", "Bouches-du-Rhone", "13", "Marseille", "133", "43.2969", "5.3811"),
        Montpellier("FR", "34000", "Montpellier", "Occitanie", "Herault", "34", "Montpellier", "343", "43.6109", "3.8764");
    
        
    //ATTRIBUTS
    private final String pays;
    private final String codePostal;
    private final String nom;
    private final String region;
    private final String departement;
    private final String numDepartement;
    private final String prefecture;
    private final String codeCommune;
    private final String latitude;
    private final String longitude;
    
    

    //CONSTRUCTEUR
    private Ville(String pays, String codePostal, String nom, String region, String departement, String numDepartement,
            String prefecture, String codeCommune, String latitude, String longitude) {
        this.pays = pays;
        this.codePostal = codePostal;
        this.nom = nom;
        this.region = region;
        this.departement = departement;
        this.numDepartement = numDepartement;
        this.prefecture = prefecture;
        this.codeCommune = codeCommune;
        this.latitude = latitude;
        this.longitude = longitude;
    }

    
    //GETTERS
    public String getPays() {
        return pays;
    }

    public String getCodePostal() {
        return codePostal;
    }

    public String getNom() {
        return nom;
    }

    public String getRegion() {
        return region;
    }

    public String getDepartement() {
        return departement;
    }

    public String getNumDeprtement() {
        return numDepartement;
    }

    public String getPrefecture() {
        return prefecture;
    }

    public String getCodeCommune() {
        return codeCommune;
    }

    public String getLatitude() {
        return latitude;
    }

    public String getLongitude() {
        return longitude;
    }
    
    
    //TOSTRING
    public String toString() {
        return String.format("%-40s%-10s\n", "Pays: " + pays, "Code Postal: " + codePostal) 
                + String.format("%-40s%-10s\n", "Nom: " + nom, "Region: " + region) 
                + String.format("%-40s%-10s\n", "Departement: " + departement, "Num Departement: " + numDepartement)
                + String.format("%-40s%-10s\n", "Prefecture: " + prefecture, "Code Commune: " + codeCommune)
                + String.format("%-40s%-10s\n\n", "Latitude: " + latitude, "Longitude: " + longitude);
    }
    }

}
package VilleEnumSet;

import java.util.EnumSet;
import java.util.Iterator;

import VilleEnumSet.VilleEnumSet.Ville;

public class MainVilleEnumSet {
    
public static void main(String[] args) {
        
        // Creating an EnumSet using allOf()
        EnumSet<Ville> villes = EnumSet.allOf(Ville.class);
        
        // Creating an iterator on games
        Iterator<Ville> iterate = villes.iterator();
        
        // Message
        System.out.println("EnumSet: " + "\n");
        
        while (iterate.hasNext()) {
            System.out.println(iterate.next());
        }
    }

}

我的代码返回这个:

EnumSet: 

Pays: FR                                Code Postal: 75000
Nom: Paris                              Region: Ile de France
Departement: Paris                      Num Departement: 75
Prefecture: Paris                       Code Commune: 751
Latitude: 48.8534                       Longitude: 2.3488


Pays: FR                                Code Postal: 69000
Nom: Lyon                               Region: Auvergne-Rhone-Alpes
Departement: Rhone                      Num Departement: 69
Prefecture: Lyon                        Code Commune: 691
Latitude: 45.7485                       Longitude: 4.8467

对于CSV结构,每一列对应于类"VilleEnumSet"中的一个属性。

我不知道该怎么办。我已经寻求帮助,但许多人建议切换到我不想做的列表。


共2个答案

匿名用户

枚举旨在表示编译时已知的一小组值。这些值的名称旨在在您的源代码中使用,如Bill K的正确答案中所述。

那不符合你的情况。

您在运行时加载了大量值。表示这些值是自定义类的目的。对自定义类的对象进行分组是Java集合框架的目的,其中包含列表、集合、队列、映射等。

如果您的自定义类的主要目的是透明且不可变地通信数据,请将您的类定义为记录。编译器隐式创建构造函数getter,equals

record Ville (String pays, String codePostal, String nom, String region, String departement, String numDepartement, String prefecture, String codeCommune, String latitude, String longitude) {}

顺便说一下,从Java16开始,记录可以在方法中本地定义,也可以嵌套在类中,或者单独定义。(枚举和接口也是如此。)

当您的CSV库导入每一行输入时,实例化记录类的一个对象。添加到集合对象,可能是List的实现。在实现可比较接口后,您可以选择使用NavigableSet/SortedSet

如果您的输入在运行时发生变化,您可以根据另一个数据导入将对象集合替换为新对象。使用枚举,您可以尝试任何成员字段的值,但不能添加或删除命名的枚举对象。

匿名用户

虽然您绝对不会为此使用枚举,但实际上有一个有效的用例,所以如果其他人来这里,这是值得回答的。

对您的问题的实际直接回答是,您希望以渐进方式生成枚举的代码。一种方法(错误的方法)是编写一个预编译器来手动构建文件,方法是将类的开头作为常量字符串发出,将csv文件中每组数据的重复行发出,然后将类的结尾作为另一个常量字符串发出。在启动实际的java编译器之前,您的buildfile会调用这个预编译器。

这是有问题的-它将需要一个预编译步骤,并且可能不会与您的IDE集成。

更正确的方法是创建注释处理器。可以在编译代码之前处理注释,并允许您将任意代码插入文件中。

如果您的注释在枚举中,您的注释处理器可以发出如下行:

Paris("FR", "75000", "Paris", "Ile de France", "Paris", "75", "Paris", "751", "48.8534", "2.3488"),

文件的其余部分将是一个实际的java类文件,其中包含一个注释,该注释会导致调用处理器。

注释处理器通过命令行开关传递给java编译器,如“javac-处理器(fullClassName)”。

这样做的好处是,你可以告诉IDE这是一个注释处理器,它将确保在你的CSV文件中添加一条记录使枚举立即可用。它还可以防止生成临时源文件(当人们试图手动编辑它们时,这些几乎总是会带来麻烦)