How can I pass a type T to a method and have it infer the type?

chrips :

Below you can see the repetition going on in my DataCsvLoader.

I've got a method getCsvAsMap which isnt in use. All the T are red because obviously while it might be getting a Map ... compiler doesnt know how to get that T type out of there...Is there a way to pass it?

Is the only way to create another class as a handler.. specifically for the getCsvAsMap method?

Sincrerely, Tricky4me

DataCsvLoader:

//
// Read and cache CSVs
//

public Map<Integer, CourseEntity> getAllCourses() {
    String csvPath = "courses.csv";
    // Create a new course Map with the right Entity type
    Map<Integer, CourseEntity> entityMap = new HashMap<>();
    repositoryInMem.put(csvPath, entityMap);
    // Get data from CSV
    EntityLoader<CourseEntity> entityLoader = new EntityLoader<>();
    entityMap = entityLoader.readCsv(csvPath);
    return entityMap;
}

public Map<Integer, StudentEntity> getAllStudents() {
    String csvPath = "students.csv";
    // Create a new course Map with the right Entity type
    Map<Integer, StudentEntity> entityMap = new HashMap<>();
    repositoryInMem.put(csvPath, entityMap);
    // Get data from CSV
    EntityLoader<StudentEntity> entityLoader = new EntityLoader<>();
    entityMap = entityLoader.readCsv(csvPath);
    return entityMap;
}

public Map<Integer, TestEntity> getAllTests() {
    String csvPath = "tests.csv";
    // Create a new course Map with the right Entity type
    Map<Integer, TestEntity> entityMap = new HashMap<>();
    repositoryInMem.put(csvPath, entityMap);
    // Get data from CSV
    EntityLoader<TestEntity> entityLoader = new EntityLoader<>();
    entityMap = entityLoader.readCsv(csvPath);
    return entityMap;
}

public Map<Integer, MarkEntity> getAllMarks() {
    String csvPath = "marks.csv";
    // Create a new course Map with the right Entity type
    Map<Integer, MarkEntity> entityMap = new HashMap<>();
    repositoryInMem.put(csvPath, entityMap);
    // Get data from CSV
    EntityLoader<MarkEntity> entityLoader = new EntityLoader<>();
    entityMap = entityLoader.readCsv(csvPath);
    return entityMap;
}


public Map<Integer, T> getCsvAsMap(String fileName, Map<Integer, T> entityMap){
    // Add the Entity map to the repository in Mem
    // The key to each entity map is just it's filename
    repositoryInMem.put(fileName, entityMap);
    // Get data from CSV
    EntityLoader<T> entityLoader = new EntityLoader<T>();
    entityMap = entityLoader.readCsv(fileName);
    return entityMap;
}

EntityLoader:

public class EntityLoader<T> {
    public Map<Integer, T> readCsv(String csvFile){
        Map<Integer, T> table = new HashMap<>(); // Fits entire CSV table
        int rowCount=0;
        try {
            String row;
            BufferedReader csvReader = new BufferedReader(new FileReader(csvFile));
            while ((row = csvReader.readLine()) != null) {
                String[] data = row.split(",");
                table.put(rowCount++, Arrays.asList(data));
            }
            csvReader.close();
        }catch (FileNotFoundException e){
            System.err.println("No file with name " +  csvFile +
                    "Are the CSV files in the root folder? Ex: ReportCard\\courses.csv");
        }catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }
}
Kalesh Kaladharan :

Looks like you are not doing things the Object Oriented way. Classes that has similar properties should use abstraction.

Follow the given steps to solve the issue.

  1. Create an interface IEntity and implement the same on all entities. For example, MarkEntity can be defined as
public class MarkEntity implements IEntity {
// class implementation
}
  1. Change the getCsvAsMap() to the following
public Map<Integer, IEntity> getCsvAsMap(String fileName, Map<Integer, IEntity> entityMap){
}
  1. Change the EntityLoader class to
public class EntityLoader<T extends IEntity> {
// Class implementation
}

That should do.

Edit

If abstraction is not possible, as entities don't share any features, or if the getCsvMap() should return the same return type as the second argument, then the following replacement should work just fine.

public <T> Map<Integer, T> getCsvAsMap(String fileName, Map<Integer, T> entityMap)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=329708&siteId=1