Можно ли создать конвертер csv в объект, используя java generics

Я создал простой конвертер, который берет String fileName и преобразует строки из файла .csv в List<Cat>. Проблема, с которой я столкнулся сейчас, заключается в том, что теперь есть Dog, и мне не разрешено копировать и вставлять метод, чтобы просто изменить тип возвращаемого значения на List<Dog>.

Я пытался использовать возвращаемый тип List<Object>, чтобы попытаться разобрать его на Cat или Dog после преобразования, но он мне не позволяет. Я ищу общее решение этой проблемы, если это возможно.

Что я пробовал:

@Data
@Entity
@Table(name = "cat")
public class Cat implements Serializable {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(columnDefinition = "int(10)", nullable = false)
    int id;

    @Column(columnDefinition = "varchar(20)", nullable = false)
    String name;    
}

@Data
@Entity
@Table(name = "dog")
public class Dog implements Serializable {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(columnDefinition = "int(10)", nullable = false)
    int id;

    @Column(columnDefinition = "varchar(20)", nullable = false)
    String name;    
}

public List<Object> convertToObject(String fileName, String object) {
    List<Object> objList = new ArrayList();
    Path pathToFile = Paths.get(fileName);

    try (BufferedReader br = Files.newBufferedReader(pathToFile)) {
        int index = 1;

        // read the first line from the text file
        String line = br.readLine();

        // loop until all lines are read
        while (line != null) {

            if (index > 1) {
                switch (object) {
                    case "cat" : {
                        // use string.split to load a string array with the values from
                        // each line of
                        // the file, using a comma (,) as the delimiter
                        String[] attributes = line.split(",");

                        Cat cat = new Cat();

                        createCat(attributes, cat);

                        // adding Cat into ArrayList
                        objList.add(cat);   
                    }

                    case "dog" : {
                        // use string.split to load a string array with the values from
                        // each line of
                        // the file, using a comma (,) as the delimiter
                        String[] attributes = line.split(",");

                        Dog dog = new Dog();

                        createDog(attributes, dog);

                        // adding Dog into ArrayList
                        objList.add(dog);   
                    }
                }
            }

            // read next line before looping
            // if end of file reached, line would be null
            line = br.readLine();

            index++;
        }

    } catch (IOException ex) {
        ex.printStackTrace(System.out);
    }

    return objList;
}

Я пытался использовать тип возвращаемого значения List<Object>, чтобы попытаться проанализировать его в Cat или Dog после преобразования, но это не позволит мне. Что именно происходит, не компилируется?

Vitaly Chura 05.11.2022 12:53

@VitalyChura Кажется, что можно добавить Cat или Dog в List<Object>, но впоследствии его нельзя проанализировать в List<Dog>. «Объект не может быть преобразован в собаку».

dbuergi 07.11.2022 10:46
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать Java Generics

Создайте класс утилиты CSV.

public class CsvUtils<T> {

    public List<T> read(final String fileName, final String object) throws IOException {
        
        // put your logic here to read the csv file (convertToObject method)
      
    }

}

Затем вы можете просто использовать его следующим образом:

    public void doSomeStuffWithMyDogs() throws IOException {
         
         CsvUtils<Dog> csvUtils = new CsvUtils<>();
         List<Dog> myDogs = csvUtils.read("MyDogs_V1.csv", "dog");
      
         // do something else

    }

    public void doSomeStuffWithMyCats(final String fileName) throws IOException {
        
         CsvUtils<Cat> csvUtils = new CsvUtils<>();
         List<Cat> myCats = csvUtils.read("MyCats_V1.csv", "cat");
      
         // do something else

    }

Моё мнение:
Мне не нравится ваша реализация convertToObject:
1.

//Why are you creating a new instance of Cat here?
Cat cat = new Cat();

// This method is called createCat...
// Why did you pass an instance of Cat? this will update the cat, not create a new cat.
// It is also supposed to return the cat created.
createCat(attributes, cat);

objList.add(cat);

Метод createCat может возвращать объект Cat, а нового кота можно создать внутри метода, поэтому вы можете удалить его из параметра.

тогда вы можете написать:

Cat cat = createCat(attributes);
objList.add(cat);

или в одну строку:

objList.add(createCat(attributes));

2.
если в следующем месяце вы добавите лошадь в проект, вам нужно будет изменить реализацию, добавив регистр переключения «лошадь», а также вам необходимо реализовать новый метод createHorse (атрибуты String [], объект String).

Представьте, если в следующем году в вашем проекте нужно будет обрабатывать всех животных, вы сойдете с ума.

Вам нужно максимально абстрагироваться, чтобы избежать этой проблемы. Вам вовсе не обязательно реализовывать алгоритм самостоятельно. Существует множество библиотек, которые преобразуют файл CSV в объект Java.

Например: (Apache Commons CSV, OpenCSV, парсер CSV SimpleFlatMapper, jackson-dataformat-csv, uniVocity-parsers, deephaven-csv), но есть и многие другие!

Документация для дженериков:

Другие вопросы по теме