美文网首页Kotlin编程
kotlin 之 range学习

kotlin 之 range学习

作者: hiLily | 来源:发表于2020-03-25 17:15 被阅读0次

    1.原理实现

    这里涉及两个操作符重载,代表范围(range)的 .. 和代表包含(contain)的 in,他们常常一起出现

    range的功能需要类扩展rangeTo来实现,操作符号是两个点-> ..

    rangeTo返回类型是interface ClosedRange<T: Comparable<T>>,它实现了contains方法

    contain的功能需要类扩展contains来实现,操作符号是 in 或是 !in

    2.常见使用方式

    上升范围

    i in 1..4
    

    下降范围

    i in 4 downTo 1
    

    进阶范围

    i in 1..10 step 3
    
    i in 1 downTo 10 step 3
    

    ->但是注意进阶的范围不会超过结尾的最大值和最小值

    开区间范围

    i in 1 until 10
    

    这里10是不包含的

    3.kotlin整型的range

    是一个Progression实例,例如IntProgression, LongProgression, and CharProgression

    Progression实现了Iterable<T>接口,因此这个范围是可以支持集合函数的,比如map,filter之类

    (1..10).filter{it%2 == 0}
    
    for (i in 1..10) print (i)
    

    4.自定义类支持range

    其实很简单,只要实现Comparable接口,然后rangeTo返回一个CloseRange<T>就ok了

    不过需要了解的是,这个仅仅能让我们的代码支持比较功能

    由于我没有支持Iterator所以类似

    for (newdate in dateStart..dateEnd)
    

    是无法支持的

    而downTo以及step也是无法支持的因为没有实现对应的扩展函数,而这两者在Int的实现方式都是通过IntProgression来实现的,这两者都需要实现迭代器才可以支持

    来看看他俩的实现就整明白了

    public infix fun Int.downTo(to: Byte): IntProgression {
    
        return IntProgression.fromClosedRange(this, to.toInt(), -1)
    
    }
    
    public infix fun IntProgression.step(step: Int): IntProgression {
    
        checkStepIsPositive(step > 0, step)
    
        return IntProgression.fromClosedRange(first, last, if (this.step > 0) step else -step)
    
    }
    

    downTo是Int的扩展函数,而step是IntProgression的扩展函数,这么一来才能这样潇洒的写

    for(x in 10 downTo 2 step 2)
    

    downTo看起来好像正好和range符号..正好相反,但实际上实现却大不同,downTo会直接返回一个Iterator<T>调用的是迭代器一个个比较,但是“..”只会调用一下比较方法compareTo就OK了,实现效率完全不同

    Kotlin确实写起来很潇洒,但是背后的调用关系还是得整明白,得知其所以然

    5.附我的自定义range代码

    class MyDate(val year:Int, val month:Int, val day:Int):Comparable<MyDate>{
        override fun compareTo(other: MyDate): Int {
            return when {
                year != other.year -> year - other.year
                month != other.month -> month - other.month
                day != other.day -> day - other.day
                else -> 0
            }
        }
    
        operator fun rangeTo(other: MyDate):MyDateRange {
            return MyDateRange(this, other)
        }
    }
    
    class MyDateRange(
        override val start: MyDate,
        override val endInclusive: MyDate
    ) : ClosedRange<MyDate>
    
    fun testRange() {
        val date2020_3_25 = MyDate(2020, 3, 25)
        val date2020_3_20 = MyDate(2020, 3, 20)
        val date2020_3_22 = MyDate(2020, 3, 22)
        val date2020_4_12 = MyDate(2020, 4, 12)
        val r1 = date2020_3_22 in date2020_3_20..date2020_3_25
        val r2 = date2020_3_22 < date2020_3_25
        val r3 = date2020_4_12 in date2020_3_20..date2020_3_25
        Log.i("lily", "date2020_3_22 in date2020_3_20..date2020_3_25 = $r1")
        Log.i("lily", "date2020_3_22 < date2020_3_25 = $r2")
        Log.i("lily", "date2020_4_12 in date2020_3_20..date2020_3_25 = $r3")
    //    for (xdate in date2020_3_20..date2020_3_25){//不支持,因为没有实现Iterator
    //
    //    }
    //    for (i in date2020_3_25 downTo date2020_3_22){//不支持,因为没有实现downTo扩展函数
    //
    //    }
    }
    

    相关文章

      网友评论

        本文标题:kotlin 之 range学习

        本文链接:https://www.haomeiwen.com/subject/ctexuhtx.html