You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何从含50万对象的JSONObject获取唯一值?

在Java中从大JSON数据集高效提取唯一值的方案

首先明确说:你当前用循环遍历WORKORDER数组逐个提取值的方式完全可行,逻辑上没有问题——只要你在遍历过程中把提取到的目标值(比如WONUM的content)存入一个Set集合,就能自动得到唯一值。但针对50万条这样的大数据量,这个方案的性能和内存占用有优化空间,下面给你拆解下更好的实现思路:

一、为什么原始方案可能不够高效?

如果用的是org.json这类基础JSON库,每次循环创建JSONObject对象会带来不小的对象开销;更关键的是,一次性把50万条数据的JSON数组加载到内存中,会占用大量堆内存,很容易触发频繁GC甚至内存溢出(OOM),尤其当你的JVM堆内存配置有限时。

二、更高效的优化方案

1. 优先用流式JSON解析(内存友好型)

流式解析的核心是不把整个JSON文件加载到内存,而是逐行/逐段读取JSON事件,只提取你需要的字段,内存占用极低,特别适合处理大文件。推荐用Jackson或者Gson的流式API,这里给你举个Jackson的示例:

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.io.File;
import java.util.HashSet;
import java.util.Set;

public class UniqueValueExtractor {
    public static void main(String[] args) throws Exception {
        JsonFactory factory = new JsonFactory();
        // 直接读取文件,不需要一次性加载
        JsonParser parser = factory.createParser(new File("your-workorders.json"));
        Set<String> uniqueWonums = new HashSet<>();
        boolean isInAttributes = false;

        while (parser.nextToken() != JsonToken.END_OBJECT) {
            if (parser.getCurrentToken() == JsonToken.FIELD_NAME) {
                String fieldName = parser.getCurrentName();
                // 定位到Attributes节点
                if ("Attributes".equals(fieldName)) {
                    isInAttributes = true;
                } 
                // 在Attributes里找到WONUM节点,提取content值
                else if (isInAttributes && "WONUM".equals(fieldName)) {
                    parser.nextToken(); // 进入WONUM的对象节点
                    while (parser.nextToken() != JsonToken.END_OBJECT) {
                        if ("content".equals(parser.getCurrentName())) {
                            parser.nextToken(); // 移动到content的值节点
                            uniqueWonums.add(parser.getText());
                            break; // 拿到值就退出当前WONUM节点的遍历
                        }
                    }
                    isInAttributes = false; // 重置标记,处理下一个WORKORDER
                }
            }
        }
        parser.close();
        System.out.println("提取到的唯一WONUM数量:" + uniqueWonums.size());
    }
}

2. 优化唯一值的存储容器

如果你的唯一值数量很大(比如接近50万),普通HashSet会因为频繁扩容产生额外开销,建议:

  • 用HashSet的带初始容量的构造方法:new HashSet<>(预计唯一值数量),提前分配足够空间;
  • 或者用Google Guava的Sets.newHashSetWithExpectedSize(int),它会更合理地计算初始容量;
  • 如果追求极致内存效率,可以用Eclipse Collections的MutableHashSet,它比JDK原生HashSet内存占用更低。

3. 用POJO绑定替代JSONObject(内存足够时可选)

如果你的JVM堆内存足够容纳50万条对象,用Jackson或Gson的POJO绑定方式会比直接操作JSONObject更简洁高效,因为POJO的对象开销比JSONObject小,而且代码可读性更好。

先定义对应结构的POJO:

public class WorkOrder {
    private Attributes Attributes;

    // getter & setter
    public static class Attributes {
        private Field SITEID;
        private Field WONUM;
        private Field WORKTYPE;

        // getter & setter
        public static class Field {
            private Object content;

            // getter & setter
        }
    }
}

然后批量解析并提取唯一值:

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.util.HashSet;
import java.util.Set;

public class PojoExtractor {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        // 直接把JSON数组转成WorkOrder数组
        WorkOrder[] orders = mapper.readValue(new File("your-workorders.json"), WorkOrder[].class);
        
        // 提前设置初始容量,避免扩容
        Set<String> uniqueWonums = new HashSet<>(orders.length);
        for (WorkOrder order : orders) {
            String wonum = (String) order.getAttributes().getWONUM().getContent();
            uniqueWonums.add(wonum);
        }
        System.out.println("唯一WONUM数量:" + uniqueWonums.size());
    }
}

4. 并行处理(谨慎使用)

如果你的机器有多核CPU,且解析瓶颈在CPU而非内存,可以考虑把JSON数组拆分后并行解析,最后合并唯一值集合。比如用ExecutorService启动多个线程,每个线程处理一部分数据,用ConcurrentHashMap.newKeySet()来保证线程安全的存储。不过这种方式的收益有限,只有当流式解析和POJO绑定都无法满足性能要求时再考虑。

总结

你的原始方案完全可以工作,但针对50万条数据的场景,流式解析是最优选择——它能把内存占用降到最低,同时保证解析速度;如果内存充足,POJO绑定的方式代码更简洁易维护。

内容的提问来源于stack exchange,提问作者Anas Elbenney

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:23:21