1.一千万个随机数,随机数范围在1到1亿之间,现在要求写出一种算法,将1到1亿之间没有出现的随机数求出来 第一题看这里
2 编 写 一 个 函 数 , 接 收 一 个 字 符 串 集 合 , 以 及 一 个 从 字 符 串 到 整 数 的 映 射 ,返回整数集合,其值为能和集合中某个字符串相应的映射值。举例来说,给Array(“Tom”,”Fred”,”Harry”) 和Map(“Tom”->3,”Dick”->4,”Harry”->5),返回Array(3,5)
做了两种实现,一种是map,一种是flatMap(注释部分)
//map将集合中的每个元素处理,并将处理后的结果返回,返回的是option // 而flatMap与map唯一不一样的地方就是传入的函数在处理完后返回值必须是List def func(a: Array[String], m: Map[String, Int]): Array[Int] = { //val res = a.flatMap(m.get(_))//简单的实现 var ans: Array[Int] = Array[Int]() val r = a.map(m.get(_)) for (a <- r) { ans = show(a, ans) } //从Option中取出Some中数据 def show(r: Option[Int], arr: Array[Int]) = r match { case None => arr case Some(s) => arr :+ s } ans }3.对给定的整型列表lst,(lst :\ ListInt)(:: )得到的是什么? (ListInt /: lst)(:+)又得到什么?如何修改这两个操作,对原来列表反向操作?
val a=(lst :\ ListInt)(::) 等价于 val c=lst.foldRight(ListInt)(+:) 相当于foldRight,添加lst中的元素到ListInt,初始是一个空List 从右开始操作,每次添加的元素在左侧,所以只能用::或+:
val b=(ListInt/:lst)(:+) 等价于 val d=lst.foldLeft(ListInt)(:+) foldLeft,从左向右添加元素到列表,所以只能用:+
val lst =List[Int](1,2,3,4,5) val res1=(lst :\ List[Int]())((x,y)=>y:+x)//正向是x+:y,反过来即可 println("反向:"+res1) val res2=(List[Int]() /: lst)((x,y)=>y+:x)//正向是x:+y,反过来即可 println("反向:"+res2)4.根据 flatMap 实现一个variance(方差)函数,如果一个序列的平均值m,variance是对序列中的每一个元素x进行math.pow(x-m,2) def variances(xs: Seq[Double]): Option[Double]
def variances(xs: Seq[Double]): Option[Double] = { val l=xs.length val m = xs.sum / l Some(xs.map(x=>math.pow(x-m,2)).sum/l) }5.统计字符串中字母出现的频率映射,例如字符串 “scalajavajavascript”返回Map[Char,Int]。用aggregate 方法
val a="scalajavajavascript".par.aggregate(HashMap[Char,Int]())( (k,v)=>{//匿名函数,k打印得kMap(),是要返回的HashMap,v是单个字母 k+(v->(k.getOrElse(v,0)+1))//返回一个HashMap[Char,Int] } , //当不使用并行的时候,只有上部分就已经可以,这部分直接返回就可以 (k,v)=>(k.keySet++v.keySet).foldLeft((HashMap[Char,Int]())) {//k打印得kMap(),v打印得vMap()\ (res,keys)=>res+(keys->(k.getOrElse(keys,0)+v.getOrElse(keys,0))) } )6.写出 ImageReader 的实现类
object work06 { trait Reader[T] { //read方法返回值是泛型,通过实现类的时候指定 def read(fileName: String): T } class StringReader extends Reader[String]{ def read(fileName: String) = Source.fromFile(fileName, "UTF-8").mkString } class ImageReader extends Reader[BufferedImage]{ override def read(fileName: String): BufferedImage = ImageIO.read(new File(fileName)) } } def main(args: Array[String]): Unit = { val a = new ImageReader println(a.read("image.png")) }拿一张图片简单测试一下
真的读到了图片
7.定义一个不可变类Pair[T,S],带一个swap 方法,返回数组交换过位置的新对偶。
class Fair[T,S](a:(T,S)){ def swap:(S,T)={ (a._2,a._1) } } object work07 { def main(args: Array[String]): Unit = { val a=new Pair(1,'a') val b=a.swap println(b) } }8 如果我们想把Pair[Person]的第一个组件替换为Student,为什么不需要给 replaceFirst 方法定义一个下界(代码不是答案,答案是文字)
object VarianceDemo { def makFriends(p: Pair[Person]): Unit = { } def main(args: Array[String]) { val p = new Pair[Student](new Student(), new Student()) //VarianceDemo.makFriends(p) } } class Pair[T](val first: T, val second: T) { def replaceFirst(newFirst: T) = new Pair[T](newFirst, second) } class Person {} class Student extends Person {}答案: 因为Student是Person的子类型,可以直接去替换Person,根本不需要定义下界 那什么时候用下界呢? 下界 R>: T 定义泛型R,R是T的超类 所以下界替换进来的类常常是原类型的超类型 如果我们需要用Person替换Student(超类替换子类),我们需要定义下界,代码如下
object VarianceDemo { def main(args: Array[String]) { val p = new Pair[Student](new Student(), new Student()) val a=new Person p.replaceFirst(a) } } class Pair[T](val first: T, val second: T) { def replaceFirst[R>:T](newFirst: R) = new Pair[R](newFirst, second) } class Person {} class Student extends Person {}如果不定义下界,也可以通过编译,要求返回的 new Pair后面不指定[T],此时返回的类型是Any 由此,可以理解‘界’这个概念
class Pair[T](val first: T, val second: T) { def replaceFirst[T](newFirst: T) = new Pair(newFirst, second) }当然有种特别的情况 上述代码,R会被什么具体类型替换,取决于T和 newFirst 的类型。如果 newFirst 的类型刚好是T的基类,,R就直接是 newFirst 的类型。如果 newFirst 的类型不是T的基类,那R就会是T和 newFirst 的类型的共同基类
这道题真是给我整蒙了,甚至让我怀疑人生,因为刚刚看完协变,第一眼就把下界看成协变了,虽然后来看到是人家问的是下界,但协变就一直没从我脑中驱除,思维一直在协变和下界中穿梭,绞尽脑汁想着哪用上协变了啊,其实人家根本没问好嘛,这个过程虽煎熬,但也确实让我把这型变和界理解得更透彻
9 查看 Iterable [+A] 特质。哪些方法使用了类型参数A?为什么在这些方法中类型参数是协变的
foldLeft, foldRight等方法,因为Iterable特质声明类型A为协变
10 定义一个操作符+%,将一个给定的百分比添加到某个值。举例来说120 +% 10 = 132,由于操作符是方法而不是函数,你需要提供一个implicit
object work10 { //隐式转换的声明必须在要使用的位置之前,否则无效 //因为Double类型中并没有+%这个方法,所以这里把Double类型转换为A类型 implicit def doubleToA(x:Double)=new A(x) def main(args: Array[String]): Unit = { val res=120 +% 10 println(res) } } class A(x:Double){ def +%(y:Double)=x*y*0.01+x }