Scala(十一)泛型、项目案例

11.1 协变和逆变

  1)语法

class MyList[+T]{ //协变

}

class MyList[-T]{ //逆变

}

class MyList[T]{//不变

}

  2)说明

    协变:SonFather子类,则MyList[Son] 也作为MyList[Father]的“子类”。

    逆变:SonFather子类,则MyList[Son]作为MyList[Father]的“父类”。

    不变:SonFather子类,则MyList[Father]与MyList[Son]“无父子关系”。

  3)实操

package com.yuange.scala.day06

abstract class Animal{
  val name: String
}

abstract class Pet extends Animal{
}

class Dog extends Pet{
  override val name: String = "狗子"
}

class Cat extends Pet{
  override val name: String = "猫子"
}

class Lion extends Animal{
  override val name: String = "狮子"
}

class PetContainer[+P](val pet: P){
}

object TestGeneric {

  def testPrint(petContainer: PetContainer[Pet]) = {
    println(petContainer.pet.name)
  }

  def main(args: Array[String]): Unit = {
    val dog: Dog = new Dog()
    var cat: Cat = new Cat()
    var lion: Lion = new Lion()

    val dogContainer: PetContainer[Dog] = new PetContainer[Dog](dog)
    val catContainer: PetContainer[Cat] = new PetContainer[Cat](cat)

    println("dogContainer=" + dogContainer)
    println("catContainer=" + catContainer)
  }
}

11.2 泛型上下限

  1)语法

Class PersonList[T <: Person]{ //泛型上限

}

Class PersonList[T >: Person]{ //泛型下限

}

  2泛型的上下限的作用是对传入的泛型进行限定。

  3)实操

package com.yuange.scala.day06

abstract class Animal{
  val name: String
}

abstract class Pet extends Animal{

}

class Dog extends Pet{
  override val name: String = "狗子"
}

class Cat extends Pet{
  override val name: String = "喵咪"
}

class Lion extends Animal{
  override val name: String = "狮子"
}

class PetContainer[P <: Pet](val pet: P){

}

object TestGenericTwo {
  def testPrint(petContainer: PetContainer[Pet]): Unit ={
    println(petContainer.pet.name)
  }

  def main(args: Array[String]): Unit = {
    var dog: Dog = new Dog()
    var cat: Cat = new Cat()
    var loin: Lion = new Lion()

    val dogContainer: PetContainer[Dog] = new PetContainer[Dog](dog)
    val catContainer: PetContainer[Cat] = new PetContainer[Cat](cat)
    val loinContainer: PetContainer[Lion] = new PetContainer[Lion](loin)  //error
    /*Error:(39, 24) type arguments [com.yuange.scala.day06.Lion] do not conform to class PetContainer's type parameter bounds [P <: com.yuange.scala.day06.Pet]
    val loinContainer: PetContainer[Lion] = new PetContainer[Lion](loin)
    Error:(39, 49) type arguments [com.yuange.scala.day06.Lion] do not conform to class PetContainer's type parameter bounds [P <: com.yuange.scala.day06.Pet]
    val loinContainer: PetContainer[Lion] = new PetContainer[Lion](loin)*/
  }
}

11.3 上下文限定

  1)语法

def f[A : B](a: A) = println(a) //等同于def f[A](a:A)(implicit arg:B[A])=println(a)

  2)上下问限定是将泛型和隐式转换的结合产物,以下两者功能相同,使用上下文限定[A : Ordering]之后,方法内无法使用隐式参数名调用隐式参数,需要通过implicitly[Ordering[A]]获取隐式变量。

  3)实操

def f[A:Ordering](a:A,b:A) =implicitly[Ordering[A]].compare(a,b)
def f[A](a: A, b: A)(implicit ord: Ordering[A]) = ord.compare(a, b)

11.4 项目案例

  1)需求

    (1)获取没有农贸市场的所有省份

    (2)获取农产品种类最多的三个省份

    (3)获取每个省份中农产品种类最多的三个农贸市场

  2)数据准备,找到 product.txt 和 allprovince.txt 文件,下载地址:https://pan.baidu.com/s/1dNIIZn6Tp5_Tee4nRjNF4A   提取码:hs37 

  3)实操

package com.yuange.scala.day06

import scala.io.Source

object TestWordCount {
  val product: List[String] = Source.fromFile("product.txt","UTF-8").getLines().toList
  val allprovince: List[String] = Source.fromFile("allprovince.txt","UTF-8").getLines().toList

  def main(args: Array[String]): Unit = {
    //1、获取没有农贸市场的所有省份
    println("获取没有农贸市场的所有省份:")
    testOne(allprovince,product)
    println("-"*100)
    //2、获取农产品种类最多的三个省份
    println("获取农产品种类最多的三个省份:")
    testTwo(product)
    println("-"*100)
    //3、获取每个省份中农产品种类最多的三个农贸市场
    println("获取每个省份中农产品种类最多的三个农贸市场:")
    testThree(product)
  }

  //3、获取每个省份中农产品种类最多的三个农贸市场
  def testThree(product: List[String]) = {
    product.filter(_.split("\t").length == 6).map({x =>
      val arr = x.split("\t")
      (arr(4),arr(3),arr(0))
    }).distinct.groupBy{case (province,market,name) => province}.map(x => {
      x._2.groupBy{case (province,market,name) => market}.map(y => {
        (x._1,y._1,y._2.size)
      }).toList.sortBy{case (province,market,num) =>num}.reverse.take(3).foreach(println)
    })
  }

  //2、获取农产品种类最多的三个省份
  def testTwo(product: List[String]) = {
    product.filter(_.split("\t").length == 6).map( x => {
        var arr = x.split("\t")
        (arr(4),arr(0))
    }).distinct.groupBy{ case (province,vegetables) => province}.map(x => {(x._1,x._2.size)}).toList.sortBy(_._2).reverse.take(3).foreach(println)
  }

  //1、获取没有农贸市场的所有省份
  def testOne(allprovince: List[String],product: List[String]) = {
//    list.filter(x => {
//      x.split("\t").length == 6(province,market)
//    })
    allprovince.diff(product.filter(_.split("\t").length == 6).map(_.split("\t")(4)).distinct).foreach(println)
  }
}
原文地址:https://www.cnblogs.com/LzMingYueShanPao/p/14809557.html