Kotlin study notes (xii) kotlin collection of sequences using operators summary, comparative list and sequence ...

6188347-6bd4e744543abda1.jpg
MilkyWayLadakh_ZH-CN7734727282_1920x1080.jpg

Preface
this blog as my learning problems encountered in Kotlin, if not where to write, hoping to help the EU chiefs pointed out, thank you.

1. The use of a set of base

The main collection kotlin as: Array, List, Set, Map, Sequence

1.1 Array

val arr = arrayOf("1",2,3,4)

1.2 List

Immutable set ( ListOf () )

val arr = arrayOf("1","2",3,4,5)   
val list1 = listOf(1,2,"3",4,"5")                // 随意创建         
val list2 = listOf<String>("1","2","3","4","5")  // 确定元素的值类型
val list3 = listOf(arr)                          // 可传入一个数组

以下代码是错误的。因为List<E>只能是不可变集合。而add、remove、clear等函数时MutableList中的函数
list1.add() 
list1.remove

Variable set ( mutableListOf )

val arr = arrayOf("1","2",3,4)
val mutableList1 = mutableListOf(1,2,3,4,"5")                // 随意创建         
val mutableList2 = mutableListOf<String>("1","2","3","4","5")  // 确定元素的值类型
val mutableList3 = mutableListOf(arr)                          // 可传入一个数组
val mutableList : ArrayList<String>  // 这里的ArrayList<>和Java里面的ArrayList一致

mutableList1.add("6")  // 添加元素
mutableList1.add("7")
mutableList1.remove(1)   // 删除某一元素

1.3 Set

val set1 = setOf(1,2,"3","4","2",1,2,3,4,5)
val mutableSet1 = mutableSetOf(1,2,"3","4","2",1,2,3,4,5)

// 这里的HashSet<>和Java里面的HashSet<>一致
val mutableSet2 : HashSet<String>  

// 输出结果 : 1 2 3 4 2 3 4 5 

  When we see the output result, it was found that all of duplicate data are not, here is kotlin features and to maintain a consistent java.

1.4 Map

// 以键值对的形式出现,键与值之间使用to

val map1 = mapOf("key1" to 2 , "key2" to 3)
val map2 = mapOf<Int,String>(1 to "value1" , 2 to "value2")
val mutableMap = mutableMapOf("key1" to 2 , "key1" to 3)

// 同Java中的HashMap
val hashMap = hashMapOf("key1" to 2 , "key1" to 3)   

val map = val map1 = mapOf("key1" to 2 , "key1" to 3 ,
                             "key1" to "value1" , "key2" to "value2")

//输出结果 key1      value1   , key2     value2

When we duplicate keys, the set will filter out duplicate elements before. value retained only the last element. The filtered out before the same key values ​​for all elements.

2 List and choose Sequence

  I believe most of the Android developers understand the difference between sets and sequences, then we should be how to better use both?

List summary usage scenarios:

  1. Middleweight relatively small set of elements (when the number is relatively small when List and Sequence cycle takes almost the same)
  2. Access index element (Lists (collection) is indexed, Sequences (serial) must be itemized fact and of java ArrayList and LinkedList knowledge almost)
  3. Returning / transferring to other functions (each iteration Sequences (sequence), is calculated every element .Lists (set) the elements are counted only once, then stored in memory.)

Here we give an example of the difference between the two under through the time-consuming cycle point of view

Kotlin

list.map { it *3 }
  .filter { it % 2 == 0 }
  .count { it < 10 }

Kotlin code

      Object element$iv$iv;
      int it;
      while(var5.hasNext()) {
         element$iv$iv = var5.next();
         it = ((Number)element$iv$iv).intValue();
         Integer var12 = it * 3;
         destination$iv$iv.add(var12);
      }

      $receiver$iv = (Iterable)((List)destination$iv$iv);
      destination$iv$iv = (Collection)(new ArrayList());
      var5 = $receiver$iv.iterator();

      while(var5.hasNext()) {
         element$iv$iv = var5.next();
         it = ((Number)element$iv$iv).intValue();
         if (it % 2 == 0) {
            destination$iv$iv.add(element$iv$iv);
         }
      }

      $receiver$iv = (Iterable)((List)destination$iv$iv);
      if (!($receiver$iv instanceof Collection) || !((Collection)$receiver$iv).isEmpty()) {
         int count$iv = 0;
         Iterator var13 = $receiver$iv.iterator();

         while(var13.hasNext()) {
            Object element$iv = var13.next();
            int it = ((Number)element$iv).intValue();
            if (it < 10) {
               ++count$iv;
            }
         }
      }

  你会发现Kotlin编译器会创建三个while循环.而Sequences则只会存在一个循环,所以在循环多的情况下 还是Sequences 比较快一点。
kotlin

    val result = list.asSequence()
            .map{ println("In Map"); it * 2 }
            .filter { println("In Filter");it % 3  == 0 }
    println("Before Average")
    println(result.average())

Kotlin code

      List list = CollectionsKt.listOf(new Integer[]{1, 2, 3, 4, 5, 6});
      Sequence result = SequencesKt.filter(SequencesKt.map(CollectionsKt.asSequence((Iterable)list), (Function1)null.INSTANCE), (Function1)null.INSTANCE);
      String var3 = "Before Average";
      System.out.println(var3);
      double var5 = SequencesKt.averageOfInt(result);
      System.out.println(var5);

  序列(Sequences) 的秘诀在于它们是共享同一个迭代器(iterator) ---序列允许 map操作 转换一个元素后,然后立马可以将这个元素传递给 filter操作 ,而不是像集合(lists) 一样等待所有的元素都循环完成了map操作后,用一个新的集合存储起来,然后又遍历循环从新的集合取出元素完成filter操作。

3. 操作符汇总

  下面对这6类操作符进行一一的讲解,不过这里就不对他们的源码进行分析。大多都存在于_Collections.kt这个文件中。下边的测试代码和运行结果 我都 将结果和 方法放在一起了 好对比

3.1 元素操作符

  • contains(元素) : 检查集合中是否包含指定的元素,若存在则返回true,反之返回false
  • elementAt(index) : 获取对应下标的元素。若下标越界,会抛出IndexOutOfBoundsException(下标越界)异常,同get(index)一样
  • elementAtOrElse(index,{...}) : 获取对应下标的元素。若下标越界,返回默认值,此默认值就是你传入的下标的运算值
  • elementAtOrNull(index) : 获取对应下标的元素。若下标越界,返回null
  • first() : 获取第一个元素,若集合为空集合,这会抛出NoSuchElementException异常
  • first{} : 获取指定元素的第一个元素。若不满足条件,则抛出NoSuchElementException异常
  • firstOrNull() : 获取第一个元素,若集合为空集合,返回null
  • firstOrNull{} : 获取指定元素的第一个元素。若不满足条件,返回null
  • getOrElse(index,{...}) : 同elementAtOrElse一样
  • getOrNull(index) : 同elementAtOrNull一样
  • last () : 同first()相反
  • last {} : 同first{}相反
  • lastOrNull{} : 同firstOrNull()相反
  • lastOrNull() : 同firstOrNull{}相反
  • indexOf(元素) : 返回指定元素的下标,若不存在,则返回-1
  • indexOfFirst{...} : 返回第一个满足条件元素的下标,若不存在,则返回-1
  • indexOfLast{...} : 返回最后一个满足条件元素的下标,若不存在,则返回-1
  • single() : 若集合的长度等于0,则抛出NoSuchElementException异常,若等于1,则返回第一个元素。反之,则抛出IllegalArgumentException异常
  • single{} : 找到集合中满足条件的元素,若元素满足条件,则返回该元素。否则会根据不同的条件,抛出异常。这个方法慎用
  • singleOrNull() : 若集合的长度等于1,则返回第一个元素。否则,返回null
  • singleOrNull{} : 找到集合中满足条件的元素,若元素满足条件,则返回该元素。否则返回null
  • forEach{...} : 遍历元素。一般用作元素的打印
  • forEachIndexed{index,value} : 遍历元素,可获得集合中元素的下标。一般用作元素以及下标的打印
  • componentX() : 这个函数在前面的章节中提过多次了。用于获取元素。其中的X只能代表1..5。详情可看下面的例子

eg:

val list = listOf("kotlin","Android","Java","PHP","Python","IOS")

println(list.contains("JS"))   // false

println(list.elementAt(2))  // Java
println(list.elementAtOrElse(10,{it}))   // 10 
println(list.elementAtOrNull(10))   // null

println(list.get(2))  //  Java
println(list.getOrElse(10,{it}))  // 10
println(list.getOrNull(10))  // null

println(list.first())   //  kotlin
println(list.first{ it == "Android" })  // Android
println(list.firstOrNull())   // kotlin
println(list.firstOrNull { it == "Android" })   // Android

println(list.last())   // IOS
println(list.last{ it == "Android" })   // Android
println(list.lastOrNull())  // IOS
println(list.lastOrNull { it == "Android" })  // Android

println(list.indexOf("Android"))  // 1
println(list.indexOfFirst { it == "Android" })  //  1
println(list.indexOfLast { it == "Android" })   //  1

val list2 = listOf("list")
// 只有当集合只有一个元素时,才去用这个函数,不然都会抛出异常。
println(list2.single())      // list
 //当集合中的元素满足条件时,才去用这个函数,不然都会抛出异常。若满足条件返回该元素
println(list2.single { it == "list" })   // list
// 只有当集合只有一个元素时,才去用这个函数,不然都会返回null。
println(list2.singleOrNull())    // list
//当集合中的元素满足条件时,才去用这个函数,不然返回null。若满足条件返回该元素
println(list2.singleOrNull { it == "list" })   // list 

list.forEach { println(it) } 
// kotlin
// Android
// Java
// PHP
// Python
// IOS

list.forEachIndexed { index, it -> println("index : $index \t value = $it") }
/**
index : 0    value = kotlin
index : 1    value = Android
index : 2    value = Java
index : 3    value = PHP
index : 4    value = Python
index : 5    value = IOS
**/

  // 等价于`list[0]  <=> list.get(0)`
println(list.component1())    //  kotlin
....
 // 等价于`list[4]  <=> list.get(4)`
println(list.component5())   // Python

3.2 顺序操作符

  • reversed() : 反序。
  • sorted() : 升序。
  • sortedBy{} : 根据条件升序。把不满足条件的放在前面,满足条件的放在后面
  • sortedDescending() : 降序。
  • sortedByDescending{} : 根据条件降序。

eg:

    val list1 = listOf(-1,-2,1,3,5,6,7,2,4)
    // 反序
    println(list1.reversed())    // [4, 2, 7, 6, 5, 3, 1, -2, -1]
    // 升序
    println(list1.sorted())   // [-2, -1, 1, 2, 3, 4, 5, 6, 7]
    // 根据条件升序,即把不满足条件的放在前面,满足条件的放在后面
    println(list1.sortedBy { it % 2 == 0})  // [-1, 1, 3, 5, 7, -2, 6, 2, 4]
    // 降序
    println(list1.sortedDescending())   // [7, 6, 5, 4, 3, 2, 1, -1, -2]
    // 根据条件降序,和`sortedBy{}`相反
    println(list1.sortedByDescending { it % 2 == 0 })   // [-2, 6, 2, 4, -1, 1, 3, 5, 7]

3.3 映射操作符

  • map{...} : 把每个元素按照特定的方法进行转换,组成新的集合。
  • mapNotNull{...} : 同map{}函数的作用相同,过滤掉转换之后为null的元素
  • mapIndexed{index,result} : 把每个元素按照特定的方法进行转换,只是其可以操作元素的下标(index),组成新的集合。
  • mapIndexedNotNull{index,result} : 同mapIndexed{}函数的作用相同,只是过滤掉转换之后为null的元素
  • flatMap{...} : 根据条件合并两个集合,组成新的集合。
  • groupBy{...} : 分组。即根据条件把集合拆分为为一个Map<K,List<T>>类型的集合。

eg:

    val list1 = listOf("kotlin","Android","Java","PHP","JavaScript")

    println(list1.map { "str-".plus(it) })
    //[str-kotlin, str-Android, str-Java, str-PHP, str-JavaScript]

    println(list1.mapNotNull { "str-".plus(it) })
    // [str-kotlin, str-Android, str-Java, str-PHP, str-JavaScript]
    
    println(list1.mapIndexed { index, str ->
        index.toString().plus("-").plus(str)
    })
    //[0-kotlin, 1-Android, 2-Java, 3-PHP, 4-JavaScript]
    
    println(list1.mapIndexedNotNull { index, str ->
        index.toString().plus("-").plus(str)
    })
    // [0-kotlin, 1-Android, 2-Java, 3-PHP, 4-JavaScript]
    
    println( list1.flatMap { listOf(it,"new-".plus(it)) })
    //[kotlin, new-kotlin, Android, new-Android, Java, new-Java, PHP, new-PHP, JavaScript, new-JavaScript]
    
    println(list1.groupBy { if (it.startsWith("Java")) "big" else "latter" })
    // {latter=[kotlin, Android, PHP], big=[Java, JavaScript]}

3.4 过滤操作符

  • filter{...} : 把不满足条件的元素过滤掉
  • filterIndexed{...} : 和filter{}函数作用类似,可以操作集合中元素的下标
  • filterNot{...} : 和filter{}函数的作用相反
  • filterNotNull() : 过滤掉集合中为null的元素。
  • take(num) : 返回集合中前num个元素组成的集合
  • takeWhile{...} : 循环遍历集合,从第一个元素开始遍历集合,当第一个出现不满足条件元素的时候,退出遍历。然后把满足条件所有元素组成的集合返回。
  • takeLast(num) : 返回集合中后num个元素组成的集合
  • takeLastWhile{...} : 循环遍历集合,从最后一个元素开始遍历集合,当第一个出现不满足条件元素的时候,退出遍历。然后把满足条件所有元素组成的集合返回。
  • drop(num) : 过滤集合中前num个元素
  • dropWhile{...} : 相同条件下,和执行takeWhile{...}函数后得到的结果相反
  • dropLast(num) : 过滤集合中后num个元素
  • dropLastWhile{...} : 相同条件下,和执行takeLastWhile{...}函数后得到的结果相反
  • distinct() : 去除重复元素
  • distinctBy{...} : 根据操作元素后的结果去除重复元素
  • slice : 过滤掉所有不满足执行下标的元素。

eg:

    val list1 = listOf(-1,-3,1,3,5,6,7,2,4)
    val list2 = listOf(1,3,4,5,null,6,null,10)
    val list3 = listOf(1,1,5,2,2,6,3,3,7,4)

    println(list1.filter { it > 1  })   // [3, 5, 6, 7, 2, 4]
    println(list1.filterIndexed { index, result ->
        index < 5 && result > 3
    })
    //  [5] 

    println(list1.filterNot { it > 1 })   //  [-1, -3, 1]
    println(list2.filterNotNull())   //   [1, 3, 4, 5, 6, 10]

    println(list1.take(5))    //  [-1, -3, 1, 3, 5]
    println(list1.takeWhile { it < 5 })   //  [-1, -3, 1, 3]
    println(list1.takeLast(5))   //  [5, 6, 7, 2, 4]
    println(list1.takeLastWhile { it > 5 })   //  []

    println(list1.drop(5))   // [6, 7, 2, 4]
    println(list1.dropWhile { it < 5 })   //  [5, 6, 7, 2, 4]
    println(list1.dropLast(5))  // [-1, -3, 1, 3]
    println(list1.dropLastWhile { it > 5 })  // [-1, -3, 1, 3, 5, 6, 7, 2, 4]

    println(list3.distinct())  //  [1, 5, 2, 6, 3, 7, 4]
    println(list3.distinctBy { it + 2 })  //  [1, 5, 2, 6, 3, 7, 4]

    println(list1.slice(listOf(1,3,5,7)))  //  [-3, 3, 6, 2]
    println(list1.slice(IntRange(1,5)))  //   [-3, 1, 3, 5, 6]

3.5 生产操作符

  • plus() : 合并两个集合中的元素,组成一个新的集合。也可以使用符号+
  • zip : 由两个集合按照相同的下标组成一个新集合。该新集合的类型是:List<Pair>
  • unzip : 和zip的作用相反。把一个类型为List<Pair>的集合拆分为两个集合。看下面的例子
  • partition : 判断元素是否满足条件把集合拆分为有两个Pair组成的新集合

eg:

    val list1 = listOf(1,2)
    val list2 = listOf("kotlin","Android","Java")

    println(list1.plus(list2))  // [1, 2, kotlin, Android, Java]
    println(list1 + list2)   //  [1, 2, kotlin, Android, Java]
    // 组成的新集合由元素少的原集合决定
    println(list1.zip(list2))   //  [(1, kotlin), (2, Android)]
    // 组成的新集合由元素少的原集合决定
    println(list1.zip(list2){
        it1,it2-> it1.toString().plus("-").plus(it2)
    })  //  [1-kotlin, 2-Android]
    
    val newList = listOf(Pair(1,"Kotlin"),Pair(2,"Android"),Pair(3,"Java"))
    println(newList.unzip())   //  ([1, 2, 3,], [Kotlin, Android, Java])

    println(list2.partition { it.startsWith("Ja") })  //  ([Java], [kotlin, Android])

3.6 统计操作符

  • any() : 判断是不是一个集合,若是,则在判断集合是否为空,若为空则返回false,反之返回true,若不是集合,则返回hasNext
  • any{...} : 判断集合中是否存在满足条件的元素。若存在则返回true,反之返回false
  • all{...} : 判断集合中的所有元素是否都满足条件。若是则返回true,反之则返回false
  • none() : 和any()函数的作用相反
  • none{...} : 和all{...}函数的作用相反
  • max() : 获取集合中最大的元素,若为空元素集合,则返回null
  • maxBy{...} : 获取方法处理后返回结果最大值对应那个元素的初始值,如果没有则返回null
  • min() : 获取集合中最小的元素,若为空元素集合,则返回null
  • minBy{...} : 获取方法处理后返回结果最小值对应那个元素的初始值,如果没有则返回null
  • sum() : 计算出集合元素累加的结果。
  • sumBy {...}: The result of the arithmetic operation element, and the accumulated value is calculated based on this result.
  • sumByDouble {...}: sumBy {} and similar, but sumBy {} is an operation Int data type, and the operation is sumByDouble {} Double type data
  • average (): Gets the average
  • reduce {...}: the set of cumulative operation from the first to the last one.
  • reduceIndexed {...}: the same effect and reduce {}, but which may be operated under standard element (index)
  • reduceRight {...}: first cumulative operation to an item in the final set.
  • reduceRightIndexed {...}: reduceRight {} and the same function, but which may be operated under standard element (index)
  • fold {...}: {} and the reduce the like, but the fold has an initial value of {}
  • foldIndexed {...}: reduceIndexed {} and the like, but foldIndexed {} have an initial value
  • foldRight {...}: reduceRight {} and the like, but foldRight {} have an initial value
  • foldRightIndexed {...}: reduceRightIndexed {} and the like, but foldRightIndexed {} have an initial value

eg:

    val list1 = listOf(1,2,3,4)
    println(list1.any())   // true
    println(list1.any{it > 10})   //  false
    println(list1.all { it > 2 })   //  false
    println(list1.none())   // false
    println(list1.none{ it > 2})    //  false
    println(list1.max())   //  4
    println(list1.maxBy { it + 2 })   // 4
    println(list1.min())    //  1
    println(list1.minBy { it + 2 })   //  1
    println(list1.sum())   //  10
    println(list1.sumBy { it + 2 })   // 18
    println(list1.sumByDouble { it.toDouble() })   //  10.0
    println(list1.average())    //  2.5
    println(list1.reduce { result, next -> result  + next})   //  10
    println(list1.reduceIndexed { index, result, next ->
        index + result + next
    })  //   16
    println(list1.reduceRight { result, next -> result  + next })   //   10
    println(list1.reduceRightIndexed {index, result, next ->
        index + result + next
    })  //  13
    println(list1.fold(3){result, next -> result  + next})  //  13
    println(list1.foldIndexed(3){index,result, next ->
        index + result  + next
    })  //  19
    println(list1.foldRight(3){result, next -> result  + next})   //  13
    println(list1.foldRightIndexed(3){index,result, next ->
        index + result  + next
    })  //  19

Reproduced in: https: //www.jianshu.com/p/a14ded7b4e0b

Guess you like

Origin blog.csdn.net/weixin_33873846/article/details/91073217