CCF JSON查询 Java 完美满分 详解
主要想法就是用一个列表当做像栈一样缓存着键,遇到键字符串的时候就把它与上一层的键结合成嵌套形式存入列表,这样,列表的最后一个元素总是代表着当前键值对的键,当当前这一个键值对处理完之后,这个键在后面就不会被使用到了,就再把它从列表中移除
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan=new Scanner(System.in);
int n=scan.nextInt();
int m=scan.nextInt();
scan.nextLine();
StringBuilder sb=new StringBuilder();
String input;
/**
因为题目中说了字符串中的内容不包含空格,则删掉空格不会影响键值字符串内容,所以为了格式清晰,就把所有的空格删掉,然后把所有内容整成一行
*/
for(int i=0;i<n;i++) {
input=scan.nextLine();
input=input.replaceAll(" ", ""); //删掉所有空格
sb.append(input);//整成一行
}
//用一个列表的最后一个元素来存当前的键字符串
ArrayList<String> list =new ArrayList<>();
list.add(null);//这样是为了第一层的键好处理
HashMap<String, String> map=new HashMap<>();
//用一个map来存所有的键值对,即使多层嵌套的对象也可以
char c;
String pre;
String key;
String value;
String tmp="";
//逐个字符遍历内容
for(int i=1;i<sb.length();i++) {
c=sb.charAt(i);
switch (c) {
case '}': //说明这个对象终止了,这个对象的键也就不会再用到了,所以移出
list.remove(list.size()-1);
break;
case '{': //说明当前这个键它的值是一个对象,所以把它这样子存进map以方便查找
key=list.get(list.size()-1);
map.put(key, "OBJECT");
break;
case '"': //说明这是一个字符串的开始,可能是键,也可能是值
i++;//跳过双引号到它真正的内容开头
tmp="";//这步很重要,先清空之前的临时字符串,不然之前的内容会重叠进来
while(sb.charAt(i)!='"') {//一直处理到字符串结束
if(sb.charAt(i)=='\\') ++i; //这一步很巧妙,若是第一个\就跳过它到下一个字符,这样可以非常巧妙地处理了\\和\"的情况
tmp+=sb.charAt(i++);//把这个字符加入临时字符串,然后到下一个字符
}
//字符串处理完了,要判断它是键还是值,
if(sb.charAt(i+1)==':') {//如果它的下一位是:,那它就是键,
key=tmp;
pre=list.get(list.size()-1);
if(pre!=null)//还要看它是不是在第一层
list.add(pre+"."+key); //如果不是在第一层,就要把在前面接上之前键和.作为嵌套形式的键
else
list.add(key);//如果在第一层就不需要接嵌套的,就直接放入list
}else {//如果是值,就将它与当前的键结合存入map,而且这样之后它的键也就不会再在后面被使用到了,所以移除,不然会占着茅坑会出错
value=tmp;
key=list.remove(list.size()-1);
map.put(key, value);
}
break;
}
}
//从map中查找,输出:
String[] output=new String[m];
for(int i=0;i<m;i++) {
key=scan.nextLine();
//如果map中包含该键,则只有两种可能,要么是object,要么是string:
if(map.containsKey(key)) {
if(map.get(key).equals("OBJECT"))
output[i]="OBJECT";
else
output[i]="STRING "+map.get(key);
}else //如果map中没有该键,则不存在:
output[i]="NOTEXIST";
}
for(String s:output)
System.out.println(s);
}
}