Taka sytuacja:
Mam 2 klasy odpowiedzialne za wczytywanie słowników z csv.
1 klasa pobiera 2 kolumny z csv i zapisuje jako Map<String, String>
.
2 klasa pobiera 2 kolumny z csv i zapisuje jako Map<String, Double>
.
Co zrobić by nie dublować kodu? Ano zrobić klasę bardziej ogólną odpowiedzialną za tworzenie Map
z csv. No to robię:
package Main;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.function.Function;
public interface MapFromCsv<T1, T2> {
public default Map<T1, T2> getMap(String FILE_TO_LOAD){
Map<T1, T2> mapResult = new HashMap<>();
File f = new File(FILE_TO_LOAD);
try (Scanner sc = new Scanner(f)) {
while (sc.hasNextLine()) {
String tmp = sc.nextLine();
String[] tmp2 = tmp.split(";");
mapResult.put((T1) tmp2[0], (T2) tmp2[1]);
}
} catch (FileNotFoundException fntf) {
System.err.println("File " + f.getPath() + "was not found.");
} catch (Exception e) {
System.err.println("Something went wrong with reading " + f.getPath());
}
return mapResult;
}
}
klasa1:
package Main;
import java.util.Map;
public enum AreaMapFromCsv implements MapFromCsv<String, String> {
INSTANCE;
final String FILE_TO_LOAD = "resources/areaMap.csv";
private Map<String, String> areaMap;
private AreaMapFromCsv() {
initAreaMap();
}
private void initAreaMap() {
this.areaMap = getMap(FILE_TO_LOAD);
}
public void reloadAreaMap() {
initAreaMap();
}
public Map<String, String> getAreaMap() {
return areaMap;
}
}
klasa2:
package Main;
import java.util.Map;
public enum CurrencyMapFromCsv implements MapFromCsv<String, Double>{
INSTANCE;
final String FILE_TO_LOAD = "resources/currencyMap.csv";
private Map<String, Double> currencyMap;
private CurrencyMapFromCsv() {
initCurrency();
}
private void initCurrency() {
this.currencyMap = getMap(FILE_TO_LOAD);
}
public void reloadCurrency() {
initCurrency();
}
public Map<String, Double> getCurrencyMap() {
return currencyMap;
}
}
Tylko teraz jest problem taki o, że klasa MapToCsv
nie wie jak zamienić Stringa na doubla i wywala się na castowaniu. Postanowiłem mu wlepić funkcje, ale mi nie działa:
package Main;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.function.Function;
public interface MapFromCsv<T1, T2> {
public default Map<T1, T2> getMap(String FILE_TO_LOAD, Function<String, T1> foo1, Function<String, T2> foo2){
Map<T1, T2> mapResult = new HashMap<>();
File f = new File(FILE_TO_LOAD);
try (Scanner sc = new Scanner(f)) {
while (sc.hasNextLine()) {
String tmp = sc.nextLine();
String[] tmp2 = tmp.split(";");
mapResult.put((T1) foo1.apply(tmp2[0]), (T2) foo2.apply(tmp2[1]));
}
} catch (FileNotFoundException fntf) {
System.err.println("File " + f.getPath() + "was not found.");
} catch (Exception e) {
System.err.println("Something went wrong with reading " + f.getPath());
}
return mapResult;
}
}
i wtedy bym w klasie1 przekazał jako 2 funkcje: String::toString
, a w klasie2: String::toString
i Double::parseDouble
.
EDIT: jednak działa. :O Jak to bardziej przejrzyście zrobić?