ObjectMapper 按行分批次写入百万数据示例

ObjectMapper 按行分批次写入百万数据示例

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    public void test() throws IOException {
        try (JsonGenerator jsonGenerator = objectMapper.getFactory()
                .createGenerator(new File("target/example.json"), JsonEncoding.UTF8)
                .setPrettyPrinter(new MinimalPrettyPrinter() {
                    private static final long serialVersionUID = -2508021383479113398L;

                    @Override
                    public void writeStartObject(JsonGenerator g) throws IOException {
                        g.writeRaw(System.lineSeparator());
                        super.writeStartObject(g);
                    }

                    @Override
                    public void writeEndArray(JsonGenerator g, int nrOfValues) throws IOException {
                        g.writeRaw(System.lineSeparator());
                        super.writeEndArray(g, nrOfValues);
                    }
                })) {
            jsonGenerator.writeStartArray();
            Example example = new Example();
            // 此处演示,限制总条数 10 条
            for (int i = 1; i <= 10; i++) {
                example.setId(i);
                example.setName("name" + i);
                objectMapper.writeValue(jsonGenerator, example);

                if (i % 2 == 0) {
                    jsonGenerator.flush();
                }
            }
        }
    }

效果如下:

[
{"id":1,"name":"name1"},
{"id":2,"name":"name2"},
{"id":3,"name":"name3"},
{"id":4,"name":"name4"},
{"id":5,"name":"name5"},
{"id":6,"name":"name6"},
{"id":7,"name":"name7"},
{"id":8,"name":"name8"},
{"id":9,"name":"name9"},
{"id":10,"name":"name10"}
]

其本质就是在每写入一个对象前自动换行,否则,所有数据都会堆积在一行上,不太美观,当然,这需要牺牲点容量!

使用 SequenceWriter 优化,如下:

    @Test
    public void test() throws IOException {
        try (JsonGenerator jsonGenerator = objectMapper.getFactory()
                .createGenerator(new File("target/example.json"), JsonEncoding.UTF8)
                .setPrettyPrinter(new MinimalPrettyPrinter() {
                    private static final long serialVersionUID = -2508021383479113398L;

                    @Override
                    public void writeStartObject(JsonGenerator g) throws IOException {
                        g.writeRaw(System.lineSeparator());
                        super.writeStartObject(g);
                    }

                    @Override
                    public void writeEndArray(JsonGenerator g, int nrOfValues) throws IOException {
                        g.writeRaw(System.lineSeparator());
                        super.writeEndArray(g, nrOfValues);
                    }
                });
             SequenceWriter sequenceWriter = objectMapper.writer().writeValuesAsArray(jsonGenerator)) {
            Example example = new Example();
            for (int i = 1; i <= 10; i++) {
                example.setId(i);
                example.setName("name" + i);
                sequenceWriter.write(example);
                
                if (i % 2 == 0) {
                    sequenceWriter.flush();
                }
            }
        }
    }

SequenceWriter 使用了一种流式写入的方式,它在写入对象时,并没有一次性将所有对象都读进内存,而是将它们分成多个较小的缓存块写入磁盘,从而减少了内存占用和GC压力。这种方式可以将内存分配和GC操作分散到多个小块中,而不是集中于一次大的内存分配和一次大的GC操作中。

具体来说,SequenceWriter 在写入每个对象时,先将该对象序列化为一个缓存块,然后写入磁盘。当缓存块达到一定大小时,SequenceWriter 会将其刷入磁盘,并开始写入下一个缓存块,从而避免了一次性将所有对象都读进内存所带来的性能问题。

因此,相比较一次性将所有对象读进内存再写入磁盘的方式,使用 SequenceWriter 可以更有效地利用内存和资源,减少内存占用和GC压力,提高写入效率。

你可能感兴趣的:(java,json,spring,boot)