在java中是否可以从JSONObject获取不同的值
我有一个包含500k对象的json文件,其格式如下:在java中是否可以从JSONObject获取不同的值,java,json,unique,distinct,Java,Json,Unique,Distinct,我有一个包含500k对象的json文件,其格式如下: "WORKORDER": [ { "Attributes": { "SITEID": { "content": "BEDFORD" }, "WONUM": { "cont
"WORKORDER": [
{
"Attributes": {
"SITEID": {
"content": "BEDFORD"
},
"WONUM": {
"content": "1000"
},
"WOPRIORITY": {
"content": 2
},
"WORKTYPE": {
"content": "CM"
}
}
},
{
"Attributes": {
"SITEID": {
"content": "BEDFORD"
},
"WONUM": {
"content": "1000-10"
},
"WORKTYPE": {
"content": "CM"
}
}
}
我将获得如下不同的值:
for (int i = 0; i < WORKORDER.length(); i++) {
JSONObject obj = WORKORDER.getJSONObject(i);
JSONObject att = obj.getJSONObject("Attributes");
if( att.has(col)){ // getting col from params in the servlet
JSONObject column = att.getJSONObject(col);
Object colval = column.get("content");
if(!(list.contains(colval))) {
out.println( colval);
list.add(colval);
}
for(inti=0;i
但只需要5000个对象就需要很长时间
是否有任何方法可以在不解析整个Json文件的情况下获取任何列的不同值,否则只解析所需的列。您正在迭代一个包含500k个元素的Json。对于每个元素,您都要检查它之前是否添加到
列表中。这意味着您的逻辑将迭代列表500k次
相反,您应该使用HashSet
,首先是集合
防止重复值。因此您只需要集合。添加(值)
,但最有趣的是实例具有恒定的复杂性值。因为它使用bucket来组织值,所以不必完全迭代集合
你可以阅读更多关于这方面的内容
请注意,HashSet给出了O(1)的摊销和平均时间性能,而不是最坏的情况。这意味着,我们可能会不时遇到O(n)操作。
因此,当垃圾箱太拥挤时,我们只需创建一个新的、更大的数组,并将元素复制到其中
请注意,要使用任何Hash#####
实现,您需要确保存储的实例实现了hashCode
且等于
。您可以了解更多信息
现在来看解决方案:
Set<Object> sets = new HashSet<>();
for (int i = 0; i < WORKORDER.length(); i++) {
// ...
Object colval = column.get("content");
if(sets.add(colval)){ //`add` return true if it wasn't present already.
out.println( colval);
}
}
然后对这两种方法进行了基本基准测试,结果如下:
public static void main(String[] args) throws Exception {
final int jsonLength = 500_000;
JSONObject json = createDummyJson(jsonLength);
long start = System.currentTimeMillis();
List<Object> list = parseJson(json);
long end = System.currentTimeMillis();
System.out.format("List - Run in %d ms for %d items and output %d lines%n", end-start, jsonLength, list.size());
start = System.currentTimeMillis();
Set<Object> set = parseJsonSet(json);
end = System.currentTimeMillis();
System.out.format("Set - Run in %d ms for %d items and output %d lines%n", end-start, jsonLength, set.size());
}
public static List<Object> parseJson(JSONObject json) {
String col = "columnC";
JSONArray array = json.getJSONArray("order");
List<Object> list = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
JSONObject att = obj.getJSONObject("Attributes");
if (att.has(col)) { // getting col from params in the servlet
JSONObject column = att.getJSONObject(col);
Object colval = column.get("content");
if (!(list.contains(colval))) {
//System.out.println(colval);
list.add(colval);
}
}
}
return list;
}
public static Set<Object> parseJsonSet(JSONObject json) {
String col = "columnC";
JSONArray array = json.getJSONArray("order");
Set<Object> set = new HashSet<>();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
JSONObject att = obj.getJSONObject("Attributes");
if (att.has(col)) { // getting col from params in the servlet
JSONObject column = att.getJSONObject(col);
Object colval = column.get("content");
if (set.add(colval)) {
//System.out.println(colval);
}
}
}
return set;
}
publicstaticvoidmain(字符串[]args)引发异常{
最终内部jsonLength=500_000;
JSONObject json=createDummyJson(jsonLength);
长启动=System.currentTimeMillis();
List=parseJson(json);
long end=System.currentTimeMillis();
System.out.format(“列表-在%d毫秒内运行%d个项目并输出%d行%n)”,结束-开始,jsonLength,List.size();
start=System.currentTimeMillis();
Set=parseJsonSet(json);
end=System.currentTimeMillis();
System.out.format(“设置-在%d毫秒内运行%d个项目并输出%d行%n)”,结束-开始,jsonLength,Set.size();
}
公共静态列表解析json(JSONObject json){
String col=“columnC”;
JSONArray数组=json.getJSONArray(“订单”);
列表=新的ArrayList();
对于(int i=0;i
列表-在5993毫秒内运行500000个项目,输出46971行
设置-在62毫秒内运行500000个项目,输出46971行
我甚至访问了一个有500万行的JSON(删除了永远不会结束的列表)
设置-在6436毫秒内运行5000000个项目,输出468895行
重要提示:每次新插入时,请删除控制台中打印的行,这将减少一点执行时间。您可以使用设置而不是列表(如果列表代表列表
),这样会“更简单”现在要直接过滤JSON…除非您可以更改JSON的生成,否则您仍然需要读取JSON(JSONObject
只是一个解析器)。您可以尝试将其转换为csv,然后获取所需的column@AxelH当使用集合时,它会加速解析吗?@PankajSinghal,但是转换成csv比抓取还需要时间!!是和否。这取决于你所采用的实现。使用哈希集合可以做到这一点,因为它使用bucket。目前,这是s是杀死你的contains
方法,它需要迭代JSON中每个元素的列表。起初这没关系,但当你已经有1000个项目时,这些项目将被迭代40万次以上。@AnasElbenney请注意最后一部分,使用列。get
使用此逻辑不安全,请使用getString(“content”)
取而代之。(忘了你已经显示了JSON…)但我不知道用户是否选择了字符串列或数字!很抱歉,它做得太长了,两个(set和list)的时间都一样好@AnasElbenney我将生成一个伪JSON来做一些测试。完成后我会回复你(可能是今晚格林威治标准时间)@AnasElbenney我使用一个“相似”的json运行,并验证了差异。如果它不起作用,那么这就不是需要时间的集。。。
public static void main(String[] args) throws Exception {
final int jsonLength = 500_000;
JSONObject json = createDummyJson(jsonLength);
long start = System.currentTimeMillis();
List<Object> list = parseJson(json);
long end = System.currentTimeMillis();
System.out.format("List - Run in %d ms for %d items and output %d lines%n", end-start, jsonLength, list.size());
start = System.currentTimeMillis();
Set<Object> set = parseJsonSet(json);
end = System.currentTimeMillis();
System.out.format("Set - Run in %d ms for %d items and output %d lines%n", end-start, jsonLength, set.size());
}
public static List<Object> parseJson(JSONObject json) {
String col = "columnC";
JSONArray array = json.getJSONArray("order");
List<Object> list = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
JSONObject att = obj.getJSONObject("Attributes");
if (att.has(col)) { // getting col from params in the servlet
JSONObject column = att.getJSONObject(col);
Object colval = column.get("content");
if (!(list.contains(colval))) {
//System.out.println(colval);
list.add(colval);
}
}
}
return list;
}
public static Set<Object> parseJsonSet(JSONObject json) {
String col = "columnC";
JSONArray array = json.getJSONArray("order");
Set<Object> set = new HashSet<>();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
JSONObject att = obj.getJSONObject("Attributes");
if (att.has(col)) { // getting col from params in the servlet
JSONObject column = att.getJSONObject(col);
Object colval = column.get("content");
if (set.add(colval)) {
//System.out.println(colval);
}
}
}
return set;
}