从“猴子到树上摘桃”到“猴子先对树上的桃子进行标记,再统一摘桃”的演变
最近在公司项目开发过程中,遇到了一个相对比较复杂的场景,大概就是对于一棵完整的树(树的结构就是若干属性集合 和 一个子节点,子节点是 同等结构的树的集合),根据有权限的 list 集合(集合的形式是从根节点到叶子节点的一个字符串,当然实际场景可能在最后加一个标识,比如“all”结尾表示下面的节点无论递归多少层都是有权限,“part”结尾表示只是到当前所在层即可),对于树上有权限的节点进行裁剪,最终返回一棵只是有权限的树的集合。
针对这个问题,可能是出于 Java8 中stream 中的过滤思想,首先想到的就是 对于每一个子节点的集合进行过滤,根据 有权限的list,过滤到无权限的节点,然后将只是有权限的节点再 set 回 children。OK,那么这种思想的具体实现其实有两种方式。第一种是 复制一个同样的树,然后对原始树进行遍历递归,然后将有权限的 节点set 到children. 但是这样会存在几个问题,如果某个节点没权限(即不存在 “该节点code-all”或者“该节点code-part”),那么它一定是没有权限的吗?答案肯定是否定的,因为他的子节点可能是有权限,只是没有递归到这一层,那么该节点肯定保留,但是如果它就是没权限,该层的list遍历结束了,还是没权限,那么它就是真的没权限了,那么我应该如何标记他是真的没权限还是只是子节点有权限;第二种解决方案是 复制一个同样的树,但是我把他的子节点都 set 为 null,可以避免上述方法一存在的问题,但是新的问题又产生了,在不停的递归过程中,我需要始终维护这个对象的 children 属性,那么维护这个 对象的 children 属性的时候又会存在 什么时候该维护,什么时候不需要维护的问题,原因与方法一类似。
至此,泪崩,我就是一个废物,这都搞不定?此时天色已晚,已到午夜亥时,不如回家刷“隐角”(原谅我最近中了隐角的毒...)第二天,精神抖擞,在早晨洗澡间隙,思考到一种方案,果断赶紧到公司继续coding。鲁迅先生说的没错,“只有休息好才能写出优秀的代码”,此处留下鲁迅先生一连串的问号脸,我TM 哪里说过?
回到正经话题,之所以昨天的方案搞不定,无非就是分不清是其子节点有权限还是他就是没权限。因此,换种思路来看,我可以给其加一个字段,用于标识,其是不是有权限,这样,针对子节点有权限的问题,那么就给其父节点标识为有权限,然后深度遍历;当对父节点所在层级遍历完后,没权限的肯定就是 没权限,因此,完美解决该问题;另外,在深度遍历过程中,如果遇到 “all”,那么直接对所有的叶子节点深度遍历且全部赋予为有权限,如果遇到“part”, 则到此为止,至此,完美解决。
将上述方案进行总结,无非就是从先是“直接对有权限的树进行裁剪”到“先标记有权限的树的节点,不破坏树的结构,最后再统一裁剪”。将其勉强戏称为“从“猴子到树上摘桃”到“猴子先对树上的桃子进行标记,再统一摘桃”的演变”。第一次在博客园写纯文字,一方面为了记录心路历程,一方面给可能遇到该问题困扰的同学提供一点解决方案。
告辞!