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()函数。第三种方法比第四种好:
欢迎使用本黄鸭编写的小程序~
微信公众号二维码:
你的每一个“喜欢”,都是对我的鼓励
领取专属 10元无门槛券
私享最新 技术干货