统计URL出现层级及次数
文章目录
- 前言
- 完整代码网址
- 题目
- 解答
- 解析url
- 输出
- 优化
前言
本文以一道统计url各层级出现层级及次数为例,总结key value存储。
完整代码网址
https://gitee.com/zfranklin/java-intelli-j/blob/master/OD/src/C1My.java
题目
可以看出,本质上是求出某一级,某一个url,出现了多少次。如果仅仅统计url出现了多少次,或者某一级上有哪些url,用一个hashmap即可。这里我首先想到的是hashmap中嵌套一个hashmap。
解答
HashMap<Integer, HashMap<String,Integer>> cnts = new HashMap<Integer,HashMap<String,Integer>>();
内层String是url,Integer是出现次数,外层Integer是所在层级。
java7之后,可以使用菱形运算符 <> 来简化泛型的声明,因为编译器可以根据变量的声明类型自动推断出泛型类型。
HashMap<Integer, HashMap<String,Integer>> cnts = new HashMap<>();
进入main,首先接受有几个url,然后每接收一个url,就开始解析,存储。
解析url
因为url仅由 / (斜杠) 和 大小写字母组成,可以用 / 来进行分割,分割后是若干个字符串,也就是字符串数组,存储在urlComponents里,值得注意的是:/a/b/c,会被分割成 { “”,“a”,“b”,“c” }。第一个 / 左边是空字符串,储存到 urlComponents[0] 里。此时,恰好a的下标是1,所以不用管空字符串。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
HashMap<Integer, HashMap<String,Integer>> cnts = new HashMap<>();
for (int i = 0; i < n; i++){
String url = sc.next();
String[] urlComponents = url.split("/");
for (int level = 0;level < urlComponents.length;level++){
}
}
}
在内层for循环里,由于初始化cnts后,cnts并没有存储确切的内容size为0,我们想从cnts通过get得到内层hashmap时,要进行必要的判断,如果没有当前层作为key,就put一个hashmap,if判断一定要加,如果不加if判断,只是一味地cnts.put,会覆盖原先的对应key value对。
if (cnts.size() <= level) { cnts.put(level,new HashMap<>()); }
HashMap<String,Integer> map = cnts.get(level);
map.put(urlComponents[level], map.getOrDefault(urlComponents[level],0)+1);
输出
循环结束后,接收一个目标层级,接收一个目标url,输出检测结果,注意,如果没有目标层级输出0,有目标层,但没有目标url也输出0。
int tar_level = sc.nextInt();
String tar_url = sc.next();
HashMap<String,Integer> defaultMap = new HashMap<>();
System.out.println(cnts.getOrDefault(tar_level,defaultMap).getOrDefault(tar_url,0));
可以用getOrDefault,如果没有该层级,就获取默认hashmap defaultMap,如果该hashmap没有目标tar_url,就默认为0。
优化
if (cnts.size() <= level) { cnts.put(level,new HashMap<>()); }
这一句判断有没有对应level的HashMap,如果没有就put一个,java8之后推出了Lambda表达式,可以替换为:
cnts.computeIfAbsent(level, k -> new HashMap<>());
如果没有level作为key的键值对,就新增一个< leve,HashMap >。