Search code examples
javacsvenumsopencsvenumset

Generate enum from CSV file


My goal is to to generate an enum in order to create an EnumSet. This part works if I write the enum. Instead of writing an enum of 50000 lines, I would like to import the 50000 rows CSV. The trouble starts when I try to replace the enum I wrote by the the CSV import.

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());
        }
    }

}

my code returns this:

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

For the CSV structure, each column corresponds to an attribute in the class "VilleEnumSet".

I have no idea what to do. I've looked for help, but many suggest to switch to list which I don't want to.


Solution

  • Enum not appropriate to your needs

    An enum is meant to represent a small set of values known at compile-time. The names of these values are meant to be used within your source code, as discussed in the correct Answer by Bill K.

    That does not match your situation.

    You have a large number of values loaded at runtime. Representing such values is the purpose of a custom class. Grouping objects of your custom class is the purpose of the Java Collections Framework with lists, sets, queues, maps, and such.

    record

    If the main purpose of your custom class is to communicate data transparently and immutably, define your class as a record. The compiler implicitly creates the constructor, getters, equals & hashCode, and toString.

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

    By the way, know that as of Java 16 a record can be defined locally within a method, or nested within a class, or separately. (Ditto for enums and interfaces.)

    As your CSV library imports each row of input, instantiate an object of your record class. Add to a collection object, likely an implementation of List. You may choose to instead use a NavigableSet/SortedSet after implementing the Comparable interface. In Java 21+, see SequencedSet.

    If your inputs were to change during runtime, you can replace the collection of objects with fresh ones based on another data import. With enums, you can change the value of any member fields, but you cannot add or remove the named enum objects at runtime.