面向对象的编程-Application 54

Previously on OOP:

In the last article, we have read a CSV file and store information inMunicipality, Community, School and Branchclasses. Afterwards, there are some requirements oninformation query/ data analysis.To implement these requirements, the most crucial point is Stream Source selection.

本需求的返回值是List类型的,其中String由两个字段构成,中间用“-”连接。“-”前面的字段是学校的数量,看起来似乎可以用counting() collector来求总数;后面的字段是Municipality的名称。可以存放两个字段的数据结构有两种,第一种是Map;第二种是新建一个class,然后把两个字段分分别存为两个attributes。这里因为Municipality的名称是unique的,所以我们可以先把两个字段存放在Map中,再把Map转化为字符串。

接下来是分析Stream Source的关键性时刻。Municipality的object reference可以在municipalities or branches中获得。而School的信息却只能从schools中获得。因为这两个字段的来源看起来风马牛不相及,所以我们要分别从municipalities, branches, schools出发,看看能不能实现需求。

(1)把schools作为Source

第一部分,Map >的key field是Municipality的名称。在前面一个一些需求中,我们已经编过了,先用flatMap()函数把Stream转化为Stream

,再用cascading dotted notation。

Value field是这座城市内的所有的学校的集合,因为School的编号是unique的,所以用set of schools比list of schools要好。Branch类中有一个attribute存放的是School的object reference,对应的getter是getSchool()。Mapping()函数会先调用getSchool(),把Stream

转化为Stream,再用toSet() collector。

第二部分,把Map >展开为新的Stream,每个Map entry是Stream的一个元素。再用map()函数把Mapentry整理成为一个个字符串。最后使用toList() collector。

(2)把branches作为Source

与“把schools作为Source”的做法基本相同,省略flatMap()函数。

(3)把municipalities作为Source

因为Municipality里面有存放对应branches的attributes,而且Branch里面有存放对应School的attribute,所以把这个数据结构作为Source也不是不行,就是从Municipality到School的距离有点远。

在本段代码中,有一个自定义的collector。Supplier是TreeMap;Combiner是把一个TreeMap的所有元素加入到另外一个TreeMap中去,要是没有使用parallel Stream,那么Combiner是不会被调用的;Finisher是implicitly存在的,没有明确地写出来。

最复杂的部分是Accumulator。往TreeMap中加入entry时,key field是Municipality的名称;value field要先把branches拿出来,再把School拿出来,最后还要用toSet() collector把学校信息汇总到一起。

要是各位宝宝们在考试中遇到要自定义collector的,强烈建议换一个Stream Source。另外,当需要的两个信息距离比较远时,尽量选择位于中间的branches作为Stream Source。

需要返回的是list of Strings,每个String有两个字段,中间用“-”连接。“-”前面的字段是学校的数量,后面是Community的名称。因为Community的名称具有unique性质,所以我们可以先把Stream整理为Map,key field是name of Community,value field是set of Schools。Community和School的关系图如下:

由此可见,我们的Stream Source共有四种可以选,比较好的是位于中间的Municipality and Branch。再看本需求的最后一句话,讲的是判定School在Community的根据,是要这所学校有至少一个Branch在Community的Municipality中。

读到这里,代码应该这样编写:

但是,本段需求还有非常难实现的倒数第二句话,因为它不是针对name of Community排序,而是针对value field排序,所以简单粗暴地使用key field自动排序的TreeMap是不行的。也就是说,为了实现这个需求,我们不得不turn to自定义collector/ collectingAndThen()。

这段代码各位宝宝欣赏一下就好了,不强制大家都要会编写。不过,请重点关注一下sorted()函数,这里需要的是逆序排列。在前文中,我们曾经讲过四种逆序排列的方法:

(1)把Comparable Interface的compareTo()函数的返回值改成相反数。

(2)把Comparator Interface的Lambda expression的expression部分加上一个负号。

(3)在comparing()中加上一个叫做reverseOrder()的参数。

(4)在comparing()后面调用reversed()函数。第三种方法比第四种好:

欢迎使用本黄鸭编写的小程序~

微信公众号二维码:

你的每一个“喜欢”,都是对我的鼓励

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190106G0WF8000?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券