繁体   English   中英

如何将表格转换为地图

[英]How to convert a table to a map of maps

我有一个看起来像这样的CSV文件:

request.car.model (STRING),request.car.make (STRING),request.person.lastname (STRING),other.person.birthdate (DATE),other.person.length (INTEGER)
BMW,7 series,Doe,31/12/1980,170
Tesla,Model S,Smith,1/1/1975,172
Volvo,C40,Johnson,13/11/1982,189

第一行是标头,其类型在括号之间进行解析。 标头使用点表示法,非常类似于Javascript解析复杂的对象。

我需要为CSV文件中的每一行创建一个Java Map<String, Serializable> 例如,第一行需要生成一张Java中的map如下所示:

Map<String, Serializable> requestCarMap = new HashMap<>();
requestCarMap.put("make", "BMW");
requestCarMap.put("model", "7 series");
Map<String, Serializable> requestPersonMap = new HashMap<>();
requestPersonMap.put("lastName", "Doe");
Map<String, Serializable> requestMap = new HashMap<>();
requestMap.put("car", (HashMap) requestCarMap);
requestMap.put("pesron", (HashMap) requestPersonMap);
Map<String, Serializable> otherPersonMap = new HashMap<>();
otherPersonMap.put("birthdate", new Date(1980,12,31));
Map<String, Serializable> otherMap = new HashMap<>();
otherMap.put("person", (HashMap) otherPersonMap);
Map<String, Serializable> map = new HashMap<>();
map.put("request", (HashMap) requestMap);
map.put("other", (HashMap) otherMap);

我目前有一种基于值创建地图的方法,但是,不拆分标题并将其放在SubMaps中:

protected static Map<String, Serializable> parseRecord(CSVRecord record, CSVRecord header) {
    final Map<String, Serializable> map = new HashMap<>();
    for (int i = 0; i < record.size(); i++) {
        String headerField = getHeader(header.get(i));
        String[] headerFieldPart = headerField.split("\\.");
        String headerFieldType = getHeaderFieldType(header.get(i));
        Object recordField = getRecordField(headerFieldType, record.get(i));
        if (recordField != null) {
            map.put(headerField, (Serializable) recordField);
        } else {
            log.warn("Skipped value for record item: "
                    + record.get(i));
        }
    }
    return map;
}

如何以通用方式将值放在示例中的subMap中? 我不知道这些列的名称,也不知道这些地图的嵌套深度。 我只是无法弄清楚在subMap不存在,存在等情况下可以使用的逻辑。有什么聪明的解决方案? 有什么库可以帮助我解决这个问题?

基本上,将标头拆分成点,然后遍历各个部分,然后根据相关部分切换目标地图指针。

像这样(假设您将CSV内容记下来):

public static void main(String[] args) {
    String[] headers = { "request.car.model", "request.car.make", "request.buyer" }; 
    String[] values = { "a", "b", "c" };

    Map<String, Serializable> outer = new HashMap<>();

    for(int i = 0; i < headers.length; i++) {
        String header = headers[i];
        String value  = values[i];

        String[] parts = header.split("\\.");
        Map<String, Serializable> targetMap = outer;
        for(int j = 0; j < parts.length - 1; j++)
            targetMap = (Map<String, Serializable>) targetMap.computeIfAbsent(parts[j], x -> new HashMap<>());
        targetMap.put(parts[parts.length - 1], value);
    }

    System.out.println(outer.get("request"));
}

注意,这仅在标头一致的情况下才有效,即不存在诸如“ aa”的值后跟“ aab”的值之类的东西。

作为参考,下面是完整的方法:

protected static Map<String, Serializable> parseRecord(CSVRecord record, CSVRecord fullHeader) {
    if (record == null) {
        log.warn("Record is null.");
        return null;
    }
    log.info("Parsing record number: " + (record.getRecordNumber() - 1));
    log.debug(" with content: " + record.toString());
    final Map<String, Serializable> map = new HashMap<>();
    for (int i = 0; i < record.size(); i++) {
        String headerFieldType = getHeaderFieldType(fullHeader.get(i));
        Object recordField = getRecordField(headerFieldType, record.get(i));
        if (recordField != null) {
            String headerField = getHeaderField(fullHeader.get(i));
            String[] headerFieldPart = headerField.split("\\.");
            Map<String, Serializable> targetMap = map;
            for (int j = 0; j < headerFieldPart.length - 1; j++) {
                targetMap = (Map<String, Serializable>) targetMap.computeIfAbsent(headerFieldPart[j], x -> new HashMap<>());
            }
            targetMap.put(headerFieldPart[headerFieldPart.length - 1], (Serializable) recordField);
        } else {
            log.warn("Skipped value for record item: "
                    + record.get(i));
        }
    }
    log.debug("Parsed map: " + map);
    return map;
}

以及生成的日志:

INFO Parsing record number: 1
DEBUG  with content: CSVRecord [comment=null, mapping=null, recordNumber=2, values=[BMW, 7 series, Doe, 31/12/1980, 170]]
INFO Parsed map: {request={car={model=BMW, make=7 series}, person={lastname=Doe}}, other={person={birthdate=Thu Jan 31 00:12:00 CET 1980, length=170}}}
INFO Parsing record number: 2
DEBUG  with content: CSVRecord [comment=null, mapping=null, recordNumber=3, values=[Tesla, Model S, Smith, 1/1/1975, 172]]
INFO Parsed map: {request={car={model=Tesla, make=Model S}, person={lastname=Smith}}, other={person={birthdate=Wed Jan 01 00:01:00 CET 1975, length=172}}}
INFO Parsing record number: 3
DEBUG  with content: CSVRecord [comment=null, mapping=null, recordNumber=4, values=[Volvo, C40, Johnson, 13/11/1982, 189]]
INFO Parsed map: {request={car={model=Volvo, make=C40}, person={lastname=Johnson}}, other={person={birthdate=Wed Jan 13 00:11:00 CET 1982, length=189}}}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM