数据(http.log)
13502468823 https://image.baidu.com 20 1000
18320173382 http://baidu.com 20 1000
13925057413 https://www.jianshu.com/p/bb88f7111b9e 20 3000
13760778710 http://blog.csdn.net/article/details/47444699 30 1000
手机段规则(手机号段规则.txt)
prefix phone province city isp post_code city_code area_code
130 1300000 山东 济南 联通 250000 0531 370100
130 1300001 江苏 常州 联通 213000 0519 320400
130 1300002 安徽 巢湖 联通 238000 0551 340181
130 1300003 四川 宜宾 联通 644000 0831 511500
需求:
1.计算出用户上网流量总流量(上行+下行)最高的的网站Top3,
2.根据给的的手机号段归属地规则,计算出总流量最高的省份Top3
3.根据给的的手机号段运营商规则,计算出总流量最高的运营商Top3
分析:
- 根据需求,声明三个map,key存 网站/省份/运营商 , value存总流量
- 读取手机号段规则,存在map, key放phone , value放TelBean 存对应手机号段的信息
- 读取http.log中的日志信息,最条分割,处理
- 对三个得到的map按流量排序,打印
代码如下:
public static void main(String[] args) throws Exception {
// 1.key存网站,value存对应的总流量
Map<String, Integer> isUrl = new HashMap<>();
// 2.key存省份,value存对应的总流量
Map<String, Integer> isProvince = new HashMap<>();
// 3.key存运营商,value存对应的总流量
Map<String, Integer> isp = new HashMap<>();
// 封装一个工具类,用来读取手机号段规则,key是phone;value是TelBean的集合
Map<String, TelBean> telBean = LogUtils.getTelBean("d:/data/手机号段规则.txt");
// 读取上网日志中的数据
BufferedReader br = new BufferedReader(new FileReader("d:/data/http.log"));
String line;
while ((line = br.readLine()) != null) {
// line --- 13026230503 http://v.baidu.com/tv 20 5000
// 分割 \\s+ 表示1个或多个空白字符
String[] split = line.split("\\s+");
String phone = split[0];
String urlString = split[1];
// 流量转成Integer
Integer upStream = Integer.parseInt(split[2]);
Integer downStream = Integer.parseInt(split[3]);
// urlString是http://v.baidu.com/tv,要进行简单筛选
String[] split2 = urlString.split("\\.");
if (split2.length > 2) {
String url = split2[1];
// 判断isUrl中有没有url,有就返回对应的value,没有返回 0
Integer urlStreamAll = isUrl.getOrDefault(url, 0);
urlStreamAll += upStream + downStream;
// 添加到isUrl,循环结束就能得到网站对应的总流量
isUrl.put(url, urlStreamAll);
}
// phone 13026230503 得到前7位(1302623),在telBean中找对应手机号的value
String substring = phone.substring(0, 7);
TelBean bean = telBean.get(substring);
// 省份
String province = bean.getProvince();
// 运营商
String isp2 = bean.getIsp();
// 添加到isProvince中
Integer pStreamAll = isProvince.getOrDefault(province, 0);
pStreamAll += upStream + downStream;
isProvince.put(province, pStreamAll);
// 添加
Integer ispStreamAll = isp.getOrDefault(isp2, 0);
ispStreamAll += upStream + downStream;
isp.put(isp2, ispStreamAll);
}
// 封装方法用来排序
List<String> isUrlRes = LogUtils.sortMap(isUrl);
List<String> isProvinceRes = LogUtils.sortMap(isProvince);
List<String> ispRes = LogUtils.sortMap(isp);
System.out.println(isUrlRes);// [baidu=142630, youku=72120, jianshu=54660, 51dot=36120, weibo=30120,
// csdn=18540]
System.out.println(isProvinceRes);// [广东=346790, 江西=5020, 北京=3040]
System.out.println(ispRes);// [移动=346790, 联通=8060]
br.close();
}
/**
* 读取手机段规则
* @param path
* @return 返回读取的TelBean数据,key是phone;value是TelBean
* @throws Exception
*/
public static Map<String, TelBean> getTelBean(String path) throws Exception {
Map<String, TelBean> telMap = new HashMap<>();
BufferedReader br = new BufferedReader(new FileReader(path));
br.readLine();// 把第一行除掉
String line;
while ((line = br.readLine()) != null) {
// 130 1300000 山东 济南 联通 250000 0531 370100
String[] split = line.split("\\s+");
String prefix = split[0];
String phone = split[1];
String province = split[2];
String city = split[3];
String isp = split[4];
String post_code = split[5];
String city_code = split[6];
String area_code = split[7];
TelBean telBean = new TelBean(prefix, phone, province, city, isp, post_code, city_code, area_code);
telMap.put(phone, telBean);
}
br.close();
return telMap;
}
/**
* 对map排序
* @param map
* @return 返回一个key=value的字符串的集合
*/
public static List<String> sortMap(Map<String, Integer> map) {
Map<String, Integer> tempMap = map;
/*
* 使用stream流操作
* sorted : 按value降序
* map : 将Entry<String,Integer>变成字符串
* collect : 将字符串转成集合
*/
List<String> collect = tempMap.entrySet()
.stream()
.sorted((o1,o2)->o2.getValue()-o1.getValue())
.map(o->o.getKey()+"="+o.getValue())
.collect(Collectors.toList());
return collect;
}