如何处理带有CSV输出映射的对象



我有一组下面的对象,我需要将它们写入CSV:

public class OutputObject {
private String userId;
private Map<String, Object> behaviour;
}

上面的集合可以有一个具有两个、三个或四个值的映射。

[
OutputObject1 [userId=11, behaviours={color=white, size=S, owner=Mr. A}], 
OutputObject2 [userId=22, behaviours={color=black, isNew=true}],
OutputObject3 [userId=33, behaviours={color=green, size=L}]
]

所需CSV输出:

userId, color, size, owner, isNew
11,     white,  S,   Mr. A,
22,     black,   ,        , true
33,     green,  L,        ,

我从下面的片段开始打印:

// Set<OutputObject> outputObjectSet already received.
JSONArray jsonArrayObject = new JSONArray(outputObjectSet);
String csvValue = CDL.toString(jsonArrayObject);
FileWriter fileWriter = new FileWriter(fileObject, true);
fileWriter.write(csvValue);
fileWriter.close();

但上面是创建一个两列csv,带有userId行为打印所有地图对象

的行为由于集合中可能包含大量这样的对象,如何才能有效地做到这一点。

使用JSONArray在这里似乎是多余的,您可以实现一个助手方法,将OutputObject序列化为CSV字符串,同时考虑到需要维护列的顺序:

public class CSVSerializer {
public static String transform(OutputObject obj) {
String[] fields = {"color", "size", "owner", "isNew"};
return Stream.concat(
Stream.of(obj.getUserId()), 
Arrays.stream(fields)
.map(f -> obj.getBehaviour().get(f))
.map(v -> v == null ? "" : v.toString()) 
)
.collect(Collectors.joining(","));
}
}

String csv = outputObjectSet.stream()
.map(CSVSerializer::transform)
.collect(Collectors.joining("n"));
// print csv contents

由于Java的HashMapArrays.sort()实现非常快,因此即使使用更多的对象,这也应该非常高效。请注意,此实现依赖于Apache的common-text-库来转义内容。

private static void outputCSV(List<OutputObject> objects, PrintStream output) {
AtomicInteger highestBehaviourIndex = new AtomicInteger();
HashMap<String, Integer> behaviourIndexMap = new HashMap<>();
// Give every behaviour an index
for (OutputObject object : objects) {
object.getBehaviour().forEach((name, value) -> behaviourIndexMap.computeIfAbsent(name, (unused) -> highestBehaviourIndex.getAndIncrement()));
}
String[] behaviours = new String[highestBehaviourIndex.get()];
behaviourIndexMap.forEach((name, index) -> {
behaviours[index] = name;
});
output.println("userId, " + String.join(", ", behaviours));
// Sort by ID
objects.sort(Comparator.comparingInt(OutputObject::getUserId));
for (OutputObject object : objects) {
// Print line
StringJoiner joiner = new StringJoiner(", ");

for (String behaviour : behaviours) {
joiner.add(StringEscapeUtils.escapeCsv(object.getBehaviour().getOrDefault(behaviour, "").toString()));
}

output.println(object.getUserId() + ", " + joiner.toString());
}
}

最新更新