zoukankan      html  css  js  c++  java
  • Scala(七)集合

    7.1 集合简介

      1说明

        (1Scala的集合有三大类:序列Seq、集Set映射Map,所有的集合都扩展自Iterable特质

        (2)对于几乎所有的集合类,Scala都同时提供了可变不可变的版本,分别位于以下两个包

          不可变集合:scala.collection.immutable

          可变集合:  scala.collection.mutable

      2案例实操

        (1Scala不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。

        (2)可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。

    package com.yuange.scala.day04
    
    import scala.collection.mutable.ListBuffer
    
    object TestListOne {
      def main(args: Array[String]): Unit = {
        //不可变List
        val testList: List[Int] = List(1,3,5,23,2)
        println(testList)
        //对不可变的List进行修改,在头部添加一个元素0
        val testList2 = 0 +: testList
        println(testList2)
    
        //可变List
        val testList3: ListBuffer[Int] = ListBuffer(1,3,5,7,4)
        println(testList3)
        //对可变list进行修改,在头部添加一个元素0
        val testList4 = 0 +: testList3
        println(testList4)
      }
    }

    7.1.1 不可变集合继承图

      1SetMapJava中也有的集合

      2SeqJava没有的,我们发现List归属到Seq了,因此这里的List就和Java不是同一个概念了

      3)我们前面的for循环有一个 1 to 3,就是IndexedSeq下的Vector

      4String也是属于IndexeSeq

      5)我们发现经典的数据结构比如QueueStack被归属到LinerSeq

      6)大家注意Scala中的Map体系有一个SortedMap,说明ScalaMap可以支持排序

      7IndexSeqLinearSeq的区别:

        (1IndexSeq是通过索引来查找和定位,因此速度快,比如String就是一个索引集合,通过索引即可定位

        (2LineaSeq是线型的,即有头尾的概念,这种数据结构一般是通过遍历来查找

    7.1.2 可变集合继承图

    7.2 数组

    7.2.1 不可变数组

      1第一种方式定义数组(定长数组)

    val arr1 = new Array[Int](10)

        (1new是关键字

        (2[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定Any

        (3(10),表示数组的大小,确定后就不可以变化

      2)案例实操

    package com.yuange.scala.day04
    
    object TestArray {
      def main(args: Array[String]): Unit = {
        //定义数组
        val testArray = new Array[Int](4)
        println(testArray.length)
        //数组赋值
        testArray(2) = 100      //修改某个元素的值
        testArray.update(0,200) //采用方法的形式给数组赋值
        //遍历数组
        println(testArray.mkString(","))  //查看数组
        for (i <- testArray){   //普通遍历
          print(i + "\t")
        }
        println()
        //简化遍历
        def ergodic(i: Int): Unit = {
          println(i)
        }
    //    testArray.foreach(ergodic)
    //    testArray.foreach((i)=>{println(i)})  //简化
    //    testArray.foreach(i=>println(i))
    //    testArray.foreach(println(_))
        testArray.foreach(println)
    
        //增加元素:由于创建的是不可变数组,所以是在产生新数组
        println("------------------------")
        println(testArray.mkString(","))
        val ints = testArray :+ 5
        println(ints.mkString(","))
      }
    }

      3)种方式定义数组

    val arr1 = Array(1, 2)

        (1)在定义数组时,直接赋值

        (2)使用apply方法创建数组对象

      4案例实操

    package com.yuange.scala.day04
    
    object TestArrayTwo {
      def main(args: Array[String]): Unit = {
        var testArray = Array("zhansan","李四","王五")
        for (i <- testArray){
          println(i)
        }
      }
    }

    7.2.2 可变数组

      1)定义变长数组

    val arr01 = ArrayBuffer[Any](3, 2, 5)

        (1[Any]存放任意数据类型

        (2)(3, 2, 5)初始化好的三个元素

        (3ArrayBuffer需要引入scala.collection.mutable.ArrayBuffer

      2)案例实操

        (1ArrayBuffer是有序的集合

        (2)增加元素使用的是append方法(),支持可变参数

    package com.yuange.scala.day04
    
    import scala.collection.mutable.ArrayBuffer
    
    object TestArrayBuffer {
      def main(args: Array[String]): Unit = {
        //创建并赋值可变数组
        val testBuffer = ArrayBuffer[Any](1,2,3)
        //遍历数组
        for (i <- testBuffer){
          println(i)
        }
        println("length=" + testBuffer.length)
        println("hash=" + testBuffer.hashCode())
        //增加元素
        testBuffer.+=(4)  //追加数据
        println(testBuffer)
        testBuffer.append(5)  //想数组末尾添加数据
        println(testBuffer)
        testBuffer.insert(3,6,7)  //在角标为3的位置插入6和7,即插入之后6的角标为3,7的角标为4,角标从0开始计算
        println(testBuffer)
        println("hash=" + testBuffer.hashCode())  //hashCode不一致
        //修改元素
        testBuffer(0) = 100   //修改第一个元素的值
        println("*"*100)
        for (i <- testBuffer){
          println(i)
        }
        println("length=" + testBuffer.length)
      }
    }

    7.2.3 不可变数组与可变数组的转换

      1说明

        arr1.toBuffer  //不可变数组转可变数组

        arr2.toArray  //可变数组转不可变数组

        (1arr2.toArray返回结果才是一个不可变数组,arr2本身没有变化

        (2arr1.toBuffer返回结果才是一个可变数组,arr1本身没有变化

      2案例实操

    package com.yuange.scala.day04
    
    import scala.collection.mutable.ArrayBuffer
    
    object TestArrayBufferTwo {
      def main(args: Array[String]): Unit = {
        //创建一个空的可变数组
        val testBuffer = ArrayBuffer[Int]()
        //追加值
        testBuffer.append(1,2,3)
        println(testBuffer)
        //转不可变数组
        val newArray = testBuffer.toArray  //返回的结果是一个新的定长数组集合且原数组集合没有变化
        println("不可变数组=" + newArray)
        //转可变数组
        val newBuffer = newArray.toBuffer   //返回一个变长数组且原数组无任何变化,依然是定长数组
        newBuffer.append(100)
        println(newBuffer)
      }
    }

    7.2.4 多维数组

      1)多维数组定义(二维数组中有三个一维数组,每个一维数组中有四个元素)

    val arr = Array.ofDim[Double](3,4)

      2)案例实操

    package com.yuange.scala.day04
    
    object DimArray {
      def main(args: Array[String]): Unit = {
        //创建一个二维数组,有三个元素,这三个元素中的每个元素含有四个元素
        var testDim = Array.ofDim[Int](3,4)
        testDim(1)(2) = 100   //给第二行的第三列元素进行修改,数组脚标从0开始
        //遍历二维数组
        for (i <- testDim){
          for (j <- i){
            print(j + "\t")
          }
          println()
        }
      }
    }

    7.3 Seq集合(List

    7.3.1 不可变List

      1说明

        (1)List默认为不可变集合

        (2)创建一个List(数据有顺序,可重复)
        (3)遍历List

        (4List增加数据

        (5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化
        (6)取指定数据
        (7)空集合Nil

      2案例实操

    package com.yuange.scala.day04
    
    object TestList {
      def main(args: Array[String]): Unit = {
        //List默认是不可变集合,创建一个List(数据有序,可重复)
        val testList: List[Int] = List(1,2,3,4,5)
        println("testList=" + testList)
        //空集合Nil
        val testList2 = 1 :: 2 :: 3 :: 4 :: 5 :: Nil
        println("testList2=" + testList2)
        //增加数据
        val testList3 = 6 :: testList //::的运算规则是从右到左
        println("testList3=" + testList3)
        val testList4 = 7 :: 8 :: 9 :: testList3  //将7,8,9插入到集合前面
        println("testList4=" + testList4)
        val testList5 = testList4.+:(10)    //将10插入到集合的第0位置
        println("testList5=" + testList5)
        //集合间合并,将一个整体拆分为一个个体,扁平化
        val testList6 = List(11,12)
        println("testList6=" + testList6)
        val testList7 = testList6 :: testList //::将testList6整个集合当成一个整体插入到testList集合前面
        println("testList7=" + testList7)
        val testList8 = testList6 ::: testList
        println("testList8=" + testList8)   //:::将testList6集合拆分成一个个个体然后插入到testList集合前面
        //取指定数据
        println("testList(3)=" + testList(3))
        //遍历List集合
        testList8.foreach(println)
      }
    }

    7.3.2 可变ListBuffer

      1说明

        (1)创建一个可变集合ListBuffer

        (2)向集合中添加数据

        (3)打印集合数据

      2案例实操

    package com.yuange.scala.day04
    
    import scala.collection.mutable.ListBuffer
    
    object TestListTwo {
      def main(args: Array[String]): Unit = {
        //创建可变集合
        val testBuffer = ListBuffer(1,2,3,4,5)
        //向集合中添加数据
        testBuffer.+=(6)  //添加数据在集合后面
        testBuffer.+=:(7)  //添加数据在集合前面
        //打印
        testBuffer.foreach(println)
      }
    }

    7.4 Set集合

      默认情况下,Scala使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set

    7.4.1 不可变Set

      1)说明

        (1Set默认是不可变集合,数据无序

        (2)数据不可重复

        (3)遍历集合

      2案例实操

    package com.yuange.scala.day04
    
    object TestSet {
      def main(args: Array[String]): Unit = {
        //set默认是不可变集合,数据无序
        val testSet = Set(1,3,5,7,9)
        println("testSet=" + testSet)
        //数据不可重复
        val testSet2 = Set(1,1,2,4,5,9);
        println("testSet2=" + testSet2)
      }
    }

    7.4.2 可变mutable.Set

      1说明

        (1)创建可变集合mutable.Set

        (2)打印集合

        (3)集合添加元素

        (4)向集合中添加元素,返回一个新的Set

        (5)删除数据

      2案例实操

    package com.yuange.scala.day04
    
    import scala.collection.mutable
    
    object TestSetTwo {
      def main(args: Array[String]): Unit = {
        //创建可变集合
        val testSet = mutable.Set(1,2,3,4)
        println("testSet=" + testSet)
        //向集合中添加元素
        testSet += 5
        println("testSet=" + testSet)
        //向集合中添加元素,返回一个新的set
        val testSet2 = testSet.+(6)
        println("testSet2=" + testSet2)
        //删除数据
        testSet2 -= 5
        //遍历集合
        testSet2.foreach(println)
        //打印集合并按,分割
        println(testSet2.mkString(","))
      }
    }

    7.5 Map集合

      Scala中的MapJava类似,也是一个散列表,它存储的内容也是键值对(key-value映射,Scala不可变的Map是有序的,可变的Map是无序的

    7.5.1 不可变Map

      1说明

        (1)创建不可变集合Map

        (2)循环打印

        (3)访问数据

        (4)如果key不存在,返回0

      2案例实操

    package com.yuange.scala.day04
    
    object TestMap {
      def main(args: Array[String]): Unit = {
        //创建不可变集合Map
        val testMap = Map("zhangsan"->1001,"lisi"->1002,"wangwu"->1003)
        //访问数据
        for (elem <- testMap.keys){
          //使用get访问map集合中的数据,会返回特殊类型Option(选项):有值(Some),无值(None)
          println(elem + "=" + testMap.get(elem).get)
        }
        //若key不存在,返回0
        println(testMap.get("zhaoliu").getOrElse(0))
        println(testMap.getOrElse("zhaoliu",0))
        //循环打印
        testMap.foreach((kv)=>{println(kv)})
        testMap.foreach(kv=>{println(kv)})
      }
    }

    7.5.2 可变Map

      1说明

        (1)创建可变集合

        (2)打印集合

        (3)向集合增加数据

        (4)删除数据

        (5)修改数据

      2案例实操

    package com.yuange.scala.day04
    
    import scala.collection.mutable
    
    object TestMapTwo {
      def main(args: Array[String]): Unit = {
        //创建可变集合
        val testMap = mutable.Map("zhangsan"->2001,"lisi"->2002,"wangwu"->2003)
        //向集合增加数据
        testMap.+=("zhaoliu"->2004)
        println("testMap=" + testMap)
        //将数值2005添加到集合,并把集合中原值2001返回
        val maybeInt: Option[Int] = testMap.put("zhangsan",2005)
        println(maybeInt.getOrElse(0))
        //删除数据
        testMap.-=("wangwu","lisi")
        println("删除数据之后:" + testMap)
        //修改数据
        testMap.update("zhaoliu",2006)
        println("修改数据之后:" + testMap)
        //打印集合
        testMap.foreach(kv=>{println(kv)})
      }
    }

    7.6 元组

      1元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组(元组中最大只能有22个元素)

      2案例实操

        (1)声明元组的方式:(元素,元素2,元素3)

        (2)访问元组

        (3)Map中的键值对其实就是元组,只不过元组的元素个数为2,称之为对偶

    package com.yuange.scala.day04
    
    object TestTuple {
      def main(args: Array[String]): Unit = {
        //声明元组的方式:(元素1,元素2,元素3,...)
        val testTuple: (Int,String,Boolean) = (1001,"张三",true)
        //通过元素的顺序访问元组,调用方式:元组名称._顺序号
        println("testTuple._1=" + testTuple._1 + ",testTuple._2=" + testTuple._2 + ",testTuple._3=" + testTuple._3)
        //通过索引访问数据
        println("testTuple.productElement(0)=" + testTuple.productElement(0))
        //通过迭代器访问数据
        for (elem <- testTuple.productIterator){
          println(elem)
        }
        //Map中的键值对就是元组,只不过元素的个数为2,称之为对偶
        val testMap = Map("张三"->3001,"李四"->3002,"王五"->3003)
        testMap.foreach(kv=>{println(kv._1 + "=" + kv._2)})
      }
    }

    7.7 集合常用函数

    7.7.1 基本属性和常用操作

      1说明

        (1)获取集合长度

        (2)获取集合大小

        (3)循环遍历

        (4)迭代器

        (5)生成字符串

        (6)是否包含

      2案例实操

    package com.yuange.scala.day04
    
    object Aggregate {
      def main(args: Array[String]): Unit = {
        val testList: List[Int] = List(1,3,5,7,9,11,13)
        //获取集合长度
        println("testList.length=" + testList.length)
        //获取集合大小
        println("testList.size=" + testList.size)
        //循环遍历
        testList.foreach(println)
        //迭代器
        for (i <- testList){
          println(i)
        }
        //生成字符串
        println(testList.mkString(","))
        //是否包含
        println(testList.contains(5))
      }
    }

    7.7.2 衍生集合

      1)说明

        (1)获取集合的头head

        (2)获取集合的尾(不是头就是尾)tail

        (3)集合最后一个数据 last

        (4)集合初始数据(不包含最后一个)

        (5)反转

        (6)取前(后)n个元素

        (7)去掉前(后)n个元素

        (8)并集

        (9)交集

        (10)差集

        (11)拉链

        (12)滑窗

      2)案例实操

    package com.yuange.scala.day04
    
    object AggregateTwo {
      def main(args: Array[String]): Unit = {
        val testList: List[Int] = List(1,2,3,4,5,6,7)
        val testList2: List[Int] = List(4,5,6,7,8,9,10,11)
        //获取集合的头
        println("testList.head=" + testList.head)
        //获取集合的尾
        println("testList.tail=" + testList.tail)
        //集合最好一个数据
        println("testList.last=" + testList.last)
        //集合初始数据(不包含最后一个)
        println("testList.init=" + testList.init)
        //反转
        println("testList.reverse=" + testList.reverse)
        //取前n个元素
        var n = 3
        println(testList.take(n))
        //取后n个元素
        println(testList.takeRight(n))
        //去掉前n个元素
        println(testList.drop(n))
        //去掉后n个元素
        println(testList.dropRight(n))
        //并集
        println(testList.union(testList2))
        //交集
        println(testList.intersect(testList2))
        //差集
        println(testList.diff(testList2))
        //拉链:若两个集合的元素个数不相等,则将同等数量的数据进行拉链,多余的数据省略不用
        println(testList.zip(testList2))
        //滑窗:从第五个位置位置开始取两个数
        testList.sliding(2,5).foreach(println)
      }
    }

    7.7.3 集合计算初级函数

      1)说明

        (1)求和

        (2)求乘积

        (3)最大值

        (4)最小值

        (5)排序

      2)实操

    package com.yuange.scala.day04
    
    object AggregateThree {
      def main(args: Array[String]): Unit = {
        val testList: List[Int] = List(1,3,-5,-7,9,-11)
        //求和
        println("testList.sum=" + testList.sum)
        //求乘积
        println("testList.product=" + testList.product)
        //求最大值
        println("testList.max=" + testList.max)
        //求最小值
        println("testList.min=" + testList.min)
        //按元素大小排序:升序
        println(testList.sortBy(x => x))
        //按元素的绝对值大小排序
        println(testList.sortBy(x => x.abs))
        //按元素大小升序排序
        println(testList.sortWith((x,y) => x < y))
        //按元素大小降序排序
        println(testList.sortWith((x,y) => x > y))
      }
    }

    7.7.4 集合计算高级函数

      1)说明

          1)过滤

          2)转化/映射

          3)扁平化

          4)扁平化+映射 注:flatMap相当于先进行map操作,在进行flatten操作

          5)分组

          6)简化(规约)

          7)折叠

      2)实操

    package com.yuange.scala.day04
    
    object AggregateFour {
      def main(args: Array[String]): Unit = {
        val testList: List[Int] = List(1,2,3,4,5,6,7,8,9)
        val nestedList: List[List[Int]] = List(List(1,2,3),List(4,5,6),List(7,8,9))
        val wordList: List[String] = List("hello world","hello yuange","hello scala")
    
        //过滤
        println(testList.filter(x => x % 2 == 0))
        //转化/映射
        println(testList.map(x => x + 1))
        //扁平化
        println("nestedList.flatten=" + nestedList.flatten)
        //扁平化+映射:flatMap相当于先进行map操作,再进行flatten操作
        println("扁平化+映射=" + wordList.flatMap(x => x.split(" ")))
        //分组
        println(testList.groupBy(x => x % 2))
      }
    }

      3)Reduce方法

        Reduce简化(规约) :通过指定的逻辑将集合中的数据进行聚合,从而减少数据,最终获取结果。

    package com.yuange.scala.day04
    
    object TestReduce {
      def main(args: Array[String]): Unit = {
        val testList: List[Int] = List(1,2,3,4,5)
        //将数据两两结合,实现运算
        val i: Int = testList.reduce((x,y) => x - y)
        println("i=" + i)
        //从源码的角度,reduce底层调用的其实就是reduceLeft
    //    val i2: Int = testList.reduce((x,y) => x - y)
        //((5-4)+(3-2)+1) = 3
        val i3 = testList.reduceRight((x,y) => x - y)
        println("i3=" + i3)
      }
    }

      4)Fold方法

        Fold折叠:化简的一种特殊情况。

        (1)案例实操:fold基本使用

    package com.yuange.scala.day04
    
    object TestFold {
      def main(args: Array[String]): Unit = {
        val testList = List(1,2,3,4,5)
        //fold方法使用了函数柯里化,存在两个参数列表
        //第一个参数列表为:零值(初始值)
        //第二个参数列表为:
        //fold底层其实是foldLeft
        val i = testList.foldLeft(1)((x,y) => x - y)
        println("i=" + i)
        val i2 = testList.foldRight(10)((x,y) => x -y)
        println("i2=" + i2)
      }
    }

        (2)案例实操:两个集合合并

    package com.yuange.scala.day04
    
    import scala.collection.mutable
    
    object TestFoldTwo {
      def main(args: Array[String]): Unit = {
        val map = mutable.Map("zhangsan"->1001,"lisi"->1002,"wangwu"->1003)
        val map2 = mutable.Map("zhangsan"->1004,"lisi"->1005,"zhaoliu"->1006)
    
        val map3: mutable.Map[String,Int] = map2.foldLeft(map){
          (map,kv) => {
            val k = kv._1
            val v = kv._2
            map(k) = map.getOrElse(k,0) + v
            map
          }
        }
        println(map3)
      }
    }

    7.7.5 普通WordCount案例

      1需求

        单词计数:集合中出现的相同的单词,进行计数,取计数排名前三的结果

      2)需求分析

      3案例实操

    package com.yuange.scala
    
    object TestWordCount {
      def main(args: Array[String]): Unit = {
        //单词计数:将集合中出现的相同单词,进行计数,取计算排名前三的结果
        val testList = List("Hello Scala Hbase kafka", "Hello Scala Hbase", "Hello Scala", "Hello")
        //将每个字符串按空格进行切分并将切分好的单词放入List集合
        val str: List[String] = testList.flatMap(x => x.split(" "))
        //将相同的单词放在一起(分组)
        val str2: Map[String,List[String]] = str.groupBy(x => x)
        //对相同的单词进行计算
        val str3: Map[String,Int] = str2.map(x => (x._1,x._2.size))
        //对结果进行降序排序
        var sortList: List[(String,Int)] = str3.toList.sortWith{
          (left,right) => {
            left._2 > right._2
          }
        }
        //对排序后的结果取前三
        val result: List[(String,Int)] = sortList.take(3)
        println(result)
      }
    }

    7.7.6 复杂WordCount案例

      1方式一

      2案例实操

    package com.yuange.scala.day04
    
    object TestWordCounTwo {
      def main(args: Array[String]): Unit = {
        val testList = List(("Hello Scala Spark World", 4), ("Hello Scala Spark", 3), ("Hello Scala", 2), ("Hello", 1))
        val testList2: List[String] = testList.map(x => (x._1 + " ")*x._2)
        println("testList2=" + testList2)
        val word: List[String] = testList2.flatMap(_.split(" "))
        println("word=" + word)
        val groupMap: Map[String,List[String]] = word.groupBy(str => str)
        println("groupMap=" + groupMap)
        val number: Map[String,Int] = groupMap.map(i => (i._1,i._2.size))
        println("number=" + number)
        val sortNumber: List[(String,Int)] = number.toList.sortWith{
          (left,right) => {
            left._2 > right._2
          }
        }.take(3)
        println("sortNumber=" + sortNumber)
    
      }
    }

      3)方式

      4)案例实操

    package com.yuange.scala.day04
    
    object TestWordCounThree {
      def main(args: Array[String]): Unit = {
        val tuples = List(("Hello Scala Spark World", 4), ("Hello Scala Spark", 3), ("Hello Scala", 2), ("Hello", 1))
        val testList: List[(String,Int)] = tuples.flatMap{
          t => {
            val str: Array[String] = t._1.split(" ")
            str.map(word => (word,t._2))
          }
        }
    
        val testMap: Map[String,List[(String,Int)]] = testList.groupBy(t=>t._1)
        val testMap2: Map[String,List[Int]] = testMap.mapValues{
          datas => datas.map(t => t._2)
        }
        val testMap3: Map[String,Int] = testMap2.map(t => (t._1,t._2.sum))
        println(testMap3)
      }
    }

    7.8 队列

      1scala也提供了队列(Queue)的数据结构,队列的特点就是先进先出。进队和出队的方法分别为enqueuedequeue

      2案例实操

    package com.yuange.scala.day04
    
    import scala.collection.mutable
    
    object TestQueue {
      def main(args: Array[String]): Unit = {
        val que = new mutable.Queue[String]()
        que.enqueue("zhangsan","lisi","wangwu")
        println(que.dequeue())
        println(que.dequeue())
        println(que.dequeue())
      }
    }

    7.9 并行集合

      1Scala为了充分使用多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。

      2案例实操

    package com.yuange.scala.day04
    
    object TestPar {
      def main(args: Array[String]): Unit = {
        val result = (0 to 100).map{case_ => Thread.currentThread.getName}
        val result2 = (0 to 100).map{case_ => Thread.currentThread.getName}
        println(result)
        println(result2)
      }
    }
  • 相关阅读:
    CruiseControl.NET与TFS结合的配置文件
    环信Restfull API dotnetSDK
    NAnt0.92版本首次在windows 8.1的机子上运行报错的问题解决
    asp.net接收ajax请求参数时为空的现象
    对接微信红包时:CA证书出错,请登录微信支付商户平台下载证书
    在打开vs解决方案时,怎样让所以打开的项目自动折叠
    使用Chrome或Fiddler抓取WebSocket包
    SVN使用教程
    禁用Resharper长代码自动换行的解决办法
    SQLServer日期格式化
  • 原文地址:https://www.cnblogs.com/LzMingYueShanPao/p/14798102.html
Copyright © 2011-2022 走看看