面向对象设计与构造 第三单元总结

面向对象设计与构造 第三单元总结

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

本单元作业比较简单,由于JML都对每个类的属性和方法都进行详细细致的描述,因此只要理解规格说明,理解每个类、每个方法的功能,就可以比较轻松的将它们用代码实现。当然完全按照JML写的方法实现可以保证正确性和强测不挂,但不能保证互测不被hack,所以在进行具体实现时需要在完成功能的前提下寻找性能更好的实现方法。

测试方法

本单元主要通过随机生成大量数据并与同学进行对拍来进行测试,通过这种方法基本上可以解决大部分bug。

容器选择及使用经验

在本次实验中,我基本上使用了以下几种容器:

  1. HashMap:高效键值对查询。由于作业需要经常通过ID映射相应的对象,因此在本次作业中,HashMap是非常便利的容器。
  2. HashSet:在第三次作业中dijkstra算法需要查询是否标记,因此在此处使用了这种容器,不需要查询值,需要判断是否存在。
  3. PriorityQueue:同样是在第三次作业中,用于实现优先队列,以优化dijkstra算法。

性能分析

第一次作业

第一次作业可能会出现性能问题的地方主要是queryPeopleSumisCircle两个方法,在处理这部分问题时,我使用了并查集进行标记,利用count对每个新加进的人进行编号,利用HashMap<Integer,Integer>来进行人的ID与连通块编号的对应,同时在加人和建立关系时对blocksum进行维护,在调用queryPeopleSum时直接输出blocksum,在调用isCircle时只需要通过HashMap进行查询连通块编号是否一致。

第二次作业

第二次作业会出现性能问题的地方主要是getValueSum这个方法,在实现这个方法时,我选择在Group类内定义一个valuesum,并在类内addPersondelPerson时对其进行维护:

HashMap<Integer, Integer> value = ((MyPerson) person).getValue();
for (int key : value.keySet()) {
	if (people.containsKey(key)) {
		valueSum = valueSum ± value.get(key);
	}
}

取得进行操作的Personvaluevalue使用PersonID作为key值,遍历valuekeyset同时查询组内是否含有同IdPerson,若有则对相应的value进行加减,此处实现存在部分问题,是遍历keyset后又进行value.get,会拖慢运行速度,应直接用entryset
在对valueSum进行维护后,在调用相关方法时只需要输出valueSum * 2即可。

第三次作业

第三次作业的关键便是最短路径,此处使用了堆优化的dijkstra算法,由于Java有现成的PriorityQueue,实现起来较为简单。

架构设计

整体架构基本按照JML规格进行,只有少数对性能要求比较高的方法没有完全按照规格实现,这部分方法在上述性能分析有说明。

心得体会

本单元主要学习了JML规格描述,JML规格描述虽然严谨,但是说明篇幅过长,有些方法只需要一两句话就可以描述清楚的功能,JML需要些好几十行,看起来费劲,理解起来也费劲。

posted @ 2021-05-31 17:03  这白开水怎么没味儿啊  阅读(74)  评论(0)    收藏  举报