算法例子:手动解析Json,按照层级打印(Java)

1.算法例子描述

给定一个json字符串

{
	"a": {
		"b": {
			"c": {
				"d": "h",
				"j": "l",
				"o": {
					"p": "q",
					"r": "s"
				},
				"t": "u"
			}
		},
		"v": {
			"w": {
				"x": {
					"y": "z"
				}
			}
		}
	},
	"e": {
		"f": {
			"i": "k"
		},
		"m": "n"
	}
}

要求把同等级的放在一起,打印出来.

[[a, e], [b, v, f, m], [c, w, i], [d, j, o, t, x], [p, r, y]]

2.算法结果打印

字符串遍历流程:

str:{"a":{"b":{"c":{"d":"h","j":"l","o":{"p":"q","r":"s"},"t":"u"}},"v":{"w":{"x":{"y":"z"}}}},"e":{"f":{"i":"k"},"m":"n"}}
key:a  level:0
key:b  level:1
key:c  level:2
key:d  level:3
key:j  level:3
key:o  level:3
key:p  level:4
key:r  level:4
key:t  level:3
key:v  level:1
key:w  level:2
key:x  level:3
key:y  level:4
key:e  level:0
key:f  level:1
key:i  level:2
key:m  level:1
resultStr:[[a, e], [b, v, f, m], [c, w, i], [d, j, o, t, x], [p, r, y]]

3.算法分析

需要考虑几个问题:
1.要想找到key,那么就需要遍历字符串?.
那么就需要将其转化为charArray,进行遍历即可.
2.怎么计算层级.
需要一个临时变量level,计算当前key的层级.
层级增加就level++
层级降低就level–.
层级不变.不需要改变level.
3.怎么判断层级增加?.
当遇到了 { 那么就是等级增加.
4.怎么判断层级结束?.
当遇到了 } 那么就是等级增加.
5.怎么判断是同等级的?.
如果两个key在同等级.
那么肯定是使用 逗号(,)隔开的,此时不需要降级.
6.怎么区分读到的字母是key还是value?.
可以在上一个key结束后,将对用key置为空,
当前的key为空,那么此时的字母是key,赋给key.
当前的key不为空,那么此时的字母是属性值.不需要赋给key.
7.怎么处理结果字符串格式?.
因为是按照层级存储的,我这里考虑使用List result;
外层的List表示层级,每个索引表是当前的层级.因为需要经常查找,用ArrayList.
外层的List存储层级中的key,因为需要添加相对较多(虽然是进行尾部插入,和ArrayList没区别,但是内存分分配上可以不连续)用LinkedList.
最后遍历result即可.组装对应的字符串.

4.算法实现

4.1 Key结点数据结构

/**
 * Key的结点Bean
 */
class KeyNode {
    private Character key;//key的值
    private int level;//key的等级,这里从0开始

    public KeyNode(Character key, int level) {
        this.key = key;
        this.level = level;
    }

    public Character getKey() {
        return key;
    }

    public int getLevel() {
        return level;
    }

}

4.2 存储结果数据结构


/**
 * 存储结果Bean
 */
public class KeyResult {
    //外层是按照登记区分.里层就是key的集合
    //因为外层要频繁的查找,所以要用ArrayList,
    //里层的那个频繁的添加,所以用LinkedList
    private List<List<Character>> result;

    public KeyResult() {
        //因为外层要频繁的查找,所以要用ArrayList,
        result = new ArrayList<>();
    }

    /**
     * 添加Key
     *
     * @param keyNode
     */
    public void addKey(KeyNode keyNode) {
        if (keyNode == null) {
            return;
        }
        //1.先通过等级找到对应的位置的数据.
        if (keyNode.getLevel() == result.size()) {
            //此时说明result中还未有此位置,则需要创建并添加到result中
            result.add(new LinkedList<Character>());
        }
        List<Character> keys = result.get(keyNode.getLevel());
        //2.将key的值添加到对应的位置中
        keys.add(keyNode.getKey());
    }

    /**
     * 获取指定格式化的字符串[[a,e],[b,c],[d]]
     *
     * @return
     */
    public String getFormatString() {
        StringBuilder resultString = new StringBuilder();
        resultString.append("[");
        //1.外层
        for (int i = 0, size = result.size(); i < size; i++) {
            if (i == 0) {
                resultString.append("[");
            } else {
                resultString.append(",").append("[");
            }
            //2.里层
            List<Character> keys = result.get(i);
            for (int j = 0, keySize = keys.size(); j < keySize; j++) {
                if (j == 0) {
                    resultString.append(keys.get(j));
                } else {
                    resultString.append(",").append(keys.get(j));
                }
            }
            resultString.append("]");
        }
        resultString.append("]");
        return result.toString();
    }
}

4.3 处理字符串方法

/**
     * 处理为指定格式的字符串
     * [[a, e], [b, v, f, m], [c, w, i], [d, j, o, t, x], [p, r, y]]
     *
     * @param strs 待处理的字符串
     * @return
     */
    public static String optFormatStr(String strs) {
        //1.将字符串转化成char数组
        char[] chars = strs.toCharArray();
        //2.辅助变量
        KeyResult result = new KeyResult();//存储打印的结果
        int level = -1;//当前的等级
        char key = ' ';//临时变量,遍历时判断是属性还是对象用的
        //3.遍历数组
        for (char c : chars) {
            if (c == '{') {
                //3.1,遇到 { 表示增加了增加,并且将key置为" "
                key = ' ';
                level++;
            } else if (c == ',') {
                //3.2,遇到 , 表示当前key对应的属性结束,并且将key置为" "
                key = ' ';
            } else if (c == '}') {
                //3.3.表示当前等级遍历结束.等级-1
                level--;
            } else if (c >= 'a' && c <= 'z') {
                //3.4.表示遇到的是字母
                //如果key为" ",说明key是上个key遍历了,此时c有效.
                if (key == ' ') {
                    key = c;
                    System.out.println("key:" + c + "  level:" + level);
                    result.addKey(new KeyNode(key, level));
                }
                // else 否则表示c是key的一个属性值,不需要进行存储.
            }
        }
        //4.返回结果
        return result.getFormatString();
    }

4.4. 调用示例

public static void main(String[] args) {
        //1.字符串
        String str = "{\n" +
                "\t\"a\": {\n" +
                "\t\t\"b\": {\n" +
                "\t\t\t\"c\": {\n" +
                "\t\t\t\t\"d\": \"h\",\n" +
                "\t\t\t\t\"j\": \"l\",\n" +
                "\t\t\t\t\"o\": {\n" +
                "\t\t\t\t\t\"p\": \"q\",\n" +
                "\t\t\t\t\t\"r\": \"s\"\n" +
                "\t\t\t\t},\n" +
                "\t\t\t\t\"t\": \"u\"\n" +
                "\t\t\t}\n" +
                "\t\t},\n" +
                "\t\t\"v\": {\n" +
                "\t\t\t\"w\": {\n" +
                "\t\t\t\t\"x\": {\n" +
                "\t\t\t\t\t\"y\": \"z\"\n" +
                "\t\t\t\t}\n" +
                "\t\t\t}\n" +
                "\t\t}\n" +
                "\t},\n" +
                "\t\"e\": {\n" +
                "\t\t\"f\": {\n" +
                "\t\t\t\"i\": \"k\"\n" +
                "\t\t},\n" +
                "\t\t\"m\": \"n\"\n" +
                "\t}\n" +
                "}";
        //2.将空格,\t,\n,去掉.
        str = str.replaceAll(" ", "");
        str = str.replaceAll("\t", "");
        str = str.replaceAll("\n", "");
        //3.调用处理为指定的个数
        System.out.println("str:" + str);
        String resultStr = optFormatStr(str);
        System.out.println("resultStr:" + resultStr);
    }

欢迎大家指正和互相学习.

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值