零基础学习java------26--------获取省访问量的top3,APP版本数据分析,事务,json,json字符串与对象间的相互转换,求电影平均分
一. day23中的ip,url案例(前面答案错了)
思路分析:
1.创建javabean,用来存储ip.txt各字段的信息
2. 创建java工具类,封装相应的方法
(1) 加载读取ip.txt文档,获取各字段,将之封装进javabean,并将javabean存储至list中去(ip地址为区间范围,用map满足不了需求),以便后面能通过access.log内的ip找到其在ip.txt所属的javabean
(2)将ip转译为长整型数
(3)利用二分法查找access.log内的ip在ip.txt所属的javabean(返回javabean,即可得到所属的省份)
3. 统计各省的访问量
java工具类以及javabean见day23
public class IpTest { // 将数据的加载放入静态代码块 static List<IpBean> list = null; static { list = IpUtils.loadIpToList(); } public static void main(String[] args) { Map<String, Integer> map = readData(); // 排序 Set<Entry<String, Integer>> entrySet = map.entrySet(); ArrayList<Entry<String, Integer>> list = new ArrayList<>(entrySet); Collections.sort(list, new Comparator<Entry<String, Integer>>(){ @Override public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) { return o2.getValue()-o1.getValue(); } }); for (Entry<String, Integer> entry : list) { System.out.println(entry); } } public static Map<String, Integer> readData() { Map<String, Integer> map = new HashMap<>(); // 获取以province为key,访问量为value的map // Integer sum = 1; try ( BufferedReader br = new BufferedReader(new FileReader("E:\\javafile\\access.log")); ){ String line = null; while((line=br.readLine()) != null) { String[] split = line.split("\\|"); String ip = split[1]; //将ip转译成长整型 Long ip1 = IpUtils.parseStrIpToLongIp(ip); //利用二分查找获取ip1对应的javabean IpBean bean = IpUtils.binaryOfIp(ip1, list); String province = bean.getProvince(); Integer count = map.getOrDefault(province, 0); map.put(province, ++count); // if(map.containsKey(province)) { 这种叠加访问量的方式不知道错在哪 // map.put(province, ++sum); // }else { // map.put(province, 1); // } } } catch (Exception e) { e.printStackTrace(); } return map; } }
运行结果:
二. APP版本数据分析
1.数据
2. 需求:
统计出每天的app版本升级情况(最小版本,和最大版本),此外日期要按时间升序排列
3. 思路分析
(1)以日期,用户名,app名,新版本下载渠道为key,装有version的Set为value,将数据封装至map
(2)将map的value值排序(升序),可得出每天最早的版本和最后更新的版本
(3)创建AppBean,用来存放上图各字段的值
(4)对AppBean中的时间字段进行排序(升序)-----> 将时间(String)转译成date格式, 使用date1.before(date2)
代码如下
AppBean
public class AppBean { private String date; private String userName; private String appName; private String store; private String minVersion; private String maxVersion; public AppBean() { } public AppBean(String date, String userName, String appName, String store, String minVersion, String maxVersion) { super(); this.date = date; this.userName = userName; this.appName = appName; this.store = store; this.minVersion = minVersion; this.maxVersion = maxVersion; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getAppName() { return appName; } public void setAppName(String appName) { this.appName = appName; } public String getStore() { return store; } public void setStore(String store) { this.store = store; } public String getMinVersion() { return minVersion; } public void setMinVersion(String minVersion) { this.minVersion = minVersion; } public String getMaxVersion() { return maxVersion; } public void setMaxVersion(String maxVersion) { this.maxVersion = maxVersion; } @Override public String toString() { return "AppBean [date=" + date + ", userName=" + userName + ", appName=" + appName + ", store=" + store + ", minVersion=" + minVersion + ", maxVersion=" + maxVersion + "]"; } }
实现类
public class appTest { public static void main(String[] args) throws Exception { // 将日期按从小到大的顺序排列 ArrayList<AppBean> list = loadDataToBean(); Collections.sort(list, new Comparator<AppBean>() { @Override public int compare(AppBean o1, AppBean o2) { try { String str1 = o1.getDate(); String str2 = o2.getDate(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date date1 = simpleDateFormat.parse(str1); Date date2 = simpleDateFormat.parse(str2); return date1.before(date2) ?-1:1; } catch (ParseException e) { e.printStackTrace(); } return 0; } }); System.out.println(list); } // 将数据封装至AppBean public static ArrayList<AppBean> loadDataToBean() { // 获取缓冲字符流,读取并切割数据 Map<String, Set<String>> map = new HashMap<>(); ArrayList<AppBean> arrayList = new ArrayList<>(); try ( BufferedReader br = new BufferedReader(new FileReader("E:/javafile/app.txt")); ){ String line = null; while((line= br.readLine()) != null) { String[] split = line.split(","); String date = split[0]; String userName = split[1]; String appName = split[2]; String store = split[3]; String version = split[5]; // 将数据封装至map String key = date +","+ userName+","+ appName+","+ store; Set<String> vs = map.getOrDefault(key, new HashSet<>()); vs.add(version); map.put(key, vs); } // Set<Entry<String, Set<String>>> entrySet = map.entrySet(); for (Entry<String, Set<String>> entry : entrySet) { // 对value(set)进行排序 Set<String> set = entry.getValue(); if(set.size()>1) { ArrayList<String> list = new ArrayList<>(set); Collections.sort(list, (o1,o2)->o1.compareTo(o2)); //获取list种的第一个和最后一个 String minVersion = list.get(0); String maxVersion = list.get(list.size()-1); String key = entry.getKey(); String[] split = key.split(","); // 向 AppBean 封装数据,并将之存储至List中 AppBean bean = new AppBean(split[0], split[1], split[2], split[3], minVersion, maxVersion); arrayList.add(bean); } } } catch (Exception e) { e.printStackTrace(); } return arrayList; } }
三 事务(https://www.cnblogs.com/huanongying/p/7021555.html)
1. 概念
一组逻辑上的操作,在这组逻辑操作中的所有sql语句在执行的过程中要么全部成功,要么全部失败。mysql默认的是一个sql语句一个事务,其会自动提交并执行sql
2. 事务的基本要素(ACID)
(1)原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位
(2)一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏。比如A向B转账,不可能A扣了钱,B却没有收到钱
(3)隔离性(Isolation):同一时间,只允许一个事务请求同一事务,不同的事务之间没有任何干扰。比如A正在从一张银行卡中取出钱,在A取钱的过程结束前,B不能向这张转账。
(4)持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚
3. 事务的并发问题
(1)脏读:事务A读取了事务B更新的数据,然后B回滚操作(读取了未提交的数据),那么A读取到的数据是脏数据
(2)不可重复读:事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致
(3)幻读:系统管理员A将数据库中所有学生的成绩从具体的分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫环读
小结:不可重复读和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
4. Mysql事务隔离级别
四. json
Json是一种数据格式,简单并且容易解析,常用于网络之间数据传输,一个json即为一个对象
Json字符串与json对象之间的相互转换
使用阿里巴巴开发的fastjson工具
数据:
转换代码
public class JsonDemo { public static void main(String[] args) { try ( BufferedReader br = new BufferedReader(new FileReader("E:/javafile/move.txt")); ){ String line =null; while((line = br.readLine()) != null) { System.out.println(line); //json字符串---->对象 Movie m = JSON.parseObject(line, Movie.class); System.out.println(m); // 对象--->字符串 // String mstr = JSON.toJSONString(m); // System.out.println(mstr); } } catch (Exception e) { e.printStackTrace(); } } }
求每个用户对电影评分的平均分
代码
public class AverageRate { public static void main(String[] args) { Map<String, Double> avgMap = getAvgMap(); System.out.println(avgMap); } // 获取以uid为key,平均分数为值的map public static Map<String,Double> getAvgMap() { Map<String,List<Double>> map = new HashMap<String,List<Double>>(); Map<String,Double> avgMap = new HashMap<>(); // 获取缓冲字符流读取文件 try ( BufferedReader br = new BufferedReader(new FileReader("E:/javafile/move.txt")); ){ String line = null; while((line = br.readLine()) != null) { // 获取以uid为key,装有date的list为值的map Movie m = JSON.parseObject(line, Movie.class); String uid = m.getUid(); Double rate = m.getRate(); List<Double> list = map.getOrDefault(uid, new ArrayList<Double>()); list.add(rate); map.put(uid,list); } // 求平均值,并将相应的值封装进avgMap Set<Entry<String, List<Double>>> entrySet = map.entrySet(); for (Entry<String, List<Double>> entry : entrySet) { String uid1 = entry.getKey(); List<Double> listValue = entry.getValue(); Double total = (double) 0; for(int i=0;i<listValue.size();i++){ total += listValue.get(i); } Double avg = total/listValue.size(); avgMap.put(uid1,avg); } } catch (Exception e) { e.printStackTrace(); } return avgMap; } }