java - 在 Java 中将 Enum 转为类

标签 java

我有一个类,其中声明了一个枚举,如下所示:

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/

相关文章:

java - 用Java读取XML文件

java - 位图()不公开

java - 如何从 ReflectionDBObject 中获取正确类型的列表

java - 从 Livelink 导出数据

java.lang.IllegalStateException : Pool has been closed

java.net.SocketException : Socket is closed TCP Connection

java - 从 json 转换为 vector 后,元素未从 vector 中删除

java - 如何解决 sun.security.provider.certpath.SunCertPathBuilderException?

java - 需要开发基于图形的模拟引擎的建议

java - 如何在 Eclipse 中找到抽象方法的实现位置?