我有一个类,其中声明了一个枚举,如下所示:
private enum Marker {
NONE {
@Override
public String[] createResultLine(String columnName, String value, String[] buf) {
return null;
}
},
STRING {
@Override
public String[] createResultLine(String columnName, String value, String[] buf) {
buf[COLUMN_VALUE_STRING] = value;
buf[COLUMN_VALUE_FLOAT] = "";
buf[COLUMN_NAME] = columnName;
buf[BLOCK_ID] = blockId;
buf[PIPELINE_ID] = pipelineId;
return buf;
}
},
FLOAT {
@Override
public String[] createResultLine(String columnName, String value, String[] buf) {
buf[COLUMN_VALUE_STRING] = "";
buf[COLUMN_VALUE_FLOAT] = value;
buf[COLUMN_NAME] = columnName;
buf[BLOCK_ID] = blockId;
buf[PIPELINE_ID] = pipelineId;
return buf;
}
};
public abstract String[] createResultLine(String columnName, String value, String[] buf);
}
这是完整的类和用法
final class CSVDataModifier {
private final Path src;
private int rowNumber = 0;
private static String blockId = "" ;
private static String pipelineId = "" ;
private static String ElasticHostURL = "";
public CSVDataModifier(Path src, /*Path dest, */ String b_id, String p_id, String elasticUrl) {
this.src = src;
this.blockId = b_id;
this.pipelineId = p_id;
this.ElasticHostURL = elasticUrl;
}
private static final int ROW_NUMBER = 0;
private static final int COLUMN_NAME = 1;
private static final int COLUMN_VALUE_STRING = 2;
private static final int COLUMN_VALUE_FLOAT = 3;
private static final int BLOCK_ID = 4;
private static final int PIPELINE_ID = 5;
private static final String[] COLUMN_NAMES = { "row_number", "column_name", "column_value_string", "column_value_float", "blockId", "pipelineId" };
private ExecutorService executorService = Executors.newFixedThreadPool( 100 );
public void apply() throws IOException, InterruptedException {
try (CSVReader reader = new CSVReader(new FileReader(src.toFile())))
{
List<String[]> csvLines = new ArrayList<>();
// key - ordered list of columns in source file
Map<String, Marker> columnNameFloatMarker = getSourceColumnNamesWithFloatMarker(reader.readNext());
int posRowNumber = getRowNumberPosition(columnNameFloatMarker.keySet());
if (columnNameFloatMarker.isEmpty()) {
System.out.println( "empty!" );
return;
}
String[] buf = new String[COLUMN_NAMES.length];
reader.forEach(values -> {
buf[ROW_NUMBER] = values[posRowNumber];
int col = 0;
String[] resultLine;
for (Map.Entry<String, Marker> entry : columnNameFloatMarker.entrySet()) {
String columnName = entry.getKey();
Marker marker = entry.getValue();
if ((resultLine = marker.createResultLine(columnName, values[col], buf)) != null) {
// writer.writeNext( resultLine );
csvLines.add( resultLine );
rowNumber++;
}
col++;
}
if (csvLines.size() >= 75)
{
List<String[]> tmp = new ArrayList<>( );
tmp.addAll( csvLines );
csvLines.clear();
executorService.execute(new BulkThread(ElasticHostURL, new ArrayList<>( tmp )));
}
});
if (csvLines.size() > 0) {
List<String[]> tmp = new ArrayList<>( );
tmp.addAll( csvLines );
csvLines.clear();
executorService.execute(new BulkThread(ElasticHostURL, new ArrayList<>( tmp )));
}
}
executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
System.out.println( "Total Lines: " + rowNumber );
}
private static final String FLOAT = "_float";
private static final String STRING = "_string";
private enum Marker {
NONE {
@Override
public String[] createResultLine(String columnName, String value, String[] buf) {
return null;
}
},
STRING {
@Override
public String[] createResultLine(String columnName, String value, String[] buf) {
buf[COLUMN_VALUE_STRING] = value;
buf[COLUMN_VALUE_FLOAT] = "";
buf[COLUMN_NAME] = columnName;
buf[BLOCK_ID] = blockId;
buf[PIPELINE_ID] = pipelineId;
return buf;
}
},
FLOAT {
@Override
public String[] createResultLine(String columnName, String value, String[] buf) {
buf[COLUMN_VALUE_STRING] = "";
buf[COLUMN_VALUE_FLOAT] = value;
buf[COLUMN_NAME] = columnName;
buf[BLOCK_ID] = blockId;
buf[PIPELINE_ID] = pipelineId;
return buf;
}
};
public abstract String[] createResultLine(String columnName, String value, String[] buf);
}
// Source column pre-processing to avoid string comparision;
private static Map<String, Marker> getSourceColumnNamesWithFloatMarker(String... columns) {
if (columns == null || columns.length == 0)
return Collections.emptyMap();
Map<String, Marker> map = new LinkedHashMap<>();
for (int i = 0; i < columns.length; i++) {
String columnName = columns[i];
Marker marker = Marker.NONE;
if (columnName.endsWith(FLOAT)) {
columnName = columnName.substring(0, columnName.length() - FLOAT.length());
marker = Marker.FLOAT;
} else if (columnName.endsWith(STRING)) {
columnName = columnName.substring(0, columnName.length() - STRING.length());
marker = Marker.STRING;
}
if (map.put(columnName, marker) != null)
throw new IllegalArgumentException("Column duplication in the source file");
}
return map;
}
private static int getRowNumberPosition(Set<String> columnNames) {
int i = 0;
for (String columnName : columnNames) {
if ("row_number".equals(columnName))
return i;
i++;
}
throw new IllegalArgumentException("Source file does not contain 'row_number' column");
}
}
问题在于私有(private)成员
private static String blockId = "" ;
private static String pipelineId = "" ;
如果它们不是静态的,并且它们正在构造函数中初始化,则不能在私有(private)枚举标记
中引用
public CSVDataModifier(Path src, /*Path dest, */ String b_id, String p_id, String elasticUrl) {
this.src = src;
this.blockId = b_id;
this.pipelineId = p_id;
this.ElasticHostURL = elasticUrl;
}
我可以看到,将私有(private)成员声明为非静态的唯一方法是将私有(private)枚举标记
转换为内部类或其他东西。
由于我是 Java 和 OOP 世界的新手,我可以获得任何指导来解决此问题吗?
最佳答案
这段代码非常核心,需要大量重构,因为它违反了大多数编程原则
您问题的答案是将这些字段提取到另一个类(例如 ModifierSetup
),并将其作为参数提供给 createResultLine
public class ModifierSetup {
private String pipelineId;
private String ElasticHostURL;
// all args constructor
}
// inside your CSVDataModifier
private ModifierSetup setup;
public CSVDataModifier(Path src, /*Path dest, */ String b_id, String p_id, String elasticUrl) {
this.src = src;
this.blockId = b_id;
this.setup = new ModifierSetup(p_id, elasticUrl);
}
// ...
if ((resultLine = marker.createResultLine(columnName, values[col], buf, this.setup)) != null) {
// ...
public abstract String[] createResultLine(String columnName, String value, String[] buf, ModifierSetup modifierSetup);
但这绝对还不够。您的许多字段应该像这样提取。您应该提供一些通用接口(interface),而不是奇怪的“单例”枚举实现,例如
public interface ResultLineCreator {
ResultData createResultLine(ColumnMetaData columnMetaData, ModifierSetup modifierSetup, ResultData result); // in ColumnMetaData you can encapsulate columnName and value, inside ResultData result data
}
以及它的正确本地实现,读者应该被某种供应商等包裹着 - 只要想想这个类有多少责任 - 即使你会解决你的问题它也不会'工作/可维护/可测试/清晰
关于java - 在 Java 中将 Enum 转为类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57795179/