以下是 50 道 Scala 编程练习题:
一、基础语法
一、基础语法(1-10 题)
1. 定义一个变量存储你的名字,并打印出来。
2. 计算两个整数的和并打印结果。
3. 判断一个整数是奇数还是偶数。
4. 打印 1 到 10 的整数。
5. 计算给定整数列表中所有元素的和。
6. 找出给定整数列表中的最大值。
7. 反转一个字符串。
8. 判断一个字符串是否为回文。
9. 计算一个字符串中某个字符出现的次数。
10. 将一个字符串中的所有小写字母转换为大写字母。
import java.util
/**
* 1. 定义一个变量存储你的名字,并打印出来。
* 2. 计算两个整数的和并打印结果。
* 3. 判断一个整数是奇数还是偶数。
* 4. 打印 1 到 10 的整数。
* 5. 计算给定整数列表中所有元素的和。
* 6. 找出给定整数列表中的最大值。
* 7. 反转一个字符串。
* 8. 判断一个字符串是否为回文。
* 9. 计算一个字符串中某个字符出现的次数。
* 10. 将一个字符串中的所有小写字母转换为大写字母。*/
object Test_1To10 {
def main(args: Array[String]): Unit = {
//1
var name:Unit= println("少帅")
//2
//可以单独用var定义变量,然后相加,这里我采用定义方法
def add(a:Int,b:Int):Unit=println(a+b)
add(3,4)
//3 这里警告是因为变量为中文的原因
val `整数` = 3;
if (`整数`%2==0) println (s"该${`整数`}为偶数") else println(s"该整数${`整数`}为奇数")
//4 注意一个小细节,to和1和10之间要有空格,主要是可以与1之间的空格可以删除,就容易报错
//Invalid literal number for(i <- 1to 10) {
for(i <- 1 to 10) {
println(i)
}
//5 直接调用sum函数
val list: Unit = println("该list集合元素之和为:"+(List(1, 2, 3, 4, 5, 6, 7).sum))
//6
val list1: Unit = println("该list集合元素中最大值为:"+(List(1, 2, 3, 4, 5, 6, 7).max))
//7 再也不用java中的bufferString反转了
val s:Unit= println("字符串abcdefg反转后为:"+"abcdefg".reverse)
//8
val s1="ababa"
if(s1==s1.reverse) println(s"字符串${s1}是回文") else println(s"字符串${s1}不是回文")
//9 这里我们统计java出现的次数
val s3="java,java,hadoop,spark,scala,scala,java"
val word: Array[String] = s3.split(",")
var i=0
for (elem <- word) if(elem=="java") i+=1;println(s"java一共出现了${i}次")
//统计每个单词的个数,需要创建一个字典,存在就加1,不存在就添加一个
val map = new util.HashMap[String, Integer]()
for (elem <- word) if(map.containsKey(elem)) map.put(elem,map.get(elem)+1) else map.put(elem,1)
println("字典:"+map)
//10
val s4="abcDEGkgLiOPqec123"
println(s"该字符串${s4}变成大写后:"+s4.toUpperCase())
}
}
二、函数与方法
**二、函数与方法(11-20 题)**
11. 定义一个函数,接受两个整数参数,返回它们的和。
12. 定义一个函数,接受一个整数参数,返回该整数的平方。
13. 定义一个函数,接受一个字符串参数,返回该字符串的长度。
14. 定义一个函数,接受一个整数列表参数,返回列表中所有偶数的平方和。
15. 定义一个递归函数,计算斐波那契数列的第 n 项。
16. 定义一个函数,接受一个函数参数和一个整数参数,返回将函数应用于整数后的结果。
17. 定义一个函数,接受一个字符串列表参数,返回列表中长度最长的字符串。
18. 定义一个函数,接受一个整数列表参数,返回一个新的列表,其中每个元素是原列表对应元素的平方。
19. 定义一个函数,接受一个整数列表参数和一个整数 n,返回一个新的列表,其中包含原列表中所有大于 n 的元素。
20. 定义一个函数,接受一个整数列表参数,返回列表中所有元素的乘积。
package scalaPractice50
import java.util
import scala.collection.mutable.ListBuffer
object Test_11To20 {
def main(args: Array[String]): Unit = {
//11、定义一个函数,接受两个整数参数,返回它们的和。
def add(a:Int ,b:Int):Int=a+b
println("加法"+add(2, 6))
//12、定义一个函数,接受一个整数参数,返回该整数的平方。
def chengFa(a:Int):Int=a*a
println("乘法"+chengFa(3))
//13、定义一个函数,接受一个字符串参数,返回该字符串的长度。
def strLen(s:String):Long=s.length
println("少帅的字符串长度为:"+strLen("少帅"))
//14、定义一个函数,接受一个整数列表参数,返回列表中所有偶数的平方和
//用到filter过滤
def evenSquaresSum(list: List[Int]): Any = {
list.filter(_ % 2 == 0).map(n => n*n).sum
}
println(evenSquaresSum(List(1, 2, 3, 4, 5)))
//直接打印每个偶数的平方和
def ouShuSquare(list: List[Int]): Unit = for (elem <- list) if (elem % 2 == 0) println(s"${elem}的平方和为:" + elem * elem)
val list1: List[Int] = List(1, 2, 4, 6, 5, 1, 7, 9, 10)
ouShuSquare(list1)
//15、定义一个递归函数,计算斐波那契数列的第 n 项。
//斐波那契数列是:1,1,2,3,5,8,13....
def fibonacci(n: Int): Int = {
if (n <= 1) n
else fibonacci(n - 1) + fibonacci(n - 2)
}
println(fibonacci(6))
//16、定义一个函数,接受一个函数参数和一个整数参数,返回将函数与整数之和后的结果。
//先定义一个两数相减的函数jianFa,fun实现两数相减,再加上另外一个数
def jiaFa(a:Int,b:Int):Int=if(a>b) (a-b) else b-a
//这个fun方法是一个参数为一个函数参数和整数参数,返回值类型为Int的函数
def fun(jianFa:Int,a:Int):Int=jianFa+a
val f: Int = fun(jiaFa(3, 7), 6)
println(s"fun方法得到的值为:${f}")
//17、定义一个函数,接受一个字符串列表参数,返回列表中长度最长的字符串。
def maxStr(list: List[String]): String={
//list是不可变列表,如果发生增删改就要用另一个集合去接收它
//listBuffer是可变列表
val buffer: ListBuffer[Int] = ListBuffer()
val map = new util.HashMap[String, Integer]()
var s=""
for (elem <- list) {
//buffer.append(elem.length)
buffer.+=(elem.length)
map.put(elem,elem.length)
}
for (elem <- list) {
if(map.get(elem)==buffer.max) s=elem
}
//默认忽略return,自动检测返回值
return s
}
val list2: List[String] = List("java","hadoop","scala","python","scala--spark","spark","hello world")
println(s"数组${list2}中字符最长的长度为"+maxStr(list2))
//简化写法用到maxBy函数
//max里面直接传数值,或者被数值对象直接调用,maxBy里面要传函数,在进行比较
def longestString(list: List[String]): String = {
list.maxBy(_.length)
}
println(longestString(List("hello", "world", "scala+spark")))
//18、定义一个函数,接受一个整数列表参数,返回一个新的列表,其中每个元素是原列表对应元素的平方。
//每一个集合都有map方法,map可以对集合中的每个元素进行操作
def pingFang(list: List[Int]):List[Int]=list.map(n => n*n)
println("List(1,2,3,4,5,6,7)对应的新列表为:"+pingFang(List(1,2,3,4,5,6,7)))
//19、定义一个函数,接受一个整数列表参数和一个整数 n,返回一个新的列表,其中包含原列表中所有大于 n 的元素。
def fun1(list: List[Int],n:Int):List[Int]=list.filter(_>n)
println("大于5的数值列表为:"+fun1(List(2,1,5,6,9,21,8,44),5))
//20、定义一个函数,接受一个整数列表参数,返回列表中所有元素的乘积。
//用到乘积函数product
def fun3(list: List[Int]):Int=list.product
println("返回列表所有元素之积:"+fun3(List(1,2,3,4,5)))
//使用foldLeft,这个给定b一个初始值,然后与该列表中的所有元素递归相乘,得到的结果是该列表所有元素的乘积再乘b
//比如给b初始值为2,则b=2*1,b=2*2,b=4*3.b=12*4,b=48*5=(2*1*2*3*4*5)
//这里报黄色警告的原因是,给初始值为1,还不如用更简洁的product相乘函数,给其他值就不会报警告了
def product(list: List[Int]): Int = list.foldLeft(1)(_ * _)
println(product(List(1, 2, 3, 4, 5)))
def f4(a:Int):Int=>Int={
def f5(b:Int):Int={
a*b
}
f5
}
val f5: Int=>Int=f4(10)
val i: Int = f5(20)
println(i)
println(f4(10)(20))
}
}
三、面向对象编程
**三、面向对象编程(21-30 题)**
21. 定义一个简单的类,包含一个整数属性和一个方法,用于打印该整数。
22. 定义一个类,包含两个整数属性和一个方法,用于计算这两个整数的和。
23. 定义一个类,继承自另一个类,并添加一个新的方法。
24. 定义一个抽象类,包含一个抽象方法,然后创建一个子类实现该抽象方法。
25. 定义一个 trait,包含一个方法,然后让一个类混入该 trait。
26. 定义一个类,包含一个私有属性和一个公共方法,用于访问该私有属性。
27. 定义一个类,包含一个构造函数参数,并在构造函数中初始化一个属性。
28. 定义一个类,包含一个静态方法(在 Scala 中使用伴生对象实现)。
29. 定义一个类,实现 equals 和 hashCode 方法。
30. 定义一个类,包含一个不可变的集合属性,并提供一个方法用于添加元素到该集合(返回一个新的集合)。
package scalaPractice50
// TODO: Scala默认是public权限,也没有public关键字,不需要写,
// 其中protect比Java更严格,同类、子类可以访问,同包无法访问
// private[包名]增加包访问权限,包名下的其他类也可以使用
// TODO: 继承样例(case class)可以用with,接口用trait声明,其他子类实现的时候正常使用extends
object Test_21To30 {
//21. 定义一个简单的类,包含一个整数属性和一个方法,用于打印该整数。
class PrintInt( num:Int){
def printNum(): Unit = {
println(num)
}
}
object PrintInt {
def apply(num: Int): PrintInt = new PrintInt(num)
def main(args: Array[String]): Unit = {
println("你好")
}
}
//22. 定义一个类,包含两个整数属性和一个方法,用于计算这两个整数的和。
//object定义的静态类,叫做伴生对象,
class SumInt( a:Int, b:Int){
def sumInt(): Int =a+b
}
object SumInt{
def apply(a: Int, b: Int): SumInt = new SumInt(a, b)
}
//23. 定义一个类,继承自另一个类,并添加一个新的方法。
// TODO: 伴生对象不能写在伴生类里面,否则就等于普通方法,通过伴生对象创建类对象,可以调用伴生类方法
class JiaFa( c:Int, d:Int) extends SumInt(c,d){
def jaFa(c:Int,d:Int)=(c+d)*c*d
}
object JiaFa{
def apply(c: Int, d: Int): JiaFa = new JiaFa(c, d)
}
//24. 定义一个抽象类,包含一个抽象方法,然后创建一个子类实现该抽象方法。
// TODO: 和Java一样,抽象类可以定义抽象方法,也可以写具体方法,并且和Scala正常类一样可以在类上传参
abstract class ChouXiang{
def chouXiang()
}
class JuTi extends ChouXiang{
override def chouXiang(): Unit = println("你好抽象方法")
}
//25. 定义一个 trait,包含一个方法,然后让一个类混入该 trait。
// TODO: //在Scala中接口就用trait=(interface+abstract)
// //接口和object一样,不能传参
trait JieKou{
def sayJieKou;
}
class ShiXianLei extends JieKou() {
override def sayJieKou: Unit = println("say 这是一个接口")
}
object ShiXianLei{
def apply(): ShiXianLei = new ShiXianLei()
}
//26. 定义一个类,包含一个私有属性和一个公共方法,用于访问该私有属性。
class Info{
private val i:Int=3
val j:Int=2
def getNum: Int =i
}
//27. 定义一个类,包含一个构造函数参数,并在构造函数中初始化一个属性。
class GouZao(b:Int=1){
println(s"初始化属性:$b")
}
//28. 定义一个类,包含一个静态方法(在 Scala 中使用伴生对象实现该方法)。
class BanShen{}
object BanShen{
def talk():Unit=println("你好伴生对象")
}
//29. 定义一个类,实现 equals 和 hashCode 方法。
class EqualsAndHashCode(num:Int) {
override def hashCode(): Int = num.hashCode()
override def equals(obj: Any): Boolean = obj match {
case that: Info => that.j == num
case _ => false
}
}
//30. 定义一个类,包含一个不可变的集合属性,并提供一个方法用于添加元素到该集合(返回一个新的集合)。
// TODO: 直接设置一个不可变列表
// TODO: 不可变集合的增加元素的语法为 elem :: list 或 list.+:(elem)
class AddList(list: List[Int]){
def addList(elem:Int):List[Int]={
val list1: List[Int] = elem :: list //todo: ::运算规则是从右往左,可以添加好多个元素
val list2: List[Int] = list.+:(elem) // TODO: 将元素添加到第一个位置
list2
}
}
def main(args: Array[String]): Unit = {
val num = new PrintInt(3)
PrintInt.apply(3).printNum()
//在Scala里面重复的println不会报错,一切都是对象, println(println)不会报错,结果是()
num.printNum()
PrintInt.main(Array())//object静态可以直接调用
println(SumInt.apply(2, 3).sumInt())
// TODO: 以为父类主构造器有参,所以子类在继承时候也要给父类参数,但是最后调用子类的方法的时候
// TODO: 父类中传的参数并不影响子类的方法和子类的参数,父类参数只是一个形式的摆设
println(JiaFa.apply(1,2).jaFa(2, 3))
val ti = new JuTi
ti.chouXiang()
ShiXianLei.apply().sayJieKou
val info = new Info
println(info.getNum)
val zao = new GouZao(10)
BanShen.talk()
val code = new EqualsAndHashCode(10)
val i: Int = code.hashCode()
println("10的hashcode值为:"+i)
val bool: Boolean = code.equals(code)
println(bool)
val list: List[Int] = new AddList(List(1, 2, 4, 6, 7)).addList(8)
println("增加新元素之后的列表:"+list)
}
}
四、高阶函数与集合操作
**四、高阶函数与集合操作(31-40 题)**
31. 使用 map 函数将一个整数列表中的每个元素乘以 2。
32. 使用 filter 函数筛选出一个整数列表中的偶数。
33. 使用 flatMap 函数将一个整数列表中的每个元素重复两次,并返回一个新的列表。
34. 使用 reduce 函数计算一个整数列表中所有元素的乘积。
35. 使用 fold 函数计算一个整数列表中所有元素的和,并指定初始值为 10。
36. 使用 for 循环和 yield 关键字生成一个新的列表,其中包含原列表中所有大于 3 的元素的平方。
37. 对一个整数列表进行排序。
38. 对一个字符串列表按照字符串长度进行排序。
39. 计算两个整数列表的笛卡尔积。
40. 使用 zip 函数将两个整数列表合并成一个包含元组的列表。
package scalaPractice50
object Test_31To40 {
def main(args: Array[String]): Unit = {
// TODO: 31. 使用 map 函数将一个整数列表中的每个元素乘以 2。
val list: List[Int] = List(1, 2, 3, 4, 5)
println(s"列表${list}所有元素乘以2得:\t"+list.map(_ * 2))
// TODO: 32. 使用 filter 函数筛选出一个整数列表中的偶数。
println(s"${list}中得偶数为:\t"+list.filter(_ % 2 == 0))
// TODO: 33. 使用 flatMap 函数将一个整数列表中的每个元素重复两次,并返回一个新的列表。
val list1: List[Int] = list.flatMap(n => List(n, n))
println(list1)
// TODO: 34. 使用 reduce 函数计算一个整数列表中所有元素的乘积。
// TODO: foldLeft可以给初始值与列表元素相乘 list.foldLeft(10)(_ * _)
// TODO: fold和foldLeft用法一样,给定初始值再处理列表元素,如果括号是*,则初始值也用*,如果是+,初始值也是+
val product: Int = list.reduce(_*_) //就是reduceLeft从左往右乘,这里报警告,是因为有更好的product写法
println(product)
// TODO: 35. 使用 fold 函数计算一个整数列表中所有元素的和,并指定初始值为 10。
// TODO: sum是直接将列表里所有元素进行相加,fold可以给定初始值与列表元素相加
val cSum: Int = list.fold(10)(_+_)
println(s"这是给定初始值为10得求和:\t${cSum}")
// TODO: 36. 使用 for 循环和 yield 关键字生成一个新的列表,其中包含原列表中所有大于 3 的元素的平方。
//简单写法
val list2: List[Int] = list.filter(_ > 3).map(n => n * n)
println(list2)
//使用yield,有点类似于SQl的写法,查找大于3的元素,yield紧接着对数据处理
val newList = for {
x <- list
if x > 3
} yield x * x
println(newList)
val list3: List[Int] = for {
n <- list
if n < 3
} yield n * n
println(list3)
// TODO: 37. 对一个整数列表进行排序。
val list4: List[Int] = List(1, 3, 2, 55, 4, 11, 67, 54)
println("直接用sorted: "+list4.sorted)
println("升序"+list4.sortBy((i: Int) => i))
println("降序"+list4.sortBy((i: Int) => -i))
// TODO: 38. 对一个字符串列表按照字符串长度进行排序。
// TODO: sortBy和sortWith都能进行升序和降序 ,在sortBy中常用一个条件,sortWith可以自定义多个参数,来判断
// TODO: 相同字符长度的按照字典排序,字典默认是升序的从a-z,A-Z
val list5: List[String] = List("java", "hadoop", "spark", "java+scala", "hive")
println(list5.sortBy(_.length))
val shenXu: List[String] = list5.sortWith((s1: String, s2: String) => if (s1.length > s2.length) false else true)
val jiangXu: List[String] = list5.sortWith((s1: String, s2: String) => if (s1.length < s2.length) true else false)
println(s"列表${list5}的长度升序为:${shenXu}\n 长度降序为:${jiangXu}")
// TODO: 39. 计算两个整数列表的笛卡尔积。
val list6: List[Int] = List(1, 2, 3, 4)
val list7: List[Int] = List(6, 7, 8, 9,10)
// TODO: 合并列表
println(list6.union(list7))
// TODO: 增强for循环只能对一个列表,而且没有返回值,所以就用for循环,yeild 还能结合条件返回新的列表
val diKaEr: List[Int] = for {
x <- list6
y <- list7
} yield x * y
println(s"列表笛卡尔乘积:${diKaEr}")
// TODO: 40. 使用 zip 函数将两个整数列表合并成一个包含元组的列表。
// TODO: 两个列表如果长度不同,压缩也不会报错,元组的长度等于最短列表的长度
val zip: List[(Int, Int)] = list6.zip(list7)
println(s"压缩列表变成元组$zip")
}
}
五、高级主题
**五、高级主题(41-50 题)**
41. 实现一个自定义的控制结构(例如,一个循环)。
42. 实现一个简单的 Actor 模型(可以使用 Scala 的 Actor 库或者自己模拟实现)。
43. 使用模式匹配处理不同类型的输入。
44. 实现一个简单的函数式编程风格的栈数据结构。
45. 使用尾递归实现一个函数,计算一个整数列表中所有元素的和。
46. 实现一个函数,将一个整数列表中的元素分组,根据元素是否为偶数进行分组。
47. 实现一个函数,对一个整数列表进行分块,每块包含固定数量的元素。
48. 使用泛型实现一个函数,接受两个不同类型的参数,并返回它们的和(如果可能的话)。
49. 实现一个函数,对一个字符串进行加密(例如,简单的替换加密)。
50. 实现一个函数,解析一个简单的数学表达式(例如,“1+2*3”)并返回结果。