掘金 后端 ( ) • 2024-04-25 09:52

定义

两者本质都是对数据进行处理分类,得到最终符合条件的数据

但是他们之间也有差别

  • 链式调用是以链表为单位,每次判断都会生成新的链表
  • 非链式调用是通过链表的节点为单位,不会生成新的链表,同时遍历链表的一部分已经满足结果时,终止遍历,节省消耗

实现的差别

如有 1 到 20 的整数,我们想得到 2 个大于 10 的偶数 所以,我们只需要依次判断三个条件即可

  • 大于 10
  • 是偶数
  • 取 2 个结果

下面是链式调用和非链式调用对此的实现,从中我们可以发现他们的差别

链式调用的实现

以链表为单位进行处理,每次都需要完整遍历集合并将中间结果缓存,下一次调用依赖上一次调用缓存的结果

 public List<Integer> dealCollection(List<Integer> list) {  
     List<Integer> evenList = new ArrayList<>();  
     for (Integer integer : list) {  
         //👇 筛选出偶数  
         if (integer % 2 == 0) {  
             evenList.add(integer);  
         }  
     }  
   
     List<Integer> bigList = new ArrayList<>();  
     for (Integer integer : evenList) {  
         //👇 从偶数中筛选出大于10的数  
         if (integer > 10) {  
             bigList.add(integer);  
         }  
     }  
     List<Integer> numList = new ArrayList<>();  
     for (Integer integer : bigList){  
         //👇 选出小于 2 的
         if (numList.size()<=2){  
             numList.add(integer);  
         }  
         if (numList.size() == 2){  
             break;  
         }  
     }  
     //👇 返回筛选结果列表  
     return numList;  
 }

可以发现每次进行处理时,我们都需要一个额外的链表存储结果,这个会导致额外的空间复杂度 每次处理都需要遍历整个链表,时间复杂度大 同时,因为这里我们只需要 2 个值,遍历整个链表会造成更大的额外时间复杂度

非链式调用的实现

以链表的每个节点为单位进行处理

 fun testSequence() {  
     val result : Sequence<Int> = (0..20)  
         .asSequence()//转换为sequence  
         .filter { it>10 }  
         .filter {  
             print(" $it")  
             it % 2 == 0//过滤偶数  
         }.take(2)  
     result.count()//调用 result 的逻辑,没有这个上面的代码不会执行  
     //  11 12 13 14 [12, 14]
 }
 }

  • 只做最少的操作
  • 不暂存数据,不进行多次遍历

从输出的结果 11 12 13 14 [12, 14] 看,只做了最少的操作,遍历到 14 就满足了,我们就不需要遍历后面的了

现有的类

  • kotlin :Sequence
  • Java : Stream
  • Android: FluentIterable

Java Stream

 private static void extracted() {  
     ArrayList<Integer> list = new ArrayList<>();  
     for (int a = 0; a < 20; a++) {  
         list.add(a);  
     }  
     Stream<Integer> stream = null;  
     stream = list.stream();  
     Stream s = stream.filter(value -> {  
         return value > 10; // 大于10  
     }).filter(value -> {  
         System.out.print(" " + value);  
         return value % 2 == 0; // 偶数  
     }).limit(2);  
     System.out.println(" " + Arrays.toString(s.toArray()));  
     //  11 12 13 14 [12, 14]
 }

kotlin  Sequence

 fun testSequence() {  
     val result : Sequence<Int> = (0..20)  
         .asSequence()//转换为sequence  
         .filter { it>10 }  
         .filter {  
             print(" $it")  
             it % 2 == 0//过滤偶数  
         }.take(2)  
     result.count()//调用 result 的逻辑,没有这个上面的代码不会执行  
     //  11 12 13 14 [12, 14]
 }

参考文档