oo第三单元总结

oo第三单元总结

实现规格所采取的设计策略

只梳理一下几个与规格的实现方法差异较大的接口,像Message这种直接照着规格写就行了

接口 数据结构实现 方法实现
Person HashMap<Integer, Integer> acquaintance保存熟人,key代表熟人的id,value代表到熟人的权值 直接用get实现查找熟人;返回acquitance在Network中插入熟人
LinkedList<Message>messages保存接收到的消息,新消息采用头插的方式,比数组更快 直接通过前几个消息的subList新建LinkedList并返回
int root用来保存并差集的根结点 通过getRoot和setRoot直接返回root,在Network类中处理并差集
Group HashSet<Person>people保存组内的所有人 getAgeVar方法由于有取整操作的存在,不好实时更新,故采用静态写法,每次遍历people进行计算
int valueSum保存组内所有人的socialValue总和,每次加人减人都实时更新
BigInteger ageSum保存组内所有人的年龄和,用来实时更新平均年龄
Network HashMap<Integer, Person>people保存所有人 getRoot(Myperson)以递归的方式获取person的根,setRoot方法也类似
ArrayList<String>names保存所有人的名字,为有序数组,用来二分快速查找名字排序 queryReachableAndSetRoot方法为dfs查询p1能不能到p2,如果能的话就把路径上的所有点设置为同一个root;这个函数只在addRelation时调用,用来实时更新联通块的数量
HashMap<Integer, Group>groups用来快速查找组 addRelation主要完成两件事,一是设置两人的关系并调整并差集和联通块数目,二是更新所有包含此两人的组的valueSum
HashMap<Integer, Message>messages用来快速查找消息 queryNameRank通过二分查找名字的最左端下标来返回相应排名
HashMap<Integer, Integer>emojis用来保存emoji表情,key为emoji表情的id,value为emoji表情的热度 addPerson主要完成三件事,一是加入person到容器中,二是二分插入name,三是增加联通块数目
TreeMap<Integer, Set<Integer>>emojiHeat用来表示emoji表情的热度,key为emoji表情的热度,value为热度为key的emoji表情的集合 addMessage除了正常加入message到容器中,还要特判emojiMessage,并加入相应的emojiMessages中
HashMap<Integer, Set<Integer>>emojiMessages表示相应的emojiMessage,key为emoji表情的id,value为emoji为key的消息的集合 sendIndirectMessage中主要是调用了getMinPath方法,通过用最小堆实现的Dijistra算法静态地计算出最短路
int rootCount用来实时记录联通块的数量 delColdEmoji方法主要通过emojiHeat这个有序树结构来删除前几个热度的所有emoji和相应的emojiMessage,避免了遍历

基于JML规格设计测试

JML规格比较适合于设计单元测试,考虑用Junit工具实现:

  • requires: 测试不同情况下的require,保证数据覆盖完全
  • ensures: 每个ensure直接照着规格写即可
  • exceptions: 异常也要进行相应检测
  • invariant: 不变式可在每调用一次方法都进行检查

至于正常数据类型下的测试,为了保证数据的有效性,也可以通过中间小,两端大的概率分布生成极端情况多,普通数据少的测试数据

还要注意的是自己新加的类也最好写规格进行相应的单元测试(比如最小堆的插入算法一开始就写错了)

容器选择和使用

最优化目标为减少遍历循环的次数:

  • 只用无序查找和插入:HashMap
  • 只用头插入和头截取:LinkedList
  • 需要有序查找次序:有序ArrayList
  • 需要有序查找和删除:TreeMap

性能问题

问题 解决办法
最短路查询过慢 最小堆实现的Dijistra贪心算法
用最小堆实现的Dijistra中需要用HashSet判断结点是否访问过,可以构造大量哈希冲突的数据拖慢查询效率 用TreeSet有序容器
联通块数目查询过慢 并差集
若为有向图,则加边时需要查询两点是否相互联通,queryValueAndSet中dfs层数会很深,导致效率低下甚至爆栈 手动写栈;采用惰性实时更新,只在查询联通时一并更新并差集,并标记为最新
delColdEmoji方法需要遍历所有emoji 用TreeMap以热度作为key从小到大进行遍历
每次addRelation都要遍历所有组 采用惰性实时更新,只在查询相应组的socialValue时实时更新,并标记为最新

架构设计

类图如下

image

图的构建采用实时构建的方法,每加一个点、边就改变一次,通过MyPerson类中的HashMap实现边

posted @ 2021-05-30 12:17  Kyle-Kirsten  阅读(72)  评论(0编辑  收藏  举报