当前位置: 代码网 > it编程>编程语言>正则表达式 > Scala学习

Scala学习

2024年07月28日 正则表达式 我要评论
本质上是将函数A的处理逻辑主体传给了函数B,在函数B中使用这个处理逻辑// f: String => Int 相当于函数A// fun3 相当于函数B//定义 函数主体a1 + 3000// 定义一个函数s.toInt//调用//定义一个函数fun1, 函数的参数列表中,既有正常的类型参数,也有函数类型的参数a1 + 1000s.toInt// .....val res1: Int = fun1("2000", show2) // 可以传不同的函数 很麻烦 使用lambda简写。

scala学习

scala介绍

scala特点

scala :oo(面向对象)+fp(函数式编程)

安装使用scala

在idea中使用scala

1.在idea中增加scala插件支持scala的使用

image.png

2.安装scala

①直接下载(scala官网下载)

②添加依赖下载


            <dependency>
                <groupid>org.scala-lang</groupid>
                <artifactid>scala-library</artifactid>
                <version>2.12.10</version>
            </dependency>

            <dependency>
                <groupid>org.scala-lang</groupid>
                <artifactid>scala-compiler</artifactid>
                <version>2.12.10</version>
            </dependency>

            <dependency>
                <groupid>org.scala-lang</groupid>
                <artifactid>scala-reflect</artifactid>
                <version>2.12.10</version>
            </dependency>

scala和java的编译插件

 	<build>
        <plugins>

            <!-- java compiler -->
            <plugin>
                <groupid>org.apache.maven.plugins</groupid>
                <artifactid>maven-compiler-plugin</artifactid>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <!-- scala compiler -->
            <plugin>
                <groupid>org.scala-tools</groupid>
                <artifactid>maven-scala-plugin</artifactid>
                <version>2.15.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testcompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>

使用scala

/**
 *  写scala可运行文件的注意事项
 *  1、如果一个scala文件要运行,class要改成object
 *  2、如果是class,就仅单纯代表一个类,如果是object代表的是单例对象
 *  3、scala语法中,一句话结束不需要加分号
 *  4、scala文件中,可以无缝使用java中的类和方法
 */
object helloworld {
  def main(args: array[string]): unit = {
    println("hello world")
    system.out.println("hhh")  // java语法同样可以运行
  }
}

scala语法

1.变量与常量

scala中的数据类型和java的数据类型对应关系:

java:scala:
bytebyte
shortshort
intint
longlong
floatfloat
doubledouble
booleanboolean
charchar
 定义一个变量a1,并赋值100
        var a1 = 100 // 自动推断出类型
        println(a1)
        println(a1.getclass) // 获取变量的类型
//        a1 = "你好" :string
        println(a1)
        a1 = 200 	//可以改变值
        println(a1)

   //定义一个整数类型的变量a2,并赋值11
    var a2: int = 11  //给类型
    println(a2)
    println(a2.getclass)
 println("=" * 50) // * 其实是一个函数,底层是通过stringbuilder链接字符的

//定义一个整数常量a3,赋值300
    val a3: int = 300
    println(a3)

2.字符串的使用

  //正常使用双引号构建字符串
    var s1: string = "我是大帅哥!"
    println(s1)
    //使用三个一对双引号构建长字符串
    var sql1: string =
      """
        |select
        |*
        |from
        |students
        |where age>18
        |""".stripmargin
    println(sql1)
// string类中的方法可以使用 
var s3 = "hello,world,java,hadoop,scala"
// 数组
val arr1: array[string] = s3.split(",")
//    val arr1: array[string] = s3 split ","  另一种写法  只有一个参数去掉符号
println(arr1) // 打印的是地址值
//scala中的数组和java中的数组一样,也是有索引的,也是从0开始的   注意是()不是java中的[]
    println(arr1(0))
    println(arr1(1))
    println(arr1(2))
    println(arr1(3))
    println(arr1(4))
    var q1: string = "hello"
    var q2: string = "world"
    var q3: string = "java"
    var res1: string = q1 + "|" + q2 + "|" + q3
    println(res1)// hello|world|java

    val sb: stringbuilder = new stringbuilder()
    sb.append(q1).append("-").append(q2).append("-").append(q3)
    println(sb) //hello-world-java

    val res3: string = arr1.mkstring("&")  // 数组方法
    println(res3) //hello&world&java&hadoop&scala

    val res4: string = s"${q1.touppercase}#${q2}#${q3}" //可以使用string的方法
    println(res4) //hello#world#java

3.运算符

  /*
  * 运算符
  * */
var x: int = 3
var y: int =4
println(x+y)
println(x-y)
println(x*y)
println(x/y)
println(x * 1.0/ y)  // 整除
println(x%y)

4.条件语句

选择语句: if

    val sc = new scanner(system.in)
    print("请输入年龄:")
    val age : int = sc.nextint()
    if(age>18){
      println("成年了")
    }else{
      println("未成年")
    }

循环语句

// for 循环遍历数组
   //创建一个数组
    //数组:在内存中一块连续固定大小的空间,有索引可以检索数据,查询快,增删慢
    val arr1: array[int] = array(1, 2, 3, 4, 5)
// 遍历数组
    // java的方法在这里行不通
//    for(var i:int = 0;i<arr1.length;i+=1){
//      println(arr1(i))
//    }
    /**
     * 注意:
     * 1、在scala语言中,没有++或者--的语法  i+=1  i= i+1
     * 2、在scala语言中,不存在和java一样的普通for循环
     * 3、scala中的for循环写法不太一样
     */
    for (i <- arr1){
      println(i)
    }
// while循环遍历数组
 var i :int = 0
    while (i<arr1.length){
      println(arr1(i))
      i +=1
    }
 // while 循环实现
    var i:int = 1
    while (i<=10){
      println("hello world")
      i+=1
    }
// 使用for循环,指定循环的次数
    // 10次  包含10
    for(e<-1 to 10){
      println("hello world")
    }
    // 9次  不包含10
    for(e<-1 until 10){
      println("hello world")
    }

5.控制流程语句

 for (e <-1 to 5){
      if(e == 2){
//        continue    用不了
      }
      println(e)
    }
// break
import scala.util.control.breaks._ // scala中大部情况下,表示所有或者默认值或者占位符的时候,使用的是下划线
 for (e <-1 to 5){
      if(e == 2){
        break  // 底层实现是一个函数,抛出一个异常,终止程序运行
      }
      println(e)
    }
println("我是大帅哥")
//exception in thread "main" scala.util.control.breakcontrol
//后续代码不会执行
// break之后不停 继续运行 使用breakable
  breakable{
      for (e <-1 to 5){
        if(e == 2){
          break  // 底层实现是一个函数,抛出一个异常,终止程序运行
        }
        println(e)
      }
    }
    println("我是大帅哥")
// 1 我是大帅哥  遇到break 继续运行

6.io流

读文件

 /*
    * 对比java与scala
    * */
    // 读取一个文件内容
    // java的方式读取
    val br = new bufferedreader(new filereader("d:\\pypro\\bigdt30\\scala\\data\\test.text"))
    var line : string = br.readline()
    while(line != null){
      println(line)
      line = br.readline()
    }

   // scala中的读取文件的方式
    // source.fromfil 底层是使用了字节输入流读取数据fileinputstream
    val bs: bufferedsource = source.fromfile("d:\\\\pypro\\\\bigdt30\\\\scala\\\\data\\\\test.text")
//    val lineiterator: iterator[string] = bs.getlines()
//        while (lineiterator.hasnext){
//          val s: string = lineiterator.next()
//          println(s)
//        }
//    for (e <- lineiterator) {
//      println(e)
//    }
// 简写
    for (e <- bs.getlines()) {
      println(e)
    }

写文件

   // java写文件
    val bw = new bufferedwriter(new filewriter("scala/data/test1.text"))
    bw.write("哈哈哈哈哈")
    bw.newline()
    bw.write("呵呵呵")
    bw.flush()

    // 纯scala中没有写文件的方式

7.异常

 /**
     *  scala中的异常和java的很像
     */
    try {
      //      println(10/2)  //除0异常
      //      val arr1: array[int] = array(1, 2, 3, 4, 5)
      //      println(arr1(5))  // 数组越界异常

      //      val br: bufferedreader = new bufferedreader(new filereader("scala/data/words888.txt")) // 文件找不到异常
      /**
       * 也可以手动的抛出异常
       */
      val sc = new scanner(system.in)
      print("输入除数:")
      val cs: int = sc.nextint()
      if(cs!=0){
        println(10/cs)
      }else{
        throw new arithmeticexception("您输入的除数是0")   // 抛出异常
      }
    }catch{
      //类似于sql语句中case when
      case e:arithmeticexception=>
        //        println("除0异常")
        e.printstacktrace()
      case e:arrayindexoutofboundsexception=>
        println("数组越界异常")
//      case e:exception=>     不确认的异常
//      println("出现异常")
      case _ =>    // 任意一个异常
        println("出现异常")
    }finally {
      //今后finally中的处理大部分情况下都与释放资源有关
      println("这是finally代码块")
    }

    println("hello world")

8.函数和方法

  def main(args: array[string]): unit = {
    //调用函数
    val res1: int = add(3, 4)
    println(res1)
      
      //在main函数内也可以创建函数  java中不行  但是要调用这个函数必须在定义后面
       def plus(x: int, y: int): int = {
      return x + y
    }// 证明:scala中的函数可以嵌套定义,函数中可以再定义函数
       //调用必须在定义之后
    val res2: int = plus(10, 20)
    println(res2)
  }
//需求1:定义一个求两个数之和的函数,返回结果
// 在main函数之外
  def add(a1: int, b1: int): int = {   
    return a1 + b1
  }
object demo5function {
  def main(args: array[string]): unit = {
  val res3: int = add2(11, 22)  // 报错
	 println(res3)
      
  val d1 = new demo1() //创建对象调用函数
    val res4: int = d1.add2(11, 22)
   	 println(res4)
  }
}
// 函数或者方法必须定义在class或者object中
def add2(a1: int, b1: int): int = {
  return a1 + b1
}

class demo1{
  //这里叫方法,将来调用时需要创建该类的对象才可以调用
  def add2(a1: int, b1: int): int = {
    return a1 + b1
  }
}
object demo5function {
  def main(args: array[string]): unit = {
  
  // 调用形式   
      //object中的函数可以使用类名调用,类似于静态一样
 	val res5: int = demo5function.add(100, 200)
   		println(res5)
//调用形式2:object中的函数调用时,可以省略类名
  	val res6: int = add(200, 300)
   		 println(res6)
      // 调用形式3
  	val res7: int = fun1("1000")
       println(res7)
      //如果方法调用的函数只有一个参数的时候,可以将.和小括号用空格代替调用
       val res8: int = demo5function fun1 "1000"   //  "=" * 50 -> "=".*(50)
  			println(res8)
      //如果定义的时候,没有小括号,调用的时候,就不需要加小括号
    		show
  }
    def fun1(s:string): int = {
    return s.toint
   //定义格式1:如果函数有返回值,且最后一句话作为返回值的话,return关键字可以不写
  def add3(a1: int, b1: int): int = {
    a1 + b1
  }
  //定义格式2:如果函数体中只有一句实现,那么大括号也可以不写
  def add4(a1: int, b1: int): int = a1 + b1

  //定义格式3:如果函数没有参数的时候,小括号省略不写
  def show= println("好好学习,天天向上!")
  }
}

函数的递归

/**
 * scala中的函数也可以递归
 * 方法定义时,调用自身的现象
 *
 * 条件:要有出口,不然就是死递归
 */
  def main(args: array[string]): unit = {
    //求阶乘 5!
    val res1: int = jiecheng(5)
    println(s"5的阶乘是$res1")

    println(s"5的阶乘是${demo6function jiecheng 5}") // 简写
  }
  def jiecheng(number: int): int = {
    if (number == 1) {
      1
    } else {
      number * jiecheng(number - 1)
    }
  }

9.类(面向对象)

 val s1: student = new student() //好好学习,天天向上!
/**
 * 可以在scala程序定义类
 * 类:构造方法 成员方法 成员变量
 *
 * 构造方法:
 * 1、在scala中构造方法的编写和在java中不太一样,类所拥有的大括号中都是构造代码块的内容
 * 2、默认情况下,每一个类都应该提供一个无参的构造方法
 * 3、构造方法可以有许多
 */
//这就是一个构造方法
class student{
   println("好好学习,天天向上!")    //理解为代码块   java中不行
}
// 带参构造
def main(args: array[string]): unit = {
 //    val s1: student = new student("jack",18)
    val s2: student = new student("jack", 18, "男")
     println(s2) // 打印的是地址 需要tostring方法
    
    //如果调用的是一个类的无参构造方法,new的时候小括号可以不用写
    val s3: student2 = new student2
    s3.fun1()
    
        //也可以使用多态的方式创建对象
//    val s4:student2=new student2   父类引用指向子类对象
    //    s4.fun1()  调用方法时 运行看左,编译看右  此时父类中没有此方法 报错
    val s4:object = new student("mike", 19, "男")
    println(s4.tostring)// 考虑这种做法
}
class student(name: string, age: int) {
  /**
   * 定义成员变量
   */
  val _name: string = name
  val _age: int = age
  var _gender: string = _ // 这个下划线,就表示将来会赋予默认值
    
    /**
   * 构造方法也可以写多个
   */
  def this(name: string, age: int, gender: string) {
    this(name: string, age: int)
    _gender = gender
  }
     /**
   * 也可以重写方法
   */
  override def tostring: string = {
    "姓名:" + _name + ", 年龄:" + _age + ", 性别:" + _gender
  }
}

class student2{
  def fun1()={
    println("牛逼666")
  }
}

与java创建类时一样,定义成员变量,构造方法,getset方法,重写tostring方法 非常麻烦

// caseclass
/**
 *  scala提供了一个非常好用的功能:样例类
 *  减少用户创建类所编写代码量,只需要定义成员变量即可,自动扩充成员变量,构造方法,重写tostring方法
 */
object demo8caseclass {
  def main(args: array[string]): unit = {
    val t1 = new teacher("jack", 22, "打胶")
    println(t1)
    println(t1.name)
    println(t1.age)
    println(t1.like)

    t1.like = "敲代码" 
    println(t1)// 改变了
  }
}

/**
 * 样例类中的成员变量,编译后默认是被jvm添加了final关键字,用户是改变不了的
 * 对于scala来说,默认是被val修饰的
 * 如果将来想要被改变,定义的时候需要使用var进行修饰
 */
case class teacher(name:string,age:int,var like:string)

apply

 def main(args: array[string]): unit = {
       val b1: book = new book()
       b1.apply() // 当作是一个普通的方法
 }
class book{
    def apply(): unit = {
        println("hhh")
    }
}
 def main(args: array[string]): unit = {
      book() // 理解为伴生对象  可以直接调用object中的功能
 }
object book{
    def apply(): unit = {
        println("hhh")
    }
}
 def main(args: array[string]): unit = {
    val b1: book = book("中华上下五千年", 999)
    println(b1)
  
}
 // object book 是 object book 的伴生对象  名字相同
object book {
  def apply(name:string,price:int): book = {
    new book(name,price)
  }
}
class book(name: string, price: int) {
  val _name: string = name
  val _price: int = price

  override def tostring: string = "书名:" + _name + ", 价格:" + _price
}

10.函数式编程

面向对象与函数式编程的区别:

//    是一个参数为字符串类型,返回值是整数类型的函数
        def fun1(s: string): int = {
          s.toint + 1000
        }
        val res1: int = fun1("1000")
        println(res1)
   //定义变量的方式,定义一个函数
        //将函数当作对象,赋值给类型是函数类型的变量,将来可以直接通过变量调用函数
        val fun2: string => int = fun1
        val res2: int = fun2("2000")
        println(res2)  // 3000
函数a作为函数b的参数定义
// f: string => int  相当于函数a
    // fun3  相当于函数b
    //定义  函数主体
        def fun3(f: string => int): int = {
          val a1: int = f("1000")
          a1 + 3000
        }
// 定义一个函数
    def show1(s:string): int = {
         s.toint
        }
      //调用
       val res1: int = fun3(show1)   // show1->f
       println(res1) // 4000

  	def show2(s: string): int = {
        s.toint+11111
       }
       val res2: int = fun3(show2)
  	   println(res2)// 15111
 //定义一个函数fun1, 函数的参数列表中,既有正常的类型参数,也有函数类型的参数
    def fun1(s: string, f: string => int): int = {
      val a1: int = f(s)
      a1 + 1000
    }
   def show1(s: string): int = {
          s.toint
        }

        def show2(s: string): int = {
          s.toint + 1111
        }

//    ..... 
        val res1: int = fun1("2000", show2)   // 可以传不同的函数 很麻烦  使用lambda简写
        println(res1)
 //使用lambda表达式改写函数作为参数传递的调用形式   直接把函数逻辑写在后面
    fun1("2000", (s: string) => s.toint)
    fun1("2000", (s: string) => s.toint+1000)

    //在scala中,数据类型可以自动类型推断
    fun1("2000", s => s.toint+1000)
    //如果当作参数的函数的参数只在函数主体使用了一次,那么可以使用_代替
    fun1("2000", _.toint+1000)

应用:遍历数组

  def main(args: array[string]): unit = {
    val arr1: array[int] = array(11, 22, 33, 44, 55)
      // 遍历  太麻烦 使用foreach函数
    //    for (e <- arr1) {
    //      println(e)
    //    }

//    def fun1(i: int): unit = {
//      println(i*2)
//    }

    //def foreach[u](f: a => u): unit
    //foreach函数需要一个参数和数组元素一样类型的类型,返回值是unit的函数
      
    //foreach函数的主要作用是将调用该方法的序列中的元素,依次取出传递给后面的函数进行处理
    arr1.foreach(fun1)

    // scala自带的一个函数
    // def println(x: any) = console.println(x)
    // any可以接收任意的数据类型元素
    arr1.foreach(println)
  }
函数当作返回值返回
 /**
     * fun1: 参数是string类型,返回值是一个函数(参数是string类型,返回值是int)
     */
//    定义返回值是函数的函数方式1:
        def fun1(s1: string): string => int = {
          def show(s: string): int = {   // 要返回的函数
            s.toint + s1.toint
          }
          show
        }
  // 调用函数的返回值是函数的方式1:
 	val resfun1: string => int = fun1("1")  // 把函数作为对象赋给一个变量   show-> resfun1
    val res1: int = resfun1("1000")
    println(res1)
    //    //调用方式2:
    //    val res2: int = fun1("1")("1000")
    //    println(res2)
 //定义方式2(是方式1的简化写法):

    /**
     * 方式2这种将参数分开定义,今后调用时可以分开传递,这种做法,在scala中叫做函数柯里化
     *
     */
    def fun1(s1: string)(s: string): int = {
      s.toint + s1.toint
    }
//函数柯里化:
        val resfun1: string => int = fun1("1")
            val r1: int = resfun1("11")
            println(r1)
            val r2: int = resfun1("12")
            println(r2)
            val r3: int = resfun1("13")
            println(r3)
// 调用方法和方式一相同
  def function1(s1: string, s2: string): int = {  // 返回值类型不是函数
      s1.toint + s2.toint
    }
  /**
     * 偏函数  
     * 分开传递
    */
    val f1: string => int = function1("1", _)  // 加_得到一个函数
    val res1: int = f1("1000")
    val res2: int = f1("2000")
    val res3: int = f1("3000")
    println(s"res1:$res1,res2:$res2,res3:$res3")

11.集合

java中的arraylist

def main(args: array[string]): unit = {
    val list1: util.arraylist[int] = new util.arraylist[int]()  // 创建arraylist
    list1.add(11)
    list1.add(22)
    list1.add(33)
    list1.add(44)
    //scala中的for循环,只能遍历scala中的序列,无法遍历java的序列
    //    for (e <- list1) {   无法使用
    //    }
    // 使用while循环遍历
    var i = 0
    while (i < list1.size()) {
      println(list1.get(i))
      i += 1
    }

scala的集合:

// list
   //创建了一个空集合
 val list1: list[nothing] = list()
   val list2: list[int] = list(34, 11, 22, 11, 33, 44, 55, 22, 75, 987, 1, 12, 34, 66)
// 1.获取list集合的长度
	println(list2.size)
    println(list2.length)
//2.通过索引下标获取元素
	println(list2(0))
    println(list2(1))
//3.scala推荐获取第一个元素的方式是调用head函数  最后一个元素调用last
 	println(list2.head)
    println(list2.last)
//4.根据指定的分隔符拼接元素
	println(list2.mkstring("|"))
//5.反转
	val reslist1: list[int] = list2.reverse
	println(s"list2:$list2")
    println(s"reslist1:$reslist1")
//6.去重
	val reslist2: list[int] = list2.distinct //返回一个新的集合
    println(s"list2:$list2")
    println(s"reslist2:$reslist2")
//7.去掉第一个元素 tail
	val reslist3: list[int] = list2.tail // 除去第一个,其余的元素返回一个新的集合
    println(s"list2:$list2")
    println(s"reslist3:$reslist3")
//8.取数(前几个)
	val reslist4: list[int] = list2.take(5) // 从左向右取元素,取若干个
    println(s"list2:$list2")
    println(s"reslist4:$reslist4")
//9.取数(靠右边的)
  	val reslist5: list[int] = list2.takeright(5) //取右边的几个,组成新的集合
    println(s"list2:$list2")
    println(s"reslist5:$reslist5")
//10.从第一个判断取数据,直到不符合条件停止
 	val reslist6: list[int] = list2.takewhile((e: int) => e % 2 == 0)
    println(s"list2:$list2")
    println(s"reslist6:$reslist6")
//11.求和
	val res1: int = list2.sum // 元素必须是数值
    println(s"集合中的元素和为:$res1")
//12.最值
 	val res2: int = list2.max
    println(s"集合中的元素最大值为:$res2")
//13.遍历集合
	for (e <- list2) {
      	println(e)
    }

//list的高阶函数

//foreach: 将集合中的元素依次取出传入到后面的函数中
//  注意:没有返回值的,要么就输出,要么就其他方式处理掉了
 //def foreach[u](f: a => u)
    list2.foreach((e: int) => println(e))
// 简写
      list2.foreach(println)
//需求1:使用foreach求出集合中偶数的和
    var ousum = 0
    var jisum = 0
    list2.foreach((e: int) => {
      if (e % 2 == 0) {
        ousum += e
      } else {
        jisum += e
      }
    })
    println(s"集合中偶数之和为:$ousum")
    println(s"集合中奇数之和为:$jisum")

// map: 依次处理每一个元素,得到一个新的结果,返回到一个新的集合中
 val list3: list[int] = list(1, 2, 3, 4, 5, 6, 7, 8, 9)
    //需求2:将集合中的每一个元素*2
    val reslist7: list[int] = list3.map((e: int) => e * 2)
    println(s"list3:$list3")
    println(s"reslist7:$reslist7")

//filter: 保留符合条件的元素
 val list4: list[int] = list(4, 7, 9, 10, 12, 11, 14, 9, 7)
    val reslist8: list[int] = list4.filter((e: int) => e % 2 == 0)
    println(s"list4:$list4")
    println(s"reslist8:$reslist8")

// sortby: 排序
// sortwith: 两个数之间的关系排序
   val reslist9: list[int] = list4.sortby((e: int) => -e)
    println(s"list4:$list4")
    println(s"reslist9:$reslist9")
    val reslist10: list[int] = list4.sortwith((x: int, y: int) => x > y)
    println(s"list4:$list4")
    println(s"reslist10:$reslist10")

//flatmap: 扁平化
	val list5: list[string] = list("hello|world|java", "hello|hadoop|flink", "scala|spark|hadoop")
    val restmp1: list[string] = list5.flatmap((e: string) => e.split("\\|"))
    restmp1.foreach(println)

// groupby: 分组
	val list6: list[string] = list("hello", "world", "java", "hadoop", "flink", "java", "hadoop", "flink", "flink", "java", "hadoop", "flink", "java", "hadoop", "hello", "world", "java", "hadoop", "hello", "world", "java", "hadoop")
    val map: map[string, list[string]] = list6.groupby((e: string) => e)  // 按照元素分组
    for (e <- map) {
      println(e)
    }
// set
//set集合:scala中的set集合也是不可变的,除了排序相关的函数以外,list集合有的高阶函数,set集合也有 无序
// 创建两个set集合
	val set1: set[int] = set(1, 4, 3, 6, 5)
    val set2: set[int] = set(3, 6, 5, 7, 8)
// 求交集
  //    val resset1: set[int] = set1.&(set2)
//    val resset1: set[int] = set1 & set2
    val resset1: set[int] = set1.intersect(set2)
 	println(s"set1: ${set1}")
    println(s"set2: ${set2}")
    println(s"交集: ${resset1}")  //(5,6,3)

//求并集
    //    val resset2: set[int] = set1.|(set2)
    val resset2: set[int] = set1 | set2
    println(s"set1: ${set1}")
    println(s"set2: ${set2}")
    println(s"并集: ${resset2}")

 //求差集
    //    val resset3: set[int] = set1.&~(set2)
    val resset3: set[int] = set1 &~ set2
    println(s"set1: ${set1}")
    println(s"set2: ${set2}")
    println(s"差集: ${resset3}")
 
//set集合和list集合相互转换  toset  tolist
 val list1: list[int] = list(11, 22, 33, 44, 55, 11, 22, 44, 88, 33, 44, 99, 11, 22, 55)
    //list->set
    val resset4: set[int] = list1.toset
    println(s"list1:${list1}")
    println(s"resset4:${resset4}")
    println("=" * 50)
    //set->list
    val list2: list[int] = resset4.tolist.sortby((e:int)=>e)
    println(s"list1:${list1}")
    println(s"resset4:${resset4}")
    println(s"list2:${list2}")
//mutable
 /**
     * 通过观察api发现,不可变的集合是属于scala.collection.immutable包下的
     * 如果将来想要使用可变的集合,就要去scala.collection.mutable包下寻找
     */
//创建一个可变的list集合
    val listbuffer1: listbuffer[int] = new listbuffer[int]
// 向集合中添加元素
 	listbuffer1.+=(11)
    listbuffer1.+=(22)
    listbuffer1.+=(33)
    listbuffer1.+=(11)
    listbuffer1.+=(55)
    listbuffer1.+=(22)
    listbuffer1.+=(33)
    listbuffer1.+=(66)
    listbuffer1.+=(33)
    println(listbuffer1)
//使用函数获取元素 同list集合 list集合的功能可变集合都能调用 
 	println(listbuffer1(2))
    println(listbuffer1.head)
    println(listbuffer1.last)
// 删除元素
 	listbuffer1.-=(33) //从左向右找元素,只会删除第一次找到的
//批量添加元素
    listbuffer1.+=(100,220,300,400)
// 直接添加一个集合进去
	val list1: list[int] = list(99, 88, 77)
    listbuffer1.++=(list1)

// 可变的set集合  功能同set集合
 	val hashset1: mutable.hashset[int] = new mutable.hashset[int]()
    val set1: hashset1.type = hashset1.+=(1, 2, 3, 4, 5, 7, 1, 2, 3, 1, 6, 5)
    println(set1)
// tuple
//大小,值是固定的,根据创建的类来定,每个元素的数据类型可以是不一样,最高可以创建存储22个元素的元组
// 不可变  保护信息
// 创建一个5元组
 val t1: (int, string, string, int, string) = tuple5(1001, "jack", "男", 17, "学习")
// case class student1(id: int, name: string, age: int, like: string)
 val s2: student1 = new student1(1002, "mike", 18, "看剧")
    val t2: (int, student1) = tuple2(1002, s2)
    println(t2._2.name)
//map
//创建map集合  元素是键值对形式
//键是唯一的,键一样的时候,值会被覆盖
val map1: map[int, string] = map((1001, "张三"), (1002, "李四"), (1003, "王五"), (1001, "赵六"), 1005 -> "老刘")
    println(map1)
//可以根据键获取值
   //    println(map1(1006)) // 小括号获取值,键不存在报错
    //    println(map1.get(1006)) // get函数获取,键不存在,返回none
 	println(map1.getorelse(1006, 0)) //根据键获取值,若键不存在,返回提供的默认值,默认值的类型可以是任意数据类型

 	val keys: iterable[int] = map1.keys // 获取所有的键,组成一个迭代器
    for (e <- keys) {
      	println(e)
    }
	val values: iterable[string] = map1.values // 获取所有的值,组成一个迭代器
    for (e <- values) {
      	println(e)
    }
// 遍历map
  //遍历map集合第一种方式,先获取所有的键,根据键获取每个值
    val keys2: iterable[int] = map1.keys // 获取所有的键,组成一个迭代器
    for (e <- keys2) {
      val v: any = map1.getorelse(e, 0)
      println(s"键:${e}, 值:${v}")
    }

    //遍历map集合第二种方式
    for (kv <- map1) { // 直接遍历map集合,得到每一个键值对组成的元组
      println(s"键:${kv._1}, 值:${kv._2}")
    }

    //遍历map集合第三种方式
    map1.foreach((kv: (int, string)) => println(s"键:${kv._1}, 值:${kv._2}"))

集合的应用案例

wordcount:

def main(args: array[string]): unit = {
    //1、读取数据文件,将每一行数据封装成集合的元素
    val linelist: list[string] = source.fromfile("scala/data/words.txt").getlines().tolist
    println(linelist)
    //2、将每一行数据按照|切分,并且进行扁平化
    val wordslist: list[string] = linelist.flatmap((line: string) => line.split("\\|"))
    println(wordslist)
    //3、根据元素进行分组
    val wordkv: map[string, list[string]] = wordslist.groupby((e: string) => e)
    println(wordkv)

    /**
     * list((world,8), (java,11),...)
     */
    val wordcount: map[string, int] = wordkv.map((kv: (string, list[string])) => {
      val word: string = kv._1
      val count: int = kv._2.size
      (word, count)
    })

    println("="*50)
    val resultlist: list[(string, int)] = wordcount.tolist
    resultlist.foreach(println)
    println("="*50)

//    /**
//     * 使用链式调用的方式简写
//     */
//    source.fromfile("scala/data/words.txt")
//      .getlines()
//      .tolist
//      .flatmap((line:string)=>line.split("\\|"))
//      .groupby((e:string)=>e)
//      .map((kv: (string, list[string])) => {
//        val word: string = kv._1
//        val count: int = kv._2.size
//        (word, count)
//      })
//      .tolist
//      .foreach(println)
}
}

12.jdbc

import java.sql.{connection, drivermanager, preparedstatement, resultset}

/**
 *  jdbc的链接步骤
 *    1、注册驱动
 *    2、创建数据库链接对象
 *    3、创建数据操作对象
 *    4、执行sql语句
 *    5、如果第4步是查询的话,分析查询结果
 *    6、释放资源
 */

object demo20jdbc {
  def main(args: array[string]): unit = {
    //1、注册驱动
    class.forname("com.mysql.jdbc.driver")

    //2、创建数据库链接对象
    //jdbc:数据库名://host:port/数据库?xxx=xxx&xxx=xxx
    val conn: connection = drivermanager.getconnection("jdbc:mysql://master:3306/y1?useunicode=true&characterencoding=utf-8&usessl=false", "root", "123456")

    //3、创建数据操作对象
    val preparedstatement: preparedstatement = conn.preparestatement("select id,name,age,gender,clazz from student where clazz=?")

    //4、执行sql语句
    // 防止sql注入
//    preparedstatement.setint(1,23)
    preparedstatement.setstring(1, "理科二班")
    val resultset: resultset = preparedstatement.executequery()
    //5、如果第4步是查询的话,分析查询结果
    while (resultset.next()){
      val id: int = resultset.getint("id")
      val name: string = resultset.getstring("name")
      val age: int = resultset.getint("age")
      val gender: string = resultset.getstring("gender")
      val clazz: string = resultset.getstring("clazz")

      println(s"学号:$id, 姓名:$name, 年龄:$age, 性别:$gender, 班级:$clazz")
    }

    //6、释放资源
    conn.close()

  }
}

13.json

导入依赖

 <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupid>com.alibaba</groupid>
            <artifactid>fastjson</artifactid>   
               <version>2.0.49</version>
        </dependency>
import scala.io.source
import com.alibaba.fastjson.{json, jsonarray, jsonobject}
def main(args: array[string]): unit = {
    val linelist: list[string] = source.fromfile("scala/data/stu.json").getlines().tolist
    // 拼起来
    val jsonstr: string = linelist.mkstring("\r\n")

    //使用fastjson包中的json类,将一个字符串转成json对象
    //转成json对象之后,可以通过键获取值
    //parseobject 将整体转成一个json格式数据
    val jsonobj1: jsonobject = json.parseobject(jsonstr)
    // 键获取值
    val s1: string = jsonobj1.getstring("student_list")


    //parsearray将一个"[{},{}]"变成一个元素是json对象的数组
    val jsonarray: jsonarray = json.parsearray(s1)
    // 遍历数组
    var i = 0
    while (i < jsonarray.size()) {
      val obj1: jsonobject = jsonarray.getjsonobject(i)
      val name: string = obj1.getstring("name")
      val like: string = obj1.getstring("like")
      println(s"${name}的爱好是${like}")
      i += 1
    }
  }

14.scala,java集合的转换

  def main(args: array[string]): unit = {
    //创建一个java中的集合
    val array1: util.arraylist[int] = new util.arraylist[int]()
    array1.add(11)
    array1.add(22)
    array1.add(33)
    array1.add(66)
    array1.add(55)
    array1.add(44)
    println(array1)

    /**
     * 将java中的集合转成scala中的集合
     *
     * java中的集合本来是没有转换scala的功能,需要导入隐式转换
     * scala中的导包,可以在任意地方
     *
     */
    import scala.collection.javaconverters._
      
    val list1: list[int] = array1.asscala.tolist
    println(list1)

    /**
     * scala中的集合转java的集合
     */
    val list2: util.list[int] = list1.asjava
    println(list2)
  }
}

15.模式匹配

 /**
     * 可以匹配变量值
     */
    var i: int = 100
    i match {
      case 20 => println("该值是20")
      case 50 => println("该值是50")
      //      case 100=>println("该值是100")
      case _ => println("其他值")
    } // 其他值

/**
//     * 匹配数据类型
//     */
    var flag1: any = true
    flag1 match {
      case _: int => println("是int类型")
      case _: boolean => println("是boolean类型")
    }

/**
//     * 匹配元组
//     */
    val t1: (int, string, int) = tuple3(1001, "张三", 18)
    t1 match {
      case (a1: int, b1: string, c1: int) =>
        println(s"学号:$a1, 姓名:$b1, 年龄:$c1")
    }

//
//    /**
//     * 匹配数组
//     */
    val array: array[any] = array(1001, "李四", "男", 18, "理科一班")
    array match {
      case array(id: int, name: string, gender: string, age: int, clazz: string) =>
        println(s"学号:$id, 姓名:$name, 性别:$gender, 年龄:$age, 班级:$clazz")
    }

模式匹配的应用:

 /**
     * 模式匹配的应用1:避免异常
     *
     */
    val map1: map[int, string] = map((1001, "张三"), (1002, "李四"))
    //    val res1: option[string] = map1.get(1001) // some("张三")
//   .get 方法获取值
    //    println(res1.get)
    //    val res1: option[string] = map1.get(1003)
    //    println(res1.get)

    val sc: scanner = new scanner(system.in)
    println("请输入要查询的键:")
    val key: int = sc.nextint()
    map1.get(key) match {
      case some(a: any) => println(s"${key}键对应的值为$a")
      case none => println(s"${key}键不存在!")
    }// 输入1001 输出 1001键对应的值为张三
	// 输入1003 输出 1003键不存在

    /**
     * 模式匹配的应用2:简化代码
     *students.txt 部分数据:
     *	1500100066,惠耘涛,22,男,文科三班
	 *	1500100067,广浦泽,22,男,文科五班
	 *	1500100068,宣南蓉,23,女,理科一班
     */

    val stulist: list[string] = source.fromfile("scala/data/students.txt").getlines().tolist
    val stuarraylist: list[array[string]] = stulist.map((line: string) => line.split(","))

// 不用模式匹配
    stuarraylist.map((e:array[string])=>{
      val id: string = e(0)
      val name: string = e(1)
      val age: string = e(2)
      val gender: string = e(3)
      val clazz: string = e(4)
      (id, name, gender, age, clazz)
    }).foreach(println)

// 使用模式匹配
    stuarraylist.map{
      case array(id: string, name: string, gender: string, age: string, clazz: string)=>
        (id, name, gender, age, clazz)
    }.foreach(println)

16.隐式转换

scala中的隐式转换:

// 隐式转换函数
// 将一个a类型将来会自动地转换成另一个b类型,类型可以式基本数据类型,也可以是引用数据类型

   var i:string = "100"
        //显式转换
        val res1: int = i.toint

//    定义一个函数
        def fun1(s: int): int = {
          return s + 1000
        }
        //调用函数
        println(fun1(100))
        println(fun1(200))
        println(fun1("300".toint))
		

// 	定义隐式转换函数
//需求:调用fun1函数,就只传字符串,不会报错
 //在需要返回值类型的功能的时候,自动地根据已有隐式转换函数将参数的类型转成返回值的类型
// 参数类型和返回值类型相同时,尽管函数体不一样,也是重复的隐式函数
		  implicit def implicitfun1(s: string): int = {
          return integer.parseint(s)
        }
		//调用函数
        println(fun1(100))
        println(fun1(200))
        println(fun1("300"))  // 不报错,有结果
// 读文件时的隐式转换  将字符串自动转换为bufferedsource类
object demo11 {
  implicit def implicitfun3(s: string): bufferedsource = source.fromfile(s)

  implicit def implicitfun1(s: string): int = integer.parseint(s)
}
import com.shujia.jichu.demo11._
        val stulist: list[string] = "scala/data/students.txt".getlines().tolist
        val scorelist: list[string] = "scala/data/scores.txt".getlines().tolist
 	println("1000" + 500) // 1000500 // 优先使用字符串自身的+拼接功能,做字符串拼接
    println("1000" - 500) // 500   // 字符串中没有-减法功能,自动使用隐式转换中的函数,将字符串转成数字做减法
    println("2000" - 500) // 1500   // 字符串中没有-减法功能,自动使用隐式转换中的函数,将字符串转成数字做减法

/**
 *  隐式转换类
 */
 def main(args: array[string]): unit = {
			// 正常做法
     // 创建对象,使用函数
        val demo1 = new demo12("scala/data/students.txt")
    	val stulist: list[string] = demo1.show1()
	// 定义隐式转换类之后  字符串自动转换为对象
         val stulist: list[string] = "scala/data/students.txt".show1()

		
 }
// 定义一个隐式转换类 读取文件信息
  //`implicit' modifier cannot be used for top-level objects  不能写在object外面
  //implicit class demo12(path: string) {
  //implicit使用的地方,不能超过object作用域
  implicit class demo12(path: string) {
    def show1(): list[string] = {
      source.fromfile(path).getlines().tolist
    }
/**
 * 隐式转换变量
 */
  def main(args: array[string]): unit = {
      // 之前没有定义过读取文件编码,是因为 def fromfile(name: string)(implicit codec: codec): bufferedsource  存在隐式转换参数codec 默认utf-8 可以手动修改
 source.fromfile("scala/data/students.txt")(codec("gbk")).getlines().tolist
      
       //定义一个隐式转换参数
    def fun1(a1: int)(implicit a2: int): int = a1 + a2

    //定义一个隐式转换变量
    implicit var i1: int = 1000
// a2可以不用传,寻找int类型的变量,直接使用默认值
    val res1: int = fun1(100)
    println(res1) //1100
  }

scala进阶应用:

阶段一

1.统计班级人数 [班级,人数]

2.统计学生的总分 [学号,学生姓名,学生年龄,总分]

阶段二

1、统计年级排名前十学生各科的分数 [学号, 姓名,班级,科目,分数]

2、统计总分大于年级平均分的学生 [学号,姓名,班级,总分]

3、统计每科都及格的学生 [学号,姓名,班级,科目,分数]

4、统计每个班级的前三名 [学号,姓名,班级,分数]

5、统计偏科最严重的前100名学生 [学号,姓名,班级,科目,分数]

数据准备:

部分数据截图:

students.txt

image.png

score.txt

image.png

subject.txt

image.png
import scala.collection.immutable
import scala.io.source

object homework {

  //定义一些变量,样例类,为后续的开发做准备

  /**
   * 定义一些样例类  类似于java的封装
   */
  private case class student(id: string, name: string, age: int, gender: string, clazz: string)

  private case class score(id: string, subject_id: string, score: int)

  private case class subject(subject_id: string, subject_name: string, subject_score: int)

  /**
   * 定义三个存储三个不同对象的list集合
   */
  private var stulist: list[student] = _
  private var scorelist: list[score] = _
  private var subjectlist: list[subject] = _

  /**
   * 定义一些map集合
   * stuinfomap  (stu.id, stu.name + "," + stu.clazz)
   * subnamemap  (subject.subject_id, subject.subject_name)
   * subscoremap (subject.subject_id, subject.subject_score)
   */
  private var stuinfomap: map[string, string] = _
  private var subnamemap: map[string, string] = _
  private var subscoremap: map[string, int] = _

  //初始化变量
  private def loaddata(): unit = {
    //读取学生数据
    stulist = "scala/data/students.txt".load()
      .map {
        case array(id: string, name: string, age: string, gender: string, clazz: string) =>
          student(id, name, age.toint, gender, clazz)
      }

    //读取成绩数据
    scorelist = "scala/data/score.txt".load()
      .map {
        case array(id: string, subject_id: string, score: string) =>
          score(id, subject_id, score.toint)
      }

    //读取科目数据
    subjectlist = "scala/data/subject.txt".load()
      .map {
        case array(subject_id: string, subject_name: string, subject_score: string) =>
          subject(subject_id, subject_name, subject_score.toint)
      }

    //处理三个map集合
    //stuinfomap 存储了学生的学号为键,姓名和班级作为值
    stuinfomap = stulist.map((stu: student) => (stu.id, stu.name + "," + stu.clazz)).tomap
    subnamemap = subjectlist.map((sub: subject) => (sub.subject_id, sub.subject_name)).tomap
    subscoremap = subjectlist.map((sub: subject) => (sub.subject_id, sub.subject_score)).tomap
  }

  /**
   * 根据学号集合打印【学号,姓名,班级,科目,分数】
   */
  private def printstudentinfowithid(ids: list[string]): unit = {
    // 从总的学生成绩信息中过滤出来
    scorelist.filter((sco: score) => ids.contains(sco.id))
      .map {
        case score(id: string, subject_id: string, score: int) => {
          //根据学号,查找姓名和班级 stuinfomap
          val namewithclazz: string = stuinfomap.getorelse(id, "查无此人")
          //根据科目编号,查找科目的名字 subnamemap
          val subject_name: string = subnamemap.getorelse(subject_id, "无此科目")
          s"[$id,$namewithclazz,$subject_name,$score]"
        }
      }.foreach(println)
  }


  /**
   * 统计班级人数 [班级,人数]
   */
  private def xuqiu1(): unit = {
    stulist.groupby((stu: student) => stu.clazz)
      .map((kv: (string, list[student])) => {
        s"[${kv._1},${kv._2.size}]"
      }).foreach(println)

  }

  /**
   * 统计学生的总分 [学号,学生姓名,学生年龄,总分]
   */
  private def xuqiu2(): unit = {
    val stringtoint: map[string, int] = scorelist.groupby((sco: score) => sco.id)
      .map((kv: (string, list[score])) => {
        (kv._1, kv._2.map(_.score).sum)
      })

    val ids: list[string] = stringtoint.map {
      case (id: string, _: int) => id
    }.tolist

    stulist.filter((stu: student) => ids.contains(stu.id))
      .map((stu: student) => {
        val sumscore: int = stringtoint.getorelse(stu.id, 0)
        s"[${stu.id},${stu.name},${stu.age},$sumscore]"
      }).foreach(println)
  }


  /**
   * 统计年级排名前十学生各科的分数 [学号,姓名,班级,科目,分数]
   */
  private def xuqiu3(): unit = {
    val ids: list[string] = scorelist.groupby((s: score) => s.id) // 按照学号进行分组
      .map((kv: (string, list[score])) => {
        (kv._1, kv._2.map(_.score).sum) // 求每个学生的总分
      })
      .tolist
      .sortby(-_._2)
      .take(10)
      .map(_._1)

    printstudentinfowithid(ids) // 学号,姓名,班级,科目,分数
  }

  /**
   * 统计总分大于年级平均分的学生 [学号,姓名,班级,总分]
   */
  private def xuqiu4(): unit = {
    //先计算年级平均分 372
    val avgscore: int = scorelist.map(_.score).sum / stulist.size
    //    println(avgscore)

    //计算每个人总分进行过滤
    scorelist.groupby((s: score) => s.id) // 按照学号进行分组
      .map((kv: (string, list[score])) => {
        (kv._1, kv._2.map(_.score).sum) // 求每个学生的总分
      })
      .filter(_._2 > avgscore)
      .map((t: (string, int)) => {
        //根据stuinfomap获取学生的姓名和班级
        val namewithclazz: string = stuinfomap.getorelse(t._1, "查无此人")
        s"[${t._1},$namewithclazz,${t._2}]"
      }).foreach(println)
  }

  /**
   * 统计每科都及格的学生 [学号,姓名,班级,科目,分数]
   */
  private def xuqiu5(): unit = {
    //1500100001,1000001,98
    val ids: list[string] = scorelist.filter((sco: score) => sco.score >= subscoremap.getorelse(sco.subject_id, 0) * 0.6)
      .groupby(_.id) // 根据学号分组,过滤6门考试都及格的学生
      .filter(_._2.size == 6)
      .keys
      .tolist

    printstudentinfowithid(ids)
  }

  /**
   * 统计每个班级的前三名 [学号,姓名,班级,分数]
   */
  private def xuqiu6(): unit = {
    val ids: list[string] = scorelist
      .groupby((s: score) => s.id) // 按照学号进行分组
      .map((kv: (string, list[score])) => {
        val namewithclazz: string = stuinfomap.getorelse(kv._1, "查无此人")
        val infos: array[string] = namewithclazz.split(",")
        val name: string = infos(0)
        val clazz: string = infos(1)
        (kv._1, name, clazz, kv._2.map(_.score).sum) // 求每个学生的总分
      })
      .groupby(_._3) // 根据班级进行分组
      .flatmap((kv: (string, iterable[(string, string, string, int)])) => {
        kv._2.tolist.sortby(-_._4).take(3)
      }).map(_._1).tolist

    // 从总的学生成绩信息中过滤出来
    scorelist.filter((sco: score) => ids.contains(sco.id))
      .map {
        case score(id: string, subject_id: string, score: int) => {
          //根据学号,查找姓名和班级 stuinfomap
          val namewithclazz: string = stuinfomap.getorelse(id, "查无此人")
          s"[$id,$namewithclazz,$score]"
        }
      }.foreach(println)
  }

  /**
   * 统计偏科最严重的前100名学生  [学号,姓名,班级,科目,分数]
   *
   * 方差
   * (每个人的各科分数-6门考试的平均分)^2 / 科目数
   *
   */
  private def xuqiu7(): unit = {
    //归一化
    val ids: list[string] = scorelist.map {
      case score(id: string, subject_id: string, score: int) =>
        (id: string, subject_id: string, score * 100 / subscoremap.getorelse(subject_id, 0))
    }.groupby(_._1) //根据学号进行分组
      .map((kv: (string, list[(string, string, int)])) => {
        val id: string = kv._1
        val scorelist: list[(string, string, int)] = kv._2
        //每个人的平均分
        val avgscore: int = scorelist.map(_._3).sum / scorelist.size
        //求方差
        val fangcha: double = scorelist.map((t3: (string, string, int)) => math.pow(t3._3 - avgscore, 2)).sum / scorelist.size
        (id, fangcha)
      })
      .tolist
      .sortby(-_._2)
      .take(100)
      .map(_._1)

    printstudentinfowithid(ids)
  }

  def main(args: array[string]): unit = {
    loaddata()

    //    xuqiu1()
    //    xuqiu2()
    //    xuqiu3()
    //    xuqiu4()
    //    xuqiu5()
    //    xuqiu6()
    xuqiu7()
  }

  //定义一个隐式转换类
  //将来可以直接通过文件路径获取一个封装了行数据的集合
  implicit class load(path: string) {
    def load(): list[array[string]] = {
      source.fromfile(path).getlines().tolist.map((line: string) => line.split(","))
    }
  }

}
(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com