Scala--03

news2024/11/27 3:53:56

6 面向对象

Scala 的面向对象思想和Java 的面向对象思想和概念是一致的。

Scala 中语法和 Java 不同,补充了更多的功能。

6.1类和对象详解

6.1.1组成结构

  • 构造函数: 在创建对象的时候给属性赋值
  • 成员变量:
  • 成员方法(函数)
  • 局部变量
  • 代码块

6.1.2构造器

每个类都有一个主构造器,这个构造器和类定义"交织"在一起类名后面的内容就是主构造器,如果参数列表为空的话,()可以省略
scala的类有且仅有一个主构造器,要想提供更加丰富的构造器,就需要使用辅助构造器,辅助构造器是可选的,它们叫做this   def this

注意:主构造器会执行类定义中的所有语句

代码示例:

Scala
// 类默认有一个无参的主构造函数
class User {
}

val user: User = new User

//
两个参数的主构造函数
class User2(val name: String, age: Int) {

}
val user2 = new User2("jim", 23)
//
使用val修饰的变量默认是成员变量,对象可以访问
// user2.age   // age没有使用val或者var修饰 所以不能被访问,他不是一个成员变量,而是一个局部变量


//辅助构造器
class User3 {
   var name: String = _
   var age: Int = _
  // 辅助构造函数
  def this(name: String, age: Int) {
    // 构造函数中的首行必须调用主构造函数或者其他构造函数
    this()
    this.name = name
    this.age = age
  }
  // 辅助构造函数
  def this(msg: String) = {
    // 首行调用一个构造
    this("ww", 12)
    println(msg)
  }
}
val u1 = new User3()
val u2 = new User3("")
val u3 = new User3("lisi", 23)
println(u3.name)

总结:

  1. 有两类构造器:主构造器,辅助构造器
  1. 构造器的定义位置:主构造器和类交织在一起,class Student2(val name: String, var age: Int)
  1. 辅助构造器是一个特殊的方法,定义在类中 def this(name:String,age:Int,gender:String)
  1. 辅助构造器,第一行必须调用主构造器(或者其他的辅助构造器)
  1. 辅助构造器的参数不能和主构造器的参数完全一致(参数个数,参数类型,参数顺序)
  1. 可以定义空参的辅助构造器,但是主构造器的参数必须进行初始化赋值
  1. 作用域:辅助构造器的变量作用域,只在方法中,主构造器的作用域是类中除了成员属性和成员方法之外的所有范围(可以通过反编译查看源码)

构造器的参数说明

  • 主构造函数中使用val 和 var修饰的变量为成员变量
  • val 修饰的变量默认只有getter方法   一要初始化
  • var 修饰的变量默认有 get和set方法  直接点属性操作  使用 _ 占位可以稍后赋值
  • @BeanProperty会生成getMsg setMsg方法

6.1.3成员方法/函数

在类的成员位置定义的函数或者方法是类的成员的一部分

6.1.4代码块

在类或者对象中的代码块在实例化的时候会被调用 

  • 在类成员位置的代码块  构造代码块 每次创建对象都会执行一次
  • 在object中成员位置的代码块是静态代码块  只执行一次
  • 代码有返回值

6.1.5object类的底层原理

Scala
package com.doit.day01.day02

//如果构造器中的变量,不加var 或者val 那他就是一个局部变量
//加了var 或者val 的话他就是一个私有的成员变量
class Student1(var id: Int, val name: String) {

  def sayHello: Unit = {
    println(name + ":
你好")
  }

  val sayFunc = () => {
    println("hello:" + name)
  }
}


object Student2{
  var id: Int = 1
  //
如果在成员变量的位置上给一个_作为占位符,相当于是给他赋了一个默认值啊
  var name: String =_

  def sayHello: Unit = {
    println(name + ":
你好")
  }
  val sayFunc = (x:String) => {
    println("hello:" + name + x)
  }
}


object Demo01_
面向对象 {
  def main(args: Array[String]): Unit = {

    Student2.sayFunc("a")

    val student1: Student1 = new Student1(1, "zhangsan")
    println(student1.name)
    println(student1.id)
    //    student1.name = "lisi" 
用val 修饰的,不能修改
    student1.id = 2
    println(student1.id)

    student1.sayHello
    student1.sayFunc()
    println(Student2.name)
  }
}

java手写实现:

Java
package com.doit;


public class Person {
    public static String getName(){
        return Person$.person.getName();
    }

    public static Integer getAge(){
        return Person$.person.getAge();
    }

    public static void setName(String name ){
        Person$.person.setName(name);
    }

    public static void setAge(Integer age ){
        Person$.person.setAge(age);
    }
}

class Person$ {
    //
自己的对象
    public static Person$ person ;
    //
成员变量
    private String name;
    private int age;

    static {
        person  = new Person$();
    }

    private Person$() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}


class Test{
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("张三");
        person.setAge(18);
        String name1 = person.getName();
        Integer age1 = person.getAge();
        System.out.println(name1);
        System.out.println(age1);
    }
}

scala中底层反编译后的代码:

Java
//decompiled from Student2$.class
package com.doit.day01.day02;

import java.lang.invoke.SerializedLambda;
import scala.Function1;
import scala.Predef.;
import scala.runtime.BoxedUnit;

public final class Student2$ {
   public static Student2$ MODULE$;
   private int id;
   private String name;
   private final Function1 sayFunc;

   static {
      new Student2$();
   }

   public int id() {
      return this.id;
   }

   public void id_$eq(final int x$1) {
      this.id = x$1;
   }

   public String name() {
      return this.name;
   }

   public void name_$eq(final String x$1) {
      this.name = x$1;
   }

   public void sayHello() {
      .MODULE$.println((new StringBuilder(3)).append(this.name()).append(":
你好").toString());
   }

   public Function1 sayFunc() {
      return this.sayFunc;
   }

// $FF: synthetic method
   public static final void $anonfun$sayFunc$1(final String x) {
      .MODULE$.println((new StringBuilder(6)).append("hello:").append(MODULE$.name()).append(x).toString());
   }

   private Student2$() {
      MODULE$ = this;
      this.id = 1;
      this.sayFunc = (x) -> {
         $anonfun$sayFunc$1(x);
         return BoxedUnit.UNIT;
      };
   }

// $FF: synthetic method
   private static Object $deserializeLambda$(SerializedLambda var0) {
      return var0.lambdaDeserialize<invokedynamic>(var0);
   }
}

 //decompiled from Student2.class
package com.doit.day01.day02;

import scala.Function1;
import scala.reflect.ScalaSignature;

@ScalaSignature(
   bytes = "\u0006\u0001!;Q\u0001D\u0007\t\u0002Y1Q\u0001G\u0007\t\u0002eAQ\u0001I\u0001\u0005\u0002\u0005BqAI\u0001A\u0002\u0013\u00051\u0005C\u0004(\u0003\u0001\u0007I\u0011\u0001\u0015\t\r9\n\u0001\u0015)\u0003%\u0011%y\u0013\u00011AA\u0002\u0013\u0005\u0001\u0007C\u0005=\u0003\u0001\u0007\t\u0019!C\u0001{!Iq(\u0001a\u0001\u0002\u0003\u0006K!\r\u0005\u0006\u0001\u0006!\t!\u0011\u0005\b\u0005\u0006\u0011\r\u0011\"\u0001D\u0011\u00199\u0015\u0001)A\u0005\t\u0006A1\u000b^;eK:$(G\u0003\u0002\u000f\u001f\u0005)A-Y=1e)\u0011\u0001#E\u0001\u0006I\u0006L\b'\r\u0006\u0003%M\tA\u0001Z8ji*\tA#A\u0002d_6\u001c\u0001\u0001\u0005\u0002\u0018\u00035\tQB\u0001\u0005TiV$WM\u001c;3'\t\t!\u0004\u0005\u0002\u001c=5\tADC\u0001\u001e\u0003\u0015\u00198-\u00197b\u0013\tyBD\u0001\u0004B]f\u0014VMZ\u0001\u0007y%t\u0017\u000e\u001e \u0015\u0003Y\t!!\u001b3\u0016\u0003\u0011\u0002\"aG\u0013\n\u0005\u0019b\"aA%oi\u00061\u0011\u000eZ0%KF$\"!\u000b\u0017\u0011\u0005mQ\u0013BA\u0016\u001d\u0005\u0011)f.\u001b;\t\u000f5\"\u0011\u0011!a\u0001I\u0005\u0019\u0001\u0010J\u0019\u0002\u0007%$\u0007%\u0001\u0003oC6,W#A\u0019\u0011\u0005IJdBA\u001a8!\t!D$D\u00016\u0015\t1T#\u0001\u0004=e>|GOP\u0005\u0003qq\ta\u0001\u0015:fI\u00164\u0017B\u0001\u001e<\u0005\u0019\u0019FO]5oO*\u0011\u0001\bH\u0001\t]\u0006lWm\u0018\u0013fcR\u0011\u0011F\u0010\u0005\b[\u001d\t\t\u00111\u00012\u0003\u0015q\u0017-\\3!\u0003!\u0019\u0018-\u001f%fY2|W#A\u0015\u0002\u000fM\f\u0017PR;oGV\tA\t\u0005\u0003\u001c\u000bFJ\u0013B\u0001$\u001d\u0005%1UO\\2uS>t\u0017'\u0001\u0005tCf4UO\\2!\u0001"
)
public final class Student2 {
   public static Function1 sayFunc() {
      return Student2$.MODULE$.sayFunc();
   }

   public static void sayHello() {
      Student2$.MODULE$.sayHello();
   }

   public static void name_$eq(final String x$1) {
      Student2$.MODULE$.name_$eq(var0);
   }

   public static String name() {
      return Student2$.MODULE$.name();
   }

   public static void id_$eq(final int x$1) {
      Student2$.MODULE$.id_$eq(var0);
   }

   public static int id() {
      return Student2$.MODULE$.id();
   }
}

练一练

需求1:1.定义一个object,里面放一个成员:base = 100

     2.定义一个工具方法:求两数之和,如果和<base 返回和,否则返回base

     3.定义一个工具函数:求两数的差,并且返回(差值<base 就返回base,否则返回差值)

     4.定义一个工具函数:求三个数的最大值,如果最大值<base 就返回base,否则返回最大值

Scala
object Max {
  val base = 100

  def sum(i: Int, j: Int) = {
    if (i + j < base) base else i + j
  }

  val cha = (i: Int, j: Int) => {
    if (i - j < base) base else i - j
  }

  val max = (a: Int, b: Int, c: Int) => {
    var mx = a
    if (b > mx) mx = b
    if (c > mx) mx = c
    if (mx > base) mx else base
  }
}

需求2:用java模拟一个object内部的实现原理,把需求1这个object类模拟出来

Java
//函数对应的接口
package com.doit;

public interface Function3<U,V,Y,Z> {
    Z apply(U u,V v,Y y);
}



package com.doit;

public interface Function2<U,V,T> {
    T apply(U u,V v);
}


//对象的.class
package com.doit;

//都是放的静态的
class Max {
    //这里面都是静态的,用Max$里面定义的对象去调用所有的成员属性,方法和函数
    private static int getBase(){
        return Max$.MODULE$.getBase();
    }

    private static int getMax(int a,int b,int c){
        return Max$.MODULE$.getMax().apply(a,b,c);
    }

    private static int getCha(int a,int b){
        return Max$.MODULE$.getCha().apply(a,b);
    }

    private static int getSum(int a,int b){
        return Max$.MODULE$.getCha().apply(a,b);
    }

}

//类似于java中的.class
class Max$ {
    //还要定义一个自己的对象,对象名字是MODULE$,为了上面静态的能访问到,所以他也要是静态的
    public static Max$ MODULE$;
    //定义成员变量,val修饰的,在java中前面要加final修饰
    private final Integer base = 100;
    //定义两个函数
    //两个数求差的函数
    private final Function2<Integer, Integer, Integer> cha = new Function2<Integer, Integer, Integer>() {
        @Override
        public Integer apply(Integer integer, Integer integer2) {
            return integer + integer2;
        }
    };

    //三个数求最大值的函数
    private final Function3<Integer, Integer, Integer, Integer> max = new Function3<Integer, Integer, Integer, Integer>() {
        @Override
        public Integer apply(Integer a, Integer b, Integer c) {
            int mx = a;
            if (b > mx) mx = b;
            if (c > mx) mx = c;
            if (mx < base) mx = base;
            return mx;
        }
    };

    //定义方法,两数求和
    public int sum(int a ,int b ){
        return a+b;
    }

    //get和set方法
    public int getBase(){
        return base;
    }
    //base 是常量,所以这边不用写set方法
//    private void setBase(int num){
//        this.base = num;
//    }

    //函数本质上也是一个类型哦,所以他也是成员变量的地位,需要写get方法哦

    public Function2<Integer, Integer, Integer> getCha(){
        return this.cha;
    }

    public Function3<Integer, Integer, Integer,Integer> getMax(){
        return this.max;
    }

    static {
        new Max$();
    }

    private Max$() {
        MODULE$ = this;
    }


}

6.1.6伴生类和伴生对象

条件 1:在同一个源文件中, 条件 2:对象名和类名相同

Scala
  //类名和object的名称一致
  //类是对象的伴生类
  //对象是类的伴生对象

class Demo6(val name: String) {
}
object Demo6 {
}

条件 2:伴生对象和伴生类之间可以互相访问彼此的私有属性和私有方法

Scala
package com.doit.day01.day02

/**
 *
伴生对象的用途:
 *      1.可以将静态的成员变量和普通成员变量分别声明
 *      2.伴生对象自己内部定义了一个apply方法,可以简化创建对象(类的实例构造)
 *      3.伴生对象自己定义了一个unapply方法,可以用于模式匹配
 */
class Car(var brand: String, var price: Double) {

  def sayHello(): Unit ={
    println("hello")
  }

  private val color: String = Car.color
  Car.start()
}


object Car {
  var color :String = "red"

  def start(): Unit ={
    println("汽车启动了,嗡~~~~~~~~")
  }
}

object Demo02_伴生对象 {
  def main(args: Array[String]): Unit = {
    val car: Car = new Car("华为", 9.9)
    println(car.brand)
    println(car.price)
    car.sayHello()
    Car.start()
  }
}

伴生对象的底层原理:

Java
//decompiled from Car.class
package com.doit.day01.day02;

import scala.Predef.;
import scala.reflect.ScalaSignature;

@ScalaSignature(
   bytes = "\u0006\u0001E3A\u0001E\t\u00015!A\u0011\u0005\u0001BA\u0002\u0013\u0005!\u0005\u0003\u0005/\u0001\t\u0005\r\u0011\"\u00010\u0011!)\u0004A!A!B\u0013\u0019\u0003\u0002\u0003\u001c\u0001\u0005\u0003\u0007I\u0011A\u001c\t\u0011m\u0002!\u00111A\u0005\u0002qB\u0001B\u0010\u0001\u0003\u0002\u0003\u0006K\u0001\u000f\u0005\u0006\u007f\u0001!\t\u0001\u0011\u0005\u0006\u000b\u0002!\tAR\u0004\u0006\u000fFA\t\u0001\u0013\u0004\u0006!EA\t!\u0013\u0005\u0006\u007f)!\tA\u0013\u0005\b\u0017*\u0001\r\u0011\"\u0001#\u0011\u001da%\u00021A\u0005\u00025Caa\u0014\u0006!B\u0013\u0019\u0003\"\u0002)\u000b\t\u00031%aA\"be*\u0011!cE\u0001\u0006I\u0006L\bG\r\u0006\u0003)U\tQ\u0001Z1zaER!AF\f\u0002\t\u0011|\u0017\u000e\u001e\u0006\u00021\u0005\u00191m\\7\u0004\u0001M\u0011\u0001a\u0007\t\u00039}i\u0011!\b\u0006\u0002=\u0005)1oY1mC&\u0011\u0001%\b\u0002\u0007\u0003:L(+\u001a4\u0002\u000b\t\u0014\u0018M\u001c3\u0016\u0003\r\u0002\"\u0001J\u0016\u000f\u0005\u0015J\u0003C\u0001\u0014\u001e\u001b\u00059#B\u0001\u0015\u001a\u0003\u0019a$o\\8u}%\u0011!&H\u0001\u0007!J,G-\u001a4\n\u00051j#AB*ue&twM\u0003\u0002+;\u0005I!M]1oI~#S-\u001d\u000b\u0003aM\u0002\"\u0001H\u0019\n\u0005Ij\"\u0001B+oSRDq\u0001\u000e\u0002\u0002\u0002\u0003\u00071%A\u0002yIE\naA\u0019:b]\u0012\u0004\u0013!\u00029sS\u000e,W#\u0001\u001d\u0011\u0005qI\u0014B\u0001\u001e\u001e\u0005\u0019!u.\u001e2mK\u0006I\u0001O]5dK~#S-\u001d\u000b\u0003auBq\u0001N\u0003\u0002\u0002\u0003\u0007\u0001(\u0001\u0004qe&\u001cW\rI\u0001\u0007y%t\u0017\u000e\u001e \u0015\u0007\u0005\u001bE\t\u0005\u0002C\u00015\t\u0011\u0003C\u0003\"\u000f\u0001\u00071\u0005C\u00037\u000f\u0001\u0007\u0001(\u0001\u0005tCfDU\r\u001c7p)\u0005\u0001\u0014aA\"beB\u0011!IC\n\u0003\u0015m!\u0012\u0001S\u0001\u0006G>dwN]\u0001\nG>dwN]0%KF$\"\u0001\r(\t\u000fQj\u0011\u0011!a\u0001G\u000511m\u001c7pe\u0002\nQa\u001d;beR\u0004"
)
public class Car {
   private String brand;
   private double price;

   public static void start() {
      Car$.MODULE$.start();
   }

   public static void color_$eq(final String x$1) {
      Car$.MODULE$.color_$eq(var0);
   }

   public static String color() {
      return Car$.MODULE$.color();
   }

   public String brand() {
      return this.brand;
   }

   public void brand_$eq(final String x$1) {
      this.brand = x$1;
   }

   public double price() {
      return this.price;
   }

   public void price_$eq(final double x$1) {
      this.price = x$1;
   }

   public void sayHello() {
      .MODULE$.println("hello");
   }

   public Car(final String brand, final double price) {
      this.brand = brand;
      this.price = price;
      super();
   }
}

        //decompiled from Car$.class
package com.doit.day01.day02;

import scala.Predef.;

public final class Car$ {
   public static Car$ MODULE$;
   private String color;

   static {
      new Car$();
   }

   public String color() {
      return this.color;
   }

   public void color_$eq(final String x$1) {
      this.color = x$1;
   }

   public void start() {
      .MODULE$.println("
汽车启动了,嗡~~~~~~~~");
   }

   private Car$() {
      MODULE$ = this;
      this.color = "red";
   }
}

       

图示:

伴生对象用途:

  1. 可以将静态的成员变量和普通成员变量分别声明(class中没办法添加静态成员,需要经过object类来添加)
  1. 伴生对象自己内部定义了一个apply方法,可以简化创建对象(类的实例构造)
  1. 伴生对象自己定义了一个unapply方法,可以用于模式匹配

6.1.6apply方法

使用此方法时,可以在main函数中不通过new来创建一个对象,即可以不用专门的一次一次地进行实例化,加载创建对象的这个类的时候,会自动调用apply这个方法,类似Java中的static静态块。

  1. 通过伴生对象的 apply 方法,实现不使用 new 方法创建对象。 
  1. apply 方法可以重载。
  1. Scala 中 obj(arg)的语句实际是在调用该对象的 apply 方法,即 obj.apply(arg)。用以统一面向对象编程和函数式编程的风格。
  1. 当使用 new 关键字构建对象时,调用的其实是类的构造方法,当直接使用类名构建对象时,调用的其实是伴生对象的 apply 方法。

Scala
object Test {
 def main(args: Array[String]): Unit = {
 //
(1)通过伴生对象的 apply 方法,实现不使用 new 关键字创建对象。
 val p1 = Person()
 println("p1.name=" + p1.name)
 val p2 = Person("bobo")
 println("p2.name=" + p2.name)
 }
}
//(2)如果想让主构造器变成私有的,可以在()之前加上 private
class Person private(cName: String) {
 var name: String = cName
}

object Person {
 def apply(): Person = {
 println("apply 空参被调用")
 new Person("xx")
 }
 
 def apply(name: String): Person = {
 println("apply 有参被调用")
 new Person(name)
}
}

6.2权限修饰符

在 Java 中,访问权限分为:public,private,protected 和默认。在 Scala 中,你可以通过类似的修饰符达到同样的效果。但是使用上有区别。

(1)Scala 中属性和方法的默认访问权限为 public,但 Scala 中无 public 关键字。

(2)private 为私有权限,只在类的内部和伴生对象中可用。

(3)protected 为受保护权限,Scala 中受保护权限比 Java 中更严格,同类、子类可以访问,同包无法访问。

(4)private[包名]增加包访问权限,包名下的其他类也可以使用

代码演示:

Scala
class Person {
 private var name: String = "bobo"
 protected var age: Int = 18
 private[test] var sex: String = "
男"
 def say(): Unit = {
 println(name)
 }
}
object Person {
 def main(args: Array[String]): Unit = {
 val person = new Person
 person.say()
 println(person.name)
 println(person.age)
 }
}
class Teacher extends Person {
 def test(): Unit = {
 this.age
 this.sex
 }
}
class Animal {
 def test: Unit = {
 new Person().sex
 }
}

6.3特质和抽象类

6.3.1特质

Trait(特质)相当于 java 的接口。比接口功能更强大。特质中可以定义属性和抽象方法和方法的实现。

Scala 的类只能够继承单一父类,但是可以实现(继承,混入)多个特质(Trait),使用的关键字是 with 和 extends

注意,特质不能有主构造函数

基本语法

Scala
trait 特质名 {
trait 主体
}

//如何使用特质:
没有父类:class 类名 extends 特质 1 with 特质 2 with 特质 3 …
有父类:class 类名 extends 父类 with 特质 1 with 特质 2 with 特质 3…

代码演示:

Scala
trait PersonTrait {
 //
声明属性
 var name:String = _
 // 声明方法
 def eat():Unit={
 }
 // 抽象属性
 var age:Int
 
 // 抽象方法
 def say():Unit
}

特质的本质就是抽象类+接口

6.3.1.2特质的动态混入

1.创建对象时混入 trait,而无需使类混入该 trait

2.如果混入的 trait 中有未实现的方法,则需要实现

代码演示:

Scala
trait PersonTrait {
 //
(1)特质可以同时拥有抽象方法和具体方法
 // 声明属性
 var name: String = _
 // 抽象属性
 var age: Int
 // 声明方法
 def eat(): Unit = {
 println("eat")
 }
 // 抽象方法
 def say(): Unit
}
trait SexTrait {
 var sex: String
}
//(2)一个类可以实现/继承多个特质
//(3)所有的 Java 接口都可以当做 Scala 特质使用
class Teacher extends PersonTrait with java.io.Serializable {
 override def say(): Unit = {
 println("say")
 }
 override var age: Int = _
}
object TestTrait {
 def main(args: Array[String]): Unit = {
 val teacher = new Teacher
 teacher.say()
 teacher.eat()
 //(4)动态混入:可灵活的扩展类的功能
 val t2 = new Teacher with SexTrait {
 override var sex: String = "男"
 }
 //调用混入 trait 的属性
 println(t2.sex)
 }
}

6.3.2抽象类

在 Scala 中, 使用 abstract 修饰的类称为抽象类. 在抽象类中可以定义属性、未实现的方法(抽象方法)和具体实现的方法。  含有抽象方法的类就是抽象类

  • 抽象类中的属性 
  • 抽象方法
  • 具体实现的方法
  • 类的单继承

示例:

Scala
/*
* abstract 修饰的类是一个抽象类
* */
abstract class Animal {
  println("Animal's constructor ....")
  //
定义一个 name 属性
  val name: String = "animal"
  //
没有任何实现的方法
  def sleep()
  //
带有具体的实现的方法
  def eat(f: String): Unit = {
    println(s"$f")
    }
  }

抽象类的继承和重写

  • 如果父类为抽象类,那么子类要么也是抽象类,要么就需要重写父类中的所有的抽象方法和抽象的成员变量
  • 重写非抽象方法需要用 override 修饰,重写抽象方法则可以不加 override。
  • 子类中调用父类的方法使用 super 关键字,在子类重写了父类的方法后,如果不加super,直接写方法名调用的就是子类重写后的,如果加了,调用的还是父类的
  • 子类对抽象属性进行实现,父类抽象属性可以用 var 修饰;子类对非抽象属性重写,父类非抽象属性只支持 val 类型,而不支持 var(var修饰具体方法和变量不好重写)

因为 var 修饰的为可变变量,子类继承之后就可以直接使用,没有必要重写

6.4样例类

使用case修饰的类就是样例类(封装数据,模式匹配)

  1. 构造器中的参数默认是val修饰的[成员,赋值1次]
  1. 样例类会自动创建伴生对象, 同时在里面实现;的apply和unapply方法 ,创建对象的时候不用new
  1. 很好的支持匹配模式
  1. 默认实现了自己的toString , hashCode , copy , equals,序列化方法

定义一个样例类:

Scala
case class Person(var name:String , var age:Int)
{}//
如果类中没有别的需要定义的,可以不写大括号

反编译之后的结果:

Scala
//decompiled from Person$.class
package com.doit.day01.day02;

import scala.Option;
import scala.Serializable;
import scala.Some;
import scala.Tuple2;
import scala.None.;
import scala.runtime.AbstractFunction2;
import scala.runtime.BoxesRunTime;

public final class Person$ extends AbstractFunction2 implements Serializable {
   public static Person$ MODULE$;

   static {
      new Person$();
   }

   public final String toString() {
      return "Person";
   }

   public Person apply(final String name, final int age) {
      return new Person(name, age);
   }

   public Option unapply(final Person x$0) {
      return (Option)(x$0 == null ? .MODULE$ : new Some(new Tuple2(x$0.name(), BoxesRunTime.boxToInteger(x$0.age()))));
   }

   private Object readResolve() {
      return MODULE$;
   }

   // $FF: synthetic method
   // $FF: bridge method
   public Object apply(final Object v1, final Object v2) {
      return this.apply((String)v1, BoxesRunTime.unboxToInt(v2));
   }

   private Person$() {
      MODULE$ = this;
   }
}

        //decompiled from Person.class
package com.doit.day01.day02;

import scala.Function1;
import scala.Option;
import scala.Product;
import scala.Serializable;
import scala.collection.Iterator;
import scala.reflect.ScalaSignature;
import scala.runtime.BoxesRunTime;
import scala.runtime.Statics;
import scala.runtime.ScalaRunTime.;

@ScalaSignature(
   bytes = "\u0006\u0001\u0005Uc\u0001\u0002\u000e\u001c\u0001\u0012B\u0001\"\r\u0001\u0003\u0012\u0004%\tA\r\u0005\t}\u0001\u0011\t\u0019!C\u0001\u007f!AQ\t\u0001B\tB\u0003&1\u0007\u0003\u0005G\u0001\tE\r\u0011\"\u0001H\u0011!Y\u0005A!a\u0001\n\u0003a\u0005\u0002\u0003(\u0001\u0005#\u0005\u000b\u0015\u0002%\t\u000b=\u0003A\u0011\u0001)\t\u000fU\u0003\u0011\u0011!C\u0001-\"9\u0011\fAI\u0001\n\u0003Q\u0006bB3\u0001#\u0003%\tA\u001a\u0005\bQ\u0002\t\t\u0011\"\u0011j\u0011\u001d\t\b!!A\u0005\u0002\u001dCqA\u001d\u0001\u0002\u0002\u0013\u00051\u000fC\u0004y\u0001\u0005\u0005I\u0011I=\t\u0013\u0005\u0005\u0001!!A\u0005\u0002\u0005\r\u0001\"CA\u0007\u0001\u0005\u0005I\u0011IA\b\u0011%\t\t\u0002AA\u0001\n\u0003\n\u0019\u0002C\u0005\u0002\u0016\u0001\t\t\u0011\"\u0011\u0002\u0018\u001dI\u00111D\u000e\u0002\u0002#\u0005\u0011Q\u0004\u0004\t5m\t\t\u0011#\u0001\u0002 !1q\n\u0006C\u0001\u0003[A\u0011\"!\u0005\u0015\u0003\u0003%)%a\u0005\t\u0013\u0005=B#!A\u0005\u0002\u0006E\u0002\"CA\u001c)\u0005\u0005I\u0011QA\u001d\u0011%\tY\u0005FA\u0001\n\u0013\tiE\u0001\u0004QKJ\u001cxN\u001c\u0006\u00039u\tQ\u0001Z1zaIR!AH\u0010\u0002\u000b\u0011\f\u0017\u0010M\u0019\u000b\u0005\u0001\n\u0013\u0001\u00023pSRT\u0011AI\u0001\u0004G>l7\u0001A\n\u0005\u0001\u0015Zc\u0006\u0005\u0002'S5\tqEC\u0001)\u0003\u0015\u00198-\u00197b\u0013\tQsE\u0001\u0004B]f\u0014VM\u001a\t\u0003M1J!!L\u0014\u0003\u000fA\u0013x\u000eZ;diB\u0011aeL\u0005\u0003a\u001d\u0012AbU3sS\u0006d\u0017N_1cY\u0016\fAA\\1nKV\t1\u0007\u0005\u00025w9\u0011Q'\u000f\t\u0003m\u001dj\u0011a\u000e\u0006\u0003q\r\na\u0001\u0010:p_Rt\u0014B\u0001\u001e(\u0003\u0019\u0001&/\u001a3fM&\u0011A(\u0010\u0002\u0007'R\u0014\u0018N\\4\u000b\u0005i:\u0013\u0001\u00038b[\u0016|F%Z9\u0015\u0005\u0001\u001b\u0005C\u0001\u0014B\u0013\t\u0011uE\u0001\u0003V]&$\bb\u0002#\u0003\u0003\u0003\u0005\raM\u0001\u0004q\u0012\n\u0014!\u00028b[\u0016\u0004\u0013aA1hKV\t\u0001\n\u0005\u0002'\u0013&\u0011!j\n\u0002\u0004\u0013:$\u0018aB1hK~#S-\u001d\u000b\u0003\u00016Cq\u0001R\u0003\u0002\u0002\u0003\u0007\u0001*\u0001\u0003bO\u0016\u0004\u0013A\u0002\u001fj]&$h\bF\u0002R'R\u0003\"A\u0015\u0001\u000e\u0003mAQ!M\u0004A\u0002MBQAR\u0004A\u0002!\u000bAaY8qsR\u0019\u0011k\u0016-\t\u000fEB\u0001\u0013!a\u0001g!9a\t\u0003I\u0001\u0002\u0004A\u0015AD2paf$C-\u001a4bk2$H%M\u000b\u00027*\u00121\u0007X\u0016\u0002;B\u0011alY\u0007\u0002?*\u0011\u0001-Y\u0001\nk:\u001c\u0007.Z2lK\u0012T!AY\u0014\u0002\u0015\u0005tgn\u001c;bi&|g.\u0003\u0002e?\n\tRO\\2iK\u000e\\W\r\u001a,be&\fgnY3\u0002\u001d\r|\u0007/\u001f\u0013eK\u001a\fW\u000f\u001c;%eU\tqM\u000b\u0002I9\u0006i\u0001O]8ek\u000e$\bK]3gSb,\u0012A\u001b\t\u0003WBl\u0011\u0001\u001c\u0006\u0003[:\fA\u0001\\1oO*\tq.\u0001\u0003kCZ\f\u0017B\u0001\u001fm\u00031\u0001(o\u001c3vGR\f%/\u001b;z\u00039\u0001(o\u001c3vGR,E.Z7f]R$\"\u0001^<\u0011\u0005\u0019*\u0018B\u0001<(\u0005\r\te.\u001f\u0005\b\t6\t\t\u00111\u0001I\u0003=\u0001(o\u001c3vGRLE/\u001a:bi>\u0014X#\u0001>\u0011\u0007mtH/D\u0001}\u0015\tix%\u0001\u0006d_2dWm\u0019;j_:L!a ?\u0003\u0011%#XM]1u_J\f\u0001bY1o\u000bF,\u0018\r\u001c\u000b\u0005\u0003\u000b\tY\u0001E\u0002'\u0003\u000fI1!!\u0003(\u0005\u001d\u0011un\u001c7fC:Dq\u0001R\b\u0002\u0002\u0003\u0007A/\u0001\u0005iCND7i\u001c3f)\u0005A\u0015\u0001\u0003;p'R\u0014\u0018N\\4\u0015\u0003)\fa!Z9vC2\u001cH\u0003BA\u0003\u00033Aq\u0001\u0012\n\u0002\u0002\u0003\u0007A/\u0001\u0004QKJ\u001cxN\u001c\t\u0003%R\u0019B\u0001FA\u0011]A9\u00111EA\u0015g!\u000bVBAA\u0013\u0015\r\t9cJ\u0001\beVtG/[7f\u0013\u0011\tY#!\n\u0003#\u0005\u00137\u000f\u001e:bGR4UO\\2uS>t'\u0007\u0006\u0002\u0002\u001e\u0005)\u0011\r\u001d9msR)\u0011+a\r\u00026!)\u0011g\u0006a\u0001g!)ai\u0006a\u0001\u0011\u00069QO\\1qa2LH\u0003BA\u001e\u0003\u000f\u0002RAJA\u001f\u0003\u0003J1!a\u0010(\u0005\u0019y\u0005\u000f^5p]B)a%a\u00114\u0011&\u0019\u0011QI\u0014\u0003\rQ+\b\u000f\\33\u0011!\tI\u0005GA\u0001\u0002\u0004\t\u0016a\u0001=%a\u0005Y!/Z1e%\u0016\u001cx\u000e\u001c<f)\t\ty\u0005E\u0002l\u0003#J1!a\u0015m\u0005\u0019y%M[3di\u0002"
)
public class Person implements Product, Serializable {
   private String name;
   private int age;

   public static Option unapply(final Person x$0) {
      return Person$.MODULE$.unapply(var0);
   }

   public static Person apply(final String name, final int age) {
      return Person$.MODULE$.apply(var0, var1);
   }

   public static Function1 tupled() {
      return Person$.MODULE$.tupled();
   }

   public static Function1 curried() {
      return Person$.MODULE$.curried();
   }

   public String name() {
      return this.name;
   }

   public void name_$eq(final String x$1) {
      this.name = x$1;
   }

   public int age() {
      return this.age;
   }

   public void age_$eq(final int x$1) {
      this.age = x$1;
   }

   public Person copy(final String name, final int age) {
      return new Person(name, age);
   }

   public String copy$default$1() {
      return this.name();
   }

   public int copy$default$2() {
      return this.age();
   }

   public String productPrefix() {
      return "Person";
   }

   public int productArity() {
      return 2;
   }

   public Object productElement(final int x$1) {
      Object var10000;
      switch(x$1) {
      case 0:
         var10000 = this.name();
         break;
      case 1:
         var10000 = BoxesRunTime.boxToInteger(this.age());
         break;
      default:
         throw new IndexOutOfBoundsException(BoxesRunTime.boxToInteger(x$1).toString());
      }

      return var10000;
   }

   public Iterator productIterator() {
      return .MODULE$.typedProductIterator(this);
   }

   public boolean canEqual(final Object x$1) {
      return x$1 instanceof Person;
   }

   public int hashCode() {
      int var1 = -889275714;
      var1 = Statics.mix(var1, Statics.anyHash(this.name()));
      var1 = Statics.mix(var1, this.age());
      return Statics.finalizeHash(var1, 2);
   }

   public String toString() {
      return .MODULE$._toString(this);
   }

   public boolean equals(final Object x$1) {
      boolean var6;
      if (this != x$1) {
         label55: {
            boolean var2;
            if (x$1 instanceof Person) {
               var2 = true;
            } else {
               var2 = false;
            }

            if (var2) {
               label38: {
                  label37: {
                     Person var4 = (Person)x$1;
                     String var10000 = this.name();
                     String var5 = var4.name();
                     if (var10000 == null) {
                        if (var5 != null) {
                           break label37;
                        }
                     } else if (!var10000.equals(var5)) {
                        break label37;
                     }

                     if (this.age() == var4.age() && var4.canEqual(this)) {
                        var6 = true;
                        break label38;
                     }
                  }

                  var6 = false;
               }

               if (var6) {
                  break label55;
               }
            }

            var6 = false;
            return var6;
         }
      }

      var6 = true;
      return var6;
   }

   public Person(final String name, final int age) {
      this.name = name;
      this.age = age;
      super();
      Product.$init$(this);
   }
}

case class 和 class 的一些区别:

  1. case class 在初始化的时候,不用 new,而普通类初始化时必须要 new。
  1. case class 重写了 toString 方法。 默认实现了 equals 和 hashCode
  1. case class 实现了序列化接口 with Serializable
  1. case class 支持模式匹配(最重要的特征),所有 case class 必须要有参数列表
  1. 有参数用 case class,无参用 case object

6.5继承和多态

基本语法

class 子类名 extends 父类名 { 类体 }

(1)子类继承父类的属性和方法

(2)scala 是单继承

案例实操:

(1)子类继承父类的属性方法

(2)继承的调用顺序:父类构造器->子类构造器

Scala
class Person(nameParam: String) {
 var name = nameParam
 var age: Int = _
 def this(nameParam: String, ageParam: Int) {
 this(nameParam)
 this.age = ageParam
 println("
父类辅助构造器")
 }
 println("父类主构造器")
}
class Emp(nameParam: String, ageParam: Int) extends
Person(nameParam, ageParam) {
 var empNo: Int = _
 def this(nameParam: String, ageParam: Int, empNoParam: Int) {
 this(nameParam, ageParam)
 this.empNo = empNoParam
 println("子类的辅助构造器")
 }
  println("子类主构造器")
}
object Test {
 def main(args: Array[String]): Unit = {
 new Emp("z3", 11,1001)
 }
}

练一练:

定义一个order

属性:user_id , order_idgoods_idcategory_idpricegoods_num

需求1:对10个订单的金额大小的升序排列

需求2:对10个订单的金额大小的降序排列

需求3:统计每一种品类下的订单总额

需求4:统计每一个用户的订单总额

需求5:找出每个用户金额最大的哪个订单

需求6:找出每一种品类中金额最大的订单

需求7:找出订单金额最大的两个订单

需求8:找出订单金额最小的两个订单

7   集合

scala中的集合分为两种 ,可变集合和不可变集合, 不可变集合可以安全的并发的访问!

集合的类主要在一下两个包中

  • 可变集合包    scala.collection.mutable
  • 不可变集合包 scala.collection.immutable   默认的

Scala 不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于 java 中的 String 对象

可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似于 java StringBuilder 对象

建议:在操作集合的时候,不可变用符号,可变用方法

scala默认使用的是不可变的集合 , 因此使用可变的集合需要导入可变集合的包

scala的集合主要分成三大类

  1. Seq 序列
  1. Set 不重复集
  1. Map 键值映射集

注意: 所有的集合都继承自Iterator迭代器这个特质

不可变集合继承图

7.1迭代器(重点)

7.1.1java中的iterator

在java中用迭代器读取文件中的数据,每次返回一行数据

Java
package com.doit;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;

class MyHero implements Iterator<String> {
    BufferedReader buffer = null;
    String line = null;

    public MyHero() {
        try {
            buffer = new BufferedReader(new FileReader("data/hero.txt"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean hasNext() {
        try {
            line = buffer.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return line != null;
    }

    @Override
    public String next() {
        return line;
    }
}

public class MyIterator{
    public static void main(String[] args) {
        MyHero myHero = new MyHero();
        while (myHero.hasNext()){
            System.out.println(myHero.next());
        }
    }
}

在java中用迭代器读取mysql表中的数据,每次返回一行数据

Java
package com.doit;

import java.sql.*;
import java.util.Iterator;

public class ReadTable implements Iterator<Login> {
    ResultSet resultSet = null;
    public ReadTable(){
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/football", "root", "123456");
            PreparedStatement pps = conn.prepareStatement("select * from login ");
            resultSet = pps.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean hasNext() {
        boolean flag = false;
        try {
            flag = resultSet.next();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return flag;
    }

    @Override
    public Login next() {
        Login login = new Login();
        try {
            login.setId(resultSet.getInt(1));
            login.setUser_id(resultSet.getInt(2));
            login.setClient_id(resultSet.getInt(3));
            login.setDate(resultSet.getString(4));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return login;
    }


}


class Login {
    private int id;
    private int user_id;
    private int client_id;
    private String date;

    public Login() {
    }

    public Login(int id, int user_id, int client_id, String date) {
        this.id = id;
        this.user_id = user_id;
        this.client_id = client_id;
        this.date = date;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getUser_id() {
        return user_id;
    }

    public void setUser_id(int user_id) {
        this.user_id = user_id;
    }

    public int getClient_id() {
        return client_id;
    }

    public void setClient_id(int client_id) {
        this.client_id = client_id;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    @Override
    public String toString() {
        return "login{" +
                "id=" + id +
                ", user_id=" + user_id +
                ", client_id=" + client_id +
                ", date='" + date + '\'' +
                '}';
    }
}

7.1.2java中的Iterable

代表可迭代的,返回的是一个迭代器

Java
package com.doit;

import java.util.Iterator;

public class ReadTableIterable implements Iterable<Login>{
    @Override
    public Iterator iterator() {
        return new ReadTable();
    }
}


//
测试
package com.doit;

import java.util.Iterator;

public class Test3 {
    public static void main(String[] args) {
        ReadTableIterable logins = new ReadTableIterable();
        //可迭代的都会有一个迭代器对象,获取出来后用hasnext next获取数据
        Iterator iterator = logins.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //可迭代的java底层都封装了增强for循环,也可以直接使用
        for (Login login : logins) {
            System.out.println(login);
        }
    }
}

7.1.3scala中的 iterator

Scala
package com.doit.day01.day02

import scala.io.{BufferedSource, Source}

object MyIter {
  def main(args: Array[String]): Unit = {
    val iter: MyIter = new MyIter
    while (iter.hasNext){
      println(iter.next())
    }
  }

}

class MyIter extends Iterator[String]{
  //
读取数据
  private val source: BufferedSource = Source.fromFile("data/hero.txt")
  private val lines: Iterator[String] = source.getLines()
  //
用scala中返回迭代器中的hasNext方法直接判断
  override def hasNext: Boolean = lines.hasNext
  //
用scala中返回迭代器中的next方法获取数据
  override def next(): String = lines.next()
}

7.1.4scala中的Iterable

Scala
package com.doit.day01.day02

import scala.io.{BufferedSource, Source}

object MyIter {
  def main(args: Array[String]): Unit = {
    val iter: MyIter1 = new MyIter1
    val iterator: Iterator[String] = iter.iterator
    while (iterator.hasNext){
      println(iterator.next())
    }

    for (elem <- iter) {
      println(elem)
    }
  }
}

class MyIter1 extends Iterable[String]{
  override def iterator: Iterator[String] = new MyIter
}

7.2比较器

7.2.1java中的比较器 Comparator

Java
package com.doit;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;

public class Test3 {
    public static void main(String[] args) {
        Order or1 = new Order("001", 100, "2022-7-12");
        Order or2 = new Order("002", 99, "2022-7-11");
        Order or3 = new Order("003", 88, "2022-7-15");
        Order or4 = new Order("004", 103, "2022-7-13");
        Order or5 = new Order("005", 55, "2022-7-10");

        ArrayList<Order> list = new ArrayList<>();
        list.add(or1);
        list.add(or2);
        list.add(or3);
        list.add(or4);
        list.add(or5);
        Collections.sort(list,new ComparatorDeme());
        System.out.println(list);
        Collections.sort(list,new ComparatorDeme1());
        System.out.println(list);
    }
}

class ComparatorDeme implements Comparator<Order>{

    @Override
    public int compare(Order o1, Order o2) {
        return -o1.getOrderAmount() + o2.getOrderAmount();
    }
}

class ComparatorDeme1 implements Comparator<Order>{

    @Override
    public int compare(Order o1, Order o2) {
        return o1.getOrderTime().compareTo(o2.getOrderTime());
    }
}

7.2.2java中的比较器 Comparable

Java
package com.doit;
//
类实现Comparable 接口,重写里面的compareTo 方法
public class Order2 implements Comparable<Order2>{
    private String orderId;
    private int orderAmount;
    private String orderTime;

    public Order2() {
    }

    public Order2(String orderId, int orderAmount, String orderTime) {
        this.orderId = orderId;
        this.orderAmount = orderAmount;
        this.orderTime = orderTime;
    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public int getOrderAmount() {
        return orderAmount;
    }

    public void setOrderAmount(int orderAmount) {
        this.orderAmount = orderAmount;
    }

    public String getOrderTime() {
        return orderTime;
    }

    public void setOrderTime(String orderTime) {
        this.orderTime = orderTime;
    }

    @Override
    public String toString() {
        return "Order{" +
                "orderId='" + orderId + '\'' +
                ", orderAmount=" + orderAmount +
                ", orderTime='" + orderTime + '\'' +
                '}';
    }

    @Override
    public int compareTo(Order2 o) {
        return this.orderAmount - o.orderAmount;
    }
}

package com.doit;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;

public class Test3 {
    public static void main(String[] args) {
//        Order or1 = new Order("001", 100, "2022-7-12");
//        Order or2 = new Order("002", 99, "2022-7-11");
//        Order or3 = new Order("003", 88, "2022-7-15");
//        Order or4 = new Order("004", 103, "2022-7-13");
//        Order or5 = new Order("005", 55, "2022-7-10");
//
//        ArrayList<Order> list = new ArrayList<>();
//        list.add(or1);
//        list.add(or2);
//        list.add(or3);
//        list.add(or4);
//        list.add(or5);
//        Collections.sort(list,new ComparatorDeme());
//        System.out.println(list);
//        Collections.sort(list,new ComparatorDeme1());
//        System.out.println(list);
//        System.out.println("===========华丽的分割线==========");

        Order2 o1 = new Order2("001", 100, "2022-7-12");
        Order2 o2 = new Order2("002", 99, "2022-7-11");
        Order2 o3 = new Order2("003", 88, "2022-7-15");
        Order2 o4 = new Order2("004", 103, "2022-7-13");
        Order2 o5 = new Order2("005", 55, "2022-7-10");

        ArrayList<Order2> list1 = new ArrayList<>();
        list1.add(o1);
        list1.add(o2);
        list1.add(o3);
        list1.add(o4);
        list1.add(o5);
        //这边就不需要再传入比较器了
        Collections.sort(list1);
        System.out.println(list1);
    }
}

7.2.3scala中的比较器 Ordering 类比于java中的Comparator

Scala
package com.doit.day01.day02

import scala.util.Sorting
   
object Demo_Ordering {
  def main(args: Array[String]): Unit = {
    val e1: Employee = new Employee(1, "
涛哥", 10000)
    val e2: Employee = new Employee(2, "
星哥", 8000)
    val e3: Employee = new Employee(3, "
行哥", 5000)
    val e4: Employee = new Employee(4, "
源哥", 3500)
    val e5: Employee = new Employee(5, "
娜姐", 2000)
    val list: Array[Employee] = List(e1, e2, e3, e4, e5).toArray
    Sorting.quickSort(list)(MyOrdering())
    println(list.mkString(","))

  }
}
case class MyOrdering() extends Ordering[Employee] {
  override def compare(x: Employee, y: Employee): Int = (x.salary - y.salary).toInt
}

class Employee(val id:Int,val name:String,val salary:Double){

  override def toString = s"Employee(id=$id, name=$name, salary=$salary)"
}

7.2.4scala中的比较器 Ordered 类比于java中的Comparable

Scala
package com.doit.day01.day02

import scala.util.Sorting

object Demo_Ordering {
  def main(args: Array[String]): Unit = {
    val e1: Employee = new Employee(1, "
涛哥", 10000)
    val e2: Employee = new Employee(2, "
星哥", 8000)
    val e3: Employee = new Employee(3, "
行哥", 5000)
    val e4: Employee = new Employee(4, "
源哥", 3500)
    val e5: Employee = new Employee(5, "
娜姐", 2000)
    val list: Array[Employee] = List(e1, e2, e3, e4, e5).toArray
    Sorting.quickSort(list)
    println(list.mkString(","))
  }
}

class Employee(val id:Int,val name:String,val salary:Double) extends Ordered[Employee]{

  override def toString = s"Employee(id=$id, name=$name, salary=$salary)"

  override def compare(that: Employee): Int = (this.salary - that.salary).toInt
}

7.3序列

许多数据结构是序列型的,也就是说,元素可以按特定的顺序访问,如:元素的插入顺

序或其他特定顺序。collection.Seq是一个trait,是所有可变或不可变序列类型的抽象,其子trait collection.mutable.Seqcollection.immutable.Seq分别对应可变和不可变序列。

从上面的图中可以看出Array,String ,List都属于序列

7.3.1不可变数组

数组的基本操作 , scala中的数组和java中的不太一样 ,这里的数组类似于一个数组对象 .有自己的方法!!

7.1.1.1数组的定义方式

方式一:创建一个长度固定的数组,后面再赋值

Scala
object TestArray{
 def main(args: Array[String]): Unit = {
 //
(1)数组定义
 val arr01 = new Array[Int](4)
 println(arr01.length) // 4
 //(2)数组赋值
 //(2.1)修改某个元素的值
 arr01(3) = 10
 //(2.2)采用方法的形式给数组赋值
 arr01.update(0,1)
 //(3)遍历数组
 //(3.1)查看数组
 println(arr01.mkString(","))
 //(3.2)普通遍历
 for (i <- arr01) {
 println(i)
 }
 //(3.3)简化遍历
 def printx(elem:Int): Unit = {
 println(elem)
 }
 arr01.foreach(printx)
 // arr01.foreach((x)=>{println(x)})
 // arr01.foreach(println(_))
 arr01.foreach(println)
 //(4)增加元素(由于创建的是不可变数组,增加元素,其实是产生新的数组)
 println(arr01)
 val ints: Array[Int] = arr01 :+ 5
 println(ints)
 }
}

方式二:使用 apply 方法创建数组对象,并且在定义数组的时候直接赋初始值

代码示例:

Scala
object TestArray{
 def main(args: Array[String]): Unit = {
 var arr02 = Array(1, 3, "bobo")
 println(arr02.length)
 for (i <- arr02) {
  println(i)
 }
 }
}

数组中的方法:

Scala
val arr = Array(1,3,5,7,9,2,6,4)
 
// 数组中的最大和最小值
 val min: Int = arr.min
 
val max: Int = arr.max
 
// 首个元素
 val head: Int = arr.head
 
//最后一个元素
 val last: Int = arr.last
 
// 去除首个元素的子数组
 val arr11: Array[Int] = arr.tail
 
// 将数组转换成List集合
 val list: List[Int] = arr.toList
 
// 获取和后面数组中不同的元素
val diff: Array[Int] = arr.diff(Array(1,111,222))
 
//求数组元素的和
 val sum: Int = arr.sum
 
// 数组的长度
 arr.length
 
//修改指定位置的元素
 arr.update(1,100)
// 取出数组中的前n个元素
 val arr3: Array[Int] = arr.take(3)
 
//  后面添加一个元素  生成 新的数组
 val arr2: Array[Int] = arr.:+(11)
 
//  后面添加一个数组
 val  res = arr ++ arr3
// 统计符合条件的个数
 val i: Int = arr.count(_>2)
 
// 数组反转
 arr.reverse
// 将不可变数组转换成可变数组
val buffer: mutable.Buffer[Int] = arr.toBuffer

练一练

需求一:有一个10个长度的数组,第一个位置放得是3,后面每个位置都是前一个位置的2倍加1,

现需要打印这个数组,然后将这个数组中的奇数位置和偶数位置互换

Scala
package com.doit.day01.day02

/**
 *
需求一:有一个10个位置的数组,第一个位置放得是3,后面每个位置都是前一个位置的2倍加1,
 * 现需要打印这个数组,然后将这个数组中的奇数位置和偶数位置互换
 */
object Test1 {
  def main(args: Array[String]): Unit = {

    val arr = new Array[Int](10)
    arr(0) = 3
    //
构建数据
    for (elem <- 1 to 9) arr(elem) = arr(elem - 1) * 2 + 1
    //
打印这个数组
    println(arr.mkString(","))
    //
将这个数组中的奇数位置和偶数位置互换
    for (elem <- 0 until arr.length) {
      if((elem+1) %2 == 1){
        var tmp = arr(elem)
        arr(elem) = arr(elem + 1)
        arr(elem + 1) = tmp
      }
    }
    println(arr.mkString(","))
  }
}

7.3.2可变数组--> ArrayBuffer

导入可变数组 : import scala.collection.mutable.ArrayBuffer ,可以修改元素的数组为可变数组

定义:

定义变长数组

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

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

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

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

实例操作:

Scala
import scala.collection.mutable.ArrayBuffer
object TestArrayBuffer {
 def main(args: Array[String]): Unit = {
 //
(1)创建并初始赋值可变数组
 val arr01 = ArrayBuffer[Any](1, 2, 3)
 //(2)遍历数组
 for (i <- arr01) {
 println(i)
 }
 println(arr01.length) // 3
 println("arr01.hash=" + arr01.hashCode())
 //(3)增加元素
 //(3.1)追加数据
 arr01.+=(4)
 //(3.2)向数组最后追加数据
 arr01.append(5,6)
 //(3.3)向指定的位置插入数据
 arr01.insert(0,7,8)
 println("arr01.hash=" + arr01.hashCode())
 //(4)修改元素
 arr01(1) = 9 //修改第 2 个元素的值
 println("--------------------------")
 for (i <- arr01) {
 println(i)
 }
 println(arr01.length) // 5
 }
}

7.3.3不可变 List

说明:

1List 默认为不可变集合

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

3)遍历 List

4List 增加数据

5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化

6)取指定数据

7)空集合 Nil

示例:

Scala
object TestList {
 def main(args: Array[String]): Unit = {
 //
(1)List 默认为不可变集合
 //(2)创建一个 List(数据有顺序,可重复)
 val list: List[Int] = List(1,2,3,4,3)
 
 //(7)空集合 Nil
 val list5 = 1::2::3::4::Nil
 //(4)List 增加数据
 //(4.1)::的运算规则从右向左
 //val list1 = 5::list
 val list1 = 7::6::5::list
 //(4.2)添加到第一个元素位置
 val list2 = list.+:(5)
 //(5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化
 val list3 = List(8,9)
 //val list4 = list3::list1
 val list4 = list3:::list1
 //(6)取指定数据
 println(list(0))
 //(3)遍历 List
 //list.foreach(println)
 //list1.foreach(println)
 //list3.foreach(println)
 //list4.foreach(println)
 list5.foreach(println)
 }
}


// 不可变的List集合 数据不允许被修改
  private val ls1 = List("SCALA", "HDP", "SPARK" , 12 , 34)
 
// 向Nil空队列中添加元素组成新的队列
  val ls2 = "HIVE" :: "MYSQL" :: "HBASE" :: Nil
  // Nil 和 List.empty[Nothing]是等价的
  private val ll = List.empty[Nothing]
 
ls1(0) // 获取指定位置元素
  // 添加一个元素生成新的List
  val ls3 = ls1 :+ "PYTHON"
  //合并两个集合 生成新的集合
  val ls4 = ls1 ++ ls2
  ls1.foreach(println)
 
// 获取前两个元素 组成新的List
  ls1.take(2)
  println(
ls1.take(2))
  println(
ls1.takeRight(2))  // 从右边取数据
// 遍历每个元素   参数是一个偏函数
 ls1.collect({ case x: Int => x })
 
// 查找匹配的元素 仅仅返回一个元素
 ls1.find(x=>x.toString.startsWith("S"))
// 判断是否为null集合
 ls1.isEmpty
// 转换成可变List集合
ls1.toBuffer

7.3.4可变List-->ListBuffer

说明:

1)创建一个可变集合 ListBuffer

2)向集合中添加数据

3)打印集合数据

代码实现:

Scala
import scala.collection.mutable.ListBuffer
object TestList {
 def main(args: Array[String]): Unit = {
 //
(1)创建一个可变集合
 val buffer = ListBuffer(1,2,3,4)
 //(2)向集合中添加数据
 buffer.+=(5)
buffer.append(6)
buffer.insert(1,2)
 //(3)打印集合数据
 buffer.foreach(println)
//(4)修改数据
buffer(1) = 6
buffer.update(1,7)
//(5)删除数据
buffer.-(5)
buffer.-=(5)
buffer.remove(5)
 }
}

7.4set

Set和list的最大区别在于Set中不可以存储重复数据 ,通常使用Set来实现元素的去重!!

Set集合也分为可变Set和不可变的Set,使用包名来区分可变和不可变,需要引用scala.collection.mutable.Set 包

7.4.1不可变set

说明:

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

2)数据不可重复

3)遍历集合

代码示例:

Scala
object TestSet {
 def main(args: Array[String]): Unit = {
 //
(1)Set 默认是不可变集合,数据无序
 val set = Set(1,2,3,4,5,6)
 //(2)数据不可重复
 val set1 = Set(1,2,3,4,5,6,3)
 //(3)遍历集合
 for(x<-set1){
 println(x)
 }
 }
}

7.4.2可变mutable.Set

说明:

1)创建可变集合 mutable.Set

2)打印集合

3)集合添加元素

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

5)删除数据

代码示例:

Scala
object TestSet {
 def main(args: Array[String]): Unit = {
 //
(1)创建可变集合
 val set = mutable.Set(1,2,3,4,5,6)
 //(3)集合添加元素
 set += 8
 //(4)向集合中添加元素,返回一个新的 Set
 val ints = set.+(9)
 println(ints)
 println("set2=" + set)
 //(5)删除数据
 set-=(5)
 //(2)打印集合
 set.foreach(println)
 println(set.mkString(","))
 }
}

7.5Map映射

Scala 中的 Map 和 Java 类似,也是一个散列表,它存储的内容也是键值对(key-value)映射,同样分为可变Map和不可变Map , 使用包名来区分是可变Map还是不可变Map

7.5.1不可变Map

说明:

1)创建不可变集合 Map

2)循环打印

3)访问数据

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

代码示例:

Scala
object TestMap {
 def main(args: Array[String]): Unit = {
 // Map
 //
(1)创建不可变集合 Map
 val map = Map( "a"->1, "b"->2, "c"->3 )
 //(3)访问数据
 for (elem <- map.keys) {
 // 使用 get 访问 map 集合的数据,会返回特殊类型 Option(选项):
有值(Some),无值(None)
 println(elem + "=" + map.get(elem).get)
 }
 //(4)如果 key 不存在,返回 0
 println(map.get("d").getOrElse(0))
 println(map.getOrElse("d", 0))
 //(2)循环打印
 map.foreach((kv)=>{println(kv)})
 }
}

7.5.2可变 Map

说明

1)创建可变集合

2)打印集合

3)向集合增加数据

4)删除数据

5)修改数据

代码示例:

Scala
object TestMap {
 def main(args: Array[String]): Unit = {
 //
(1)创建可变集合
 val map = mutable.Map( "a"->1, "b"->2, "c"->3 )
 //(3)向集合增加数据
 map.+=("d"->4)
 // 将数值 4 添加到集合,并把集合中原值 1 返回
 val maybeInt: Option[Int] = map.put("a", 4)
 println(maybeInt.getOrElse(0))
 //(4)删除数据
 map.-=("b", "c")
 //(5)修改数据
 map.update("d",5)
map("d") = 5
 //(2)打印集合
 map.foreach((kv)=>{println(kv)})
 }
}

7.6元组

元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组。

注意:元组中最大只能有 22 个元素

示例内容:

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

(2)访问元组

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

代码实现:

Scala
object TestTuple {
 def main(args: Array[String]): Unit = {
 //
(1)声明元组的方式:(元素 1,元素 2,元素 3)
 val tuple: (Int, String, Boolean) = (40,"bobo",true)
 //(2)访问元组
 //(2.1)通过元素的顺序进行访问,调用方式:_顺序号
 println(tuple._1)
 println(tuple._2)
 println(tuple._3)
 //(2.2)通过索引访问数据
 println(tuple.productElement(0))
 //(2.3)通过迭代器访问数据
 for (elem <- tuple.productIterator) {
 println(elem)
 }
 //(3)Map 中的键值对其实就是元组,只不过元组的元素个数为 2,称之为对偶
 val map = Map("a"->1, "b"->2, "c"->3)
 val map1 = Map(("a",1), ("b",2), ("c",3))
 map.foreach(tuple=>{println(tuple._1 + "=" + tuple._2)})
 }
}

7.7Option

Option(选项)类型用来表示一个值是可选的(有值或无值)

Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None 。

Option 有两个子类别,一个是 Some,一个是 None,当他回传 Some 的时候,代表这个函式成功地给了你一个 String,而你可以通过 get() 这个函式拿到那个 String,如果他返回的是 None,则代表没有字符串可以给你。

代码示例:

Scala
val myMap: Map[String, String] = Map("key1" -> "value")
val value1: Option[String] = myMap.get("key1")
val value2: Option[String] = myMap.get("key2")
println(value1)
// Some("value1")
println(value2) // None

复习:

Scala
package com.doit.day01.day02

import scala.collection.mutable
import scala.collection.parallel.immutable


object ListTest {
  def main(args: Array[String]): Unit = {
    //1.
定义一个长度为10的int类型的数组,里面装10个整数
    //    val arr: Array[Int] = new Array[Int](10)
    //    arr(0) = 1
    //    arr.update(0,1)
    //
第二种遍历方式
    val arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)

    //2.
打印数组的长度
    //    println(arr.length)

    //3.
遍历数组
    //方式1:for循环
    //    for (elem <- arr) {println(elem)}
    //
方式二,foreach
    //    arr.foreach(println)
    //4.
查看数组中的元素,显示成1--2--3...这样的形式
    //    println(arr.mkString("--"))
    //5.
找到数组中的最大值
    //    println(arr.max)
    //6.
找到数组中的最小值
    //    println(arr.min)
    //
数组中的第一个元素
    //    println(arr.head)
    //
数组中的最后一个元素
    //    println(arr.last)
    //
数组中除了第一个元素的后面所有的元素
    //    println(arr.tail.mkString(","))
    //
数组中的前三个元素和后三个元素
    //    println(arr.take(3).mkString(","))//前三个
    //    println(arr.takeRight(3).mkString(","))
    //
计算数组中大于4的个数
    //    println(arr.count(_ > 4))
    //
将不可变数组转换成可变数组
    val buffer: mutable.Buffer[Int] = arr.toBuffer
    //
在可变数组中添加一个元素10
    //    buffer.append(10)
    //    buffer.+=(10)
    //    buffer += 10
    //
在指定索引为1的位置插入11,12两个元素
    //    buffer.insert(1,11,12)
    //
删除一个指定的元素元素
    //    buffer.-=(1)
    //    buffer -= 1
    //
删除指定索引位置的元素
    //    buffer.remove(1)
    //
数组的反转
    //    buffer.reverse

    val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
    //    val list1: List[Int] = 1 :: 2 :: 3 :: 4 :: 5 :: Nil
    //
遍历list
    //    for (elem <- list) {}
    //    list.foreach(println)
    list.head
    list.tail
    list.last
    list.max
    list.min
    list.take(2)
    //    list ::: arr.toList 
正常都用不到
    //val ints: List[Int] = list.::(1)  加在最前面


    //    Set(1,2,2,6,3,4)

    //    val ints: mutable.Set[Int] = mutable.Set(1, 2, 3, 4, 5, 6, 7)
    //    for (elem <- ints) {}
    //
添加一个元素
    //    ints.+=(1)
    //
删除索引位置的元素
    //    ints.remove(1)
    //
删除指定的元素
    //    ints.-=(1)

    //    val map: Map[String, Int] = Map("hadoop" -> 1, "hive" -> 2, "hbase" -> 3)
    //    val tail: Map[String, Int] = map.tail
    //    val head: (String, Int) = map.head
    //    val i: Int = map.getOrElse("hadoop", 0)
    //        map.get("he").get  //
用这个的时候得注意报错,正常情况下用getOrElse

    val map: mutable.Map[String, Int] = mutable.Map("hadoop" -> 1, "hive" -> 2, "hbase" -> 3)
//    map.update("hadoop", 111)
//    map.+=("he"->11)
//    map.put("haha",11 )
//    map.remove("hadoop")
//    for (elem <- map) {}

    //    for (elem <- map) {}
//    val tuple = (1,"sy",false,1.0)
//    val tuple2: (Int, String) = Tuple2(1, "hh")
  }
}

7.8集合中的常用方法

7.8.1forEach

迭代遍历集合中的每个元素,对每个元素进行处理 ,但是没有返回值 ,常用于打印结果数据 !

Scala
val ls = List(1,3,5,7,9)
ls.foreach(println)
// 打印每个元素
ls.foreach(println(_))// 打印每个元素
ls.foreach(x=>println(x*10)) // 每个元素乘以10 打印结果
ls.foreach(x=>print(x+" "))// 打印每个元素 空格隔开

7.8.2map

适用于任意集合

注意Map集合的用法:map函数遍历每个元素处理返回原集合类型的新集合 , 也可以不返回数据列表,数组,Map中都有map函数  元组中没有map函数

Scala
val arr = Array[String]("JAVA", "C++", "SCALA")
val ls = List(1, 3, 5, 7, 9)
val set = Set(1, 3, 5, 7)
val mp = Map[String, Int]("ZSS" -> 100, "LSS" -> 99)
// map函数遍历每个元素处理返回原集合类型的新集合
val new_arr: Array[String] = arr.map(x => x)
val new_list: List[Int] = ls.map(x => x)
val new_set: Set[Int] = set.map(x => x)
// Map集合使用map函数
val new_Map1: Map[String, Int] = mp.map({ case v: (String, Int) => (v._1, v._2 * 10) })
val new_Map2: Map[String, Int] = mp.map(e => (e._1, e._2 + 100))
 

// map函数也可以不返回数据
ls.map(println(_))

7.8.3filterfilterNot

适用于: 数组  List  Map

filter返回符合自己条件的新的集合,filterNot返回不符合自己条件的新的集合

Scala
val ls: List[Int] = List.range(1,10)
ls.filter(x=>x%
2==0)
val new_list: List[Int] = ls.filter(_ % 2 == 0)//  _ 代表每个元素
new_list .foreach(x=>print(x+"  "))  // 2  4  6  8
ls.filterNot(_%2!=1).foreach(x=>print(x+"  ")) 1  3  5  7  9 

每个元素进行过滤

Scala
val set = Set("spark" , "scala" , "c++" , "java")
val new_set: Set[String] = set.filter(_.startsWith("s"))
set.filter(_.length>
3)

多条件filter进行条件过滤

Scala
val ls = "spark":: "scala" :: "c++"::"java"::1::2::12.34::Nil
// 过滤出String类型的和Double类型的数据
ls.filter{
 
case i:String => true
  case i:Int=>false
  case i:Double=>true
}

连续使用多次filter进行条件过滤

Scala
// 连续使用多次filter进行条件过滤
val map = Map[String,Int](("zss" ,91),("zww",89),("zzx",92) , ("ww",23))
map.filter(_._1.startsWith(
"z")).filter(_._2>90)

7.8.4collect

常用于:  Array  List  Map

collect函数也可以遍历集合中的每个元素处理返回新的集合

def map[B](f: (A) ⇒ B): List[B]
def collect[B](pf: PartialFunction[A, B]): List[B]

主要支持偏函数

Scala
val ls = List(1,2,3,4,"hello")
// 主要支持偏函数
 val new_list: List[Int] = ls.collect({case i:Int=>i*10})
 new_list.foreach(x=>print(x+
" "))//10 20 30 40
// collect
实现filter和map特性
list.collect({ case i: Int => i * 10
case i: String => i.toUpperCase
}).foreach(println)
val new_list2: List[Int] = ls.map({case x:Int=>x*10})
 new_list2.foreach(x=>print(x+
" "))// 错误 hello (of class java.lang.String)

因为collect支持偏函数 , 所以我们可以使用collect实现filter和map的特性!!!

Scala
val res: List[Int] = List(1, 2, 3, 4, 5, 6,"hello").collect({case i:Int if i%2==0=>i*10})
res.foreach(println)
 // 40  60 是不是牛逼闪电??

7.8.5minmax

适用于:数组  List  Map

  • 数组

Scala
val arr = Array(1,2,345,67,5)
arr.min
arr.max
arr.sum

  • List

Scala
val ls = List(1,2,345,67,5)
ls.min
ls.max
ls.sum

  • Set

Scala
val set = Set(1,2,345,67,5)
set.min
set.max
set.sum

  • map 默认按照key排序获取最大和最小数据

Scala
val map = Map[String,Int]("a"->10, "b"->99 , "c"->88)
// map默认按照key排序获取最大和最小数据
map.min  //(a,10)
map.max //(c,88)

7.8.6minBymaxBy

适用于: 数组  List  Map

集合中的min和max可以获取任意集合中的最小和最大值 ,但是如果集合中存储的是用户自定义的类 , 或者是按照Map集合中的key, value规则排序的话就需要用户指定排序规则

  • map按照value取最大最小

Scala
val map = Map[String,Int]("a"->10, "b"->99 , "c"->88)
// map默认按照key排序获取最大和最小数据
// 指定map排序  按照value排序
map.maxBy(x=>x._2) //(b,99)
map.minBy(x=>x._2) //(a,10)

  • 集合中存储的是用户自定义的类型

Scala
class User(val name:String ,val age:Int) {}

方式一 隐式转换

Scala
implicit  def ordersUser(user:User)={
 
new Ordered[User] {
   
override def compare(that: User) = {
       user.age.compareTo(that.age)
    }
  }
}

val ls = List(new User("zs",22),new User("ww",18) ,new User("tq",34))
println(ls.max.name)
println(ls.min.name)

Scala
println(ls.maxBy(x => x.age).name)

方式二:

7.8.7sum

适用于 数组  List  Set

求集合中的所有元素的和 ,下面三种集合类型常用

Scala
val arr = Array(1,2,345,67,5)
arr.sum


val ls = List(1,2,345,67,5)
ls.sum


val set = Set(1,2,345,67,5)
set.sum

7.8.8count

适用于 数组  List  Map

def count(p: ((A, B)) => Boolean): Int

计算满足指定条件的集合元素数量

Scala
val arr = Array(1,2,345,67,5)
arr.count(_>
5// array list  set 统用

val ls = List("hello" , "hi" , "heihei" , "tom")
ls.count(_.startsWith(
"h"))
ls.count(_.equals(
"hello"))
ls.count(_ ==
"hello")
// 忽略大小写
ls.count(_.equalsIgnoreCase("HELLO"))
// 统计符合条件的map元素的数量
val map = Map[String,Int]("a"->10,"ab"->10, "b"->99 , "c"->88)
map.count(x=>x._1.startsWith(
"a"))
map.count(_._2>
10)

7.8.9find

适用于 数组  List  Map

查找符合要求的元素 , 匹配到就反回数据 ,最多只返回一个

Option中的数据要么是Some(T)  要么是None标识没有找到

Scala
val arr = Array(1,2,345,67,5)
val e: Option[Int] = arr.find(x=>x>1)

val ls = List("hello" , "hi" , "heihei" , "tom")
val res: Option[String] = ls.find(_.contains("a"))
if(res.isDefined){
  println(res) 
//Some(hello)
  println(res.get)  //hello
}
val map = Map[String,Int]("a"->10,"ab"->10, "b"->99 , "c"->88)
val res_map: Option[(String, Int)] = map.find(x=>x._2>20)
if(res_map.isEmpty){
 
"没有匹配到内容"
}else{
 
// 打印数据
    println(res_map.get)
}

7.8.10flatten

适用于 数组  List

压平  将一个集合展开  组成一个新的集合

Scala
val arr = Array(1,2,345,67,5.23)
//val res1: Array[Nothing] = arr.flatten  I数值了类型的无法压平
val ls = List("hello" , "hi" , "heihei" , "tom")
val res2: Seq[Char] = ls.flatten  // 压成单个字符  因为字符串属于序列集合的一种
val map = Map[String,Int]("a"->10,"ab"->10, "b"->99 , "c"->88)
// map无法直接压平
//val flatten: immutable.Iterable[Nothing] = map.flatten
// 压平存储Map集合的list   获取Map中每个元素
val ls1 = List[Map[String,Int]](Map[String,Int]("a"->10,"ab"->10) , Map[String,Int]("jim"->100,"cat"->99))
ls1.flatten  
// List((a,10), (ab,10), (jim,100), (cat,99))

val res: List[Int] = List(Array(1,2,3),Array(4,5,6)).flatten
// 错误  注意压平的数据的类型
 val res4 = List(Array(1,2,3),Array("hel",5,6)).flatten

7.8.11flatMap

适用于 数组  List

map+flatten方法的组合 ,先遍历集合中的每个元素 , 再按照指定的规则压平, 返回压平后的新的集合

Scala
val ls = List("today is my first day of my life" , "so I feel so happy")
// map处理每个元素 就是处理每句话
 ls.map(x=>println(x))
// 获取集合中的每个元素   获取两句话   然后再扁平成字符
ls.flatMap(x=>x)
// 指定扁平化的规则 按照空格压平  压平的规则
ls.flatMap(x=>x.split(" ")).foreach(println) // 获取到每个单词


// 读取外部文件
val bs: BufferedSource = Source.fromFile("d://word.txt")
// 读取所有的数据行
val lines: Iterator[String] = bs.getLines()
// m遍历每行数据按照 \\s+ 切割返回一个新的迭代器
val words: Iterator[String] = lines.flatMap(_.split("\\s+"))
// 遍历迭代器 获取每个单词
words.foreach(println)
// 读取外部文件
val bs2: BufferedSource = Source.fromFile("d://word.txt")
 
// 获取所有的行数据
val lines2: Iterator[String] = bs2.getLines()
// 处理每行数据 切割单词后  每行返回一个数组   将所有的数组封装在迭代器中
val arrs: Iterator[Array[String]] = lines2.map(_.split("\\s+"))

7.8.12 mapValues

适用于 Map

mapValues方法只对Map集合的value做处理!

7.8.13sorted

适用于 数组  List  Map

sorted 使用域简单的数字, 字符串等排序规则简答的集合进行排序 , 如果需要定制化排序建议使用sortBy 和 sortWith函数

List对数值

Scala
val  list = List (1, 34 , 32 , 12 , 20 ,44 ,27)
// 返回排好序的list集合   默认从小到达排序
val sorted: List[Int] = list.sorted

对Array字符串

Scala
val arr = Array("jim" , "cat" , "jong" , "huba")
// 字符串默认按照先后排序
val sorted_arr: Array[String] = arr.sorted

对map

Scala
val map = Map[String , Int]("aeiqi"->4 , "qiaozhi"->2 , "baji"->34)
// map集合也没有sorted 函数 只有转换成List或者Array集合 默认按照key字典先后排序
val sorted_map: Seq[(String, Int)] = map.toList.sorted
sorted_map.foreach(println)

7.8.14sortBysortWith

适用于 数组  List  Map

Scala
var arr = Array(1, 11, 23, 45, 8, 56)
val arr1 = arr.sortBy(x => x) //ArraySeq(1, 8, 11, 23, 45, 56)
//按照数据倒序排列
val arr2 = arr.sortBy(x => -x) //(56, 45, 23, 11, 8, 1)
// 按照字典顺序排序
val arr3 = arr.sortBy(x => x.toString) //ArraySeq(1, 11, 23, 45, 56, 8)
// x 前面的元素  y 后面的元素
arr.sortWith((x, y) => x > y)
arr.sortWith((x, y) => x < y)


var list = List("hello", "cat", "happy", "feel")
// 字典顺序
list.sortBy(x => x)
// 执行排序
list.sortWith((x, y) => x > y)
list.sortWith((x, y) => x < y)


val map = Map("peiqi" -> 5, "jong" -> 3, "baji" -> 12)
map.toList.sortBy(x => x._1)
//List((baji,12), (jong,3), (peiqi,5))
map.toList.sortBy(x => x._2) //List((jong,3), (peiqi,5), (baji,12))
// 指定key排序
map.toArray.sortWith((x,y)=>x._1>y._1)
map.toArray.sortWith((x,y)=>x._1<y._1)

//指定value排序规则
map.toArray.sortWith((x,y)=>x._2>y._2)
map.toArray.sortWith((x,y)=>x._2<y._2)

自定义类型在集合中的排序

Scala
val u1 = new User("wuji", 34)
val u2 = new User("zhiruo", 24)
val u3 = new User("zhoamin", 44)
val u4 = new User("cuishan", 64)

var arr = Array(u1, u2, u3, u4)
// 按照姓名字典排序
arr.sortBy(user => user.name)
//年龄小到大
arr.sortBy(user => user.age)
//数值类型的排序可以直接使用- 来倒序排列 年龄大到小
arr.sortBy(user => -user.age)
// 年龄大到小
arr.sortWith((user1, user2) => user1.age > user2.age)
// 年龄小到大
arr.sortWith((user1, user2) => user1.age < user2.age)
// 姓名字典升序
arr.sortWith((user1, user2) => user1.name < user2.name)
//姓名字典降序
arr.sortWith((user1, user2) => user1.name > user2.name)

7.8.15partitionspan (了解)

partition将数组按照指定的规则分组 ,适用于 数组  List  Map

Scala
val  list = List(1,2,3,4,5,6,7,8,9)
// 将集合根据条件分成两组返回一个存储集合的元组第一个集和实符合要求的元素
//(List(3, 6, 9),List(1, 2, 4, 5, 7, 8))
val res: (List[Int], List[Int]) = list.partition(x=>x%3==0)
//从第一个元素开始处理 配到不符合条件的就结束
list.span(_<3) // (List(1, 2),List(3, 4, 5, 6, 7, 8, 9))

val list2 = List("scala" , "is" , "option" , "fucntion")
// (List(scala, is, fucntion),List(option))
list2.partition(_.hashCode%2==0)
map
集合******************************************
val map = Map("peiqi" -> 5, "jong" -> 3, "baji" -> 12)
// (Map(baji -> 12),Map(peiqi -> 5, jong -> 3))
val tuple: (Map[String, Int], Map[String, Int]) = map.partition(x=>x._1.contains("b"))
val tuple2: (Map[String, Int], Map[String, Int]) = map.partition(x=>x._2 >5)

7.8.16grouped

将集合中的元素按照指定的个数进行分组

Scala
val  list1 = List(1,2,3,4,5,6,7,8,9)
val list2 = List("scala" , "is" , "option" , "fucntion")
val map = Map[String,Int]("peiqi" -> 5, "jong" -> 3, "baji" -> 12)
// 两个元素分成一组 ,9个元素总共分成5组
val res: Iterator[List[Int]] = list1.grouped(2)
var i = 0
// 遍历每个元素
res.foreach(list=>{
  i+=
1
  list.foreach(x=>println(x+"----"+i))  // 打印每个元素和它所对应的组
})
// 将map集合按照个数进行分组
val res2: Iterator[Map[String, Int]] = map.grouped(2)
res2.foreach(i=>i.foreach(x=>println((x._1,x._2))))

7.8.17groupBy

将集合中的数据按照指定的规则进行分组

序列集合

Scala
val  list1 = List(1,2,3,4,5,6,7,8,9)
val list2 = List("scala" , "is" , "option" , "fucntion")
 
// 对序列数据进行分组
val res1: Map[Boolean, List[Int]] = list1.groupBy(x=>x>3) //HashMap(false -> List(1, 2, 3), true -> List(4, 5, 6, 7, 8, 9))
val res2: Map[Boolean, List[Int]] = list1.groupBy(x=>x%2==0)//HashMap(false -> List(1, 3, 5, 7, 9), true -> List(2, 4, 6, 8))
list2.groupBy(x=>x.hashCode%2==0)
//HashMap(false -> List(is, option, fucntion), true -> List(scala))
val res: Map[Boolean, List[String]] = list2.groupBy(x=>x.startsWith("s"))

键值映射集合分组

Scala
val map = Map[String,Int]("peiqi" -> 5, "jong" -> 3, "baji" -> 12)
 
val arr = Array(("cat",21),("lucy",33),("book",22),("jack",34))
// 按照key和value的内容分组
 println(map.groupBy(mp => mp._1))
 println(map.groupBy(mp => mp._2))
 

//  根据key 或者 value 分成两组  满足条件的和不满足条件的
 println(map.groupBy(mp => mp._1.hashCode%2==0))
 println(map.groupBy(mp => mp._2>
2))

 
// 对偶元组集合 和map的分组方式是一样的
 arr.groupBy(arr=>arr._1)
 arr.groupBy(arr=>arr._2)

7.8.18reduce

底层调用的是reduceLeft , 从左边开始运算元素

Scala
val list = List(1,3,5,7,9)
// 每个元素累加  从左到右相加
val res1: Int = list.reduce(_+_)  // 25
//
1-3)-5)-7)-9
val res2: Int = list.reduce(_ - _)  // -23
val arr = Array("haha", "heihei", "hehe")
// x 前面的元素  y 后面的元素  实现集合中字符串的拼接
val res3: String = arr.reduce((x, y) => x + " " + y) //haha heihei hehe
// 键值对元素的
val map = Map(("shaolin",88),("emei", 77),("wudang",99))
//(shaolin emei wudang,264)   key value分别做归约操作
val res4: (String, Int) = map.reduce((m1,m2)=>(m1._1+" "+m2._1 , m1._2+ m2._2))

7.8.19reduceLeftreduceRight

Scala
  val list = List(1, 3, 5, 7, 9)
 
val arr = Array("a", "b", "c","d","e")
 
val map = Map(("shaolin",88),("emei", 77),("wudang",99))
 
// 执行顺序是  1+3)+5)+7)+9
  val res1: Int = list.reduceLeft(_+_)
 
// 1-3)-5)-7)-9
  val res01: Int = list.reduceLeft(_-_)
 
val res2: String = arr.reduceLeft((a1, a2)=>a1+","+a2)
 
val res3: (String, Int) = map.reduceLeft((m1,m2)=>(m1._1+" "+m2._1 , m1._2+ m2._2))
  println(res1) 
//25
  println(res2) //a,b,c,d,e
  println(res3)//(shaolin emei wudang,264)

  val res11: Int = list.reduceRight(_+_) //  25
  // 执行顺序是  a,(b,(c,(d,e)))    a2  右边的最后一个元素
  val res12: String = arr.reduceRight((a1, a2)=>a1+","+a2)//a,b,c,d,e
  val res13: (String, Int) = map.reduceRight((m1,m2)=>(m1._1+" "+m2._1 , m1._2+ m2._2))//(shaolin emei wudang,264)
 // 5-(7-9)-->5-(7-9)-->3-(5-(7-9))-->1-(3-(5-(7-9)))
  val res14: Int = list.reduceRight(_-_)
  println(res14)
// 5
  println(res11)  //25
  println(res12) //a,b,c,d,e
  println(res13)//(shaolin emei wudang,264)
// 字符串的拼接
arr.reduce(_ ++ _)
// 字符串的拼接
println(arr.reduce(_ ++"."++ _))

7.8.20fold,foldLeft foldRight

归约操作类似于reduce函数  ,但是fold函数中多出来一个初始值

Scala
val arr = Array("tom" , "cat" , "jim" , "rose")
// 遍历集合中的每个元素进行拼接  比reduce函数多出一个初始值
val res = arr.fold("hello")(_+" "+_)
val ls = List(1,3,5,7)
// 100+1)+3)+5)+7 底层调用的是  foldLeft
val res2 = ls.fold(100)(_+_)  // 116
ls.foldLeft(100)(_+_) //  116
 

从右边开始运算   默认的值先参与运算进来
// 7-10)-->5-(-3)-->3-8 -->1-(-5)

val res01: Int = ls.foldRight(10)(_-_) //6

7.8.21交集差集并集

Scala
val arr1 = Array(1, 3, 5, 7, 0)
val arr2 = Array(5, 7, 8, 9)
val res1: Array[Int] = arr1.intersect(arr2) // 交集 5 7
val res2: Array[Int] = arr1.diff(arr2) // 差集  1  3
// 单纯的合并两个元素中的数据
val res3: mutable.ArraySeq[Int] = arr1.union(arr2) // 1,3,5,7 ,5,7,8,9
// 去除重复数据
val res4: mutable.ArraySeq[Int] = res3.distinct //,3,5,7,8,9

7.8.22distinctdistinctBy

去除集合中的重复的元素  ,可以去除简单类型的数据, 也可以除去自定义的类型(底层依然是hashcode和equals)

Scala
val arr1 = Array("a", "a","ab","cat" ,"hellocat" ,"hicat")
val newarr: Array[String] = arr1.distinct
newarr.foreach(println)

条件去重

Scala
val arr1 = Array(new User("ls",21),new User("ls",22),new User("zss",21))
//
去除重名的重复数据
val res: Array[User] = arr1.distinctBy(x=>x.age)
res.foreach(x=> println(x.name))

7.8.23zip

实现拉链式拼接, 只要操作的集合是迭代集合就可以拼接

Scala
val list1 = List("a" , "b" , "c" , "d")
val arr1 = Array(1,2,3,4)
val map  = Map[String,Int]("aa"->11,"cc"->22,"dd"->33)
// 以两个迭代集合中少的一方为基准对偶拼接List((a,1), (b,2), (c,3))
val res: List[(String, Int)] = list1.zip(arr1)
//ArraySeq((1,(aa,11)), (2,(cc,22)), (3,(dd,33)))
val res2: Array[(Int, (String, Int))] = arr1.zip(map)

7.8.24zipWithIndex

简单理解为 遍历集合中的每个元素 , 将每个元素打上对应的索引值 , 组成元组(element , index) 返回新的集合 !

Scala
val list1 = List("a" , "b" , "c" , "d")
val arr1 = Array(1,2,3,4)
val map  = Map[String,Int]("aa"->11,"cc"->22,"dd"->33)
// List(((a,1),0), ((b,2),1), ((c,3),2), ((d,4),3))
list1.zip(arr1).zipWithIndex
//List((a,0), (b,1), (c,2), (d,3))
list1.zipWithIndex

7.8.25scan

一个初始值开始,从左向右遍历每个元素,进行积累的op操作

Scala
val arr = Array("cat" , "jim" , "tom")
// ArraySeq(hello, hello cat, hello cat jim, hello cat jim tom)
arr.scan("hello" )(_ +" "+ _)
val nums = List(1,2,3)
// List(10,10+1,10+1+2,10+1+2+3) = List(10,11,13,16)
val result = nums.scan(10)(_+_)  
nums.foldLeft(10)(_+_)  //   16

7.8.26mkString

将集合中的每个元素拼接成字符串

Scala
val arr = Array("a", "b", "c")
val str = arr.mkString
arr.mkString(
" ")
arr.reduce(_+_)
arr.reduce(_ +
" " + _)

7.8.27slice,sliding

slice(from: Int, until: Int): List[A] 提取列表中从位置from到位置until(不含该位置)的元素列表, 起始位置角标从0开始;

  • slice

Scala
val arr = Array("a", "b", "c" ,"d","e","f")
arr.slice(
0 ,2) // res0: Array[String] = ArraySeq(a, b)

  • sliding

sliding(size: Int, step: Int): Iterator[List[A]] 将列表按照固定大小size进行分组,步进为step,step默认为1,返回结果为迭代器;

Scala
val nums = List(1,1,2,2,3,3,4,4)
//
参数一:子集的大小  参数二:步进
val res: Iterator[List[Int]] = nums.sliding(2,2)
res.toList
// List(List(1, 1), List(2, 2), List(3, 3), List(4, 4))

7.8.28take,takeRight,takeWhile

  • take  默认从左边开始取

Scala
val arr = Array("a", "b", "c" ,"d","e","f")
// 从左边获取三个元素,组成新的数组集合
arr.take(3)

  • takeRight  默认从右边开始取

Scala
val nums = List(1,1,1,1,4,4,4,4)
val right = nums.takeRight(4) // List(4,4,4,4)

  • takeWhile

Scala
// 小于4 终止
nums.takeWhile(_ < 4)
val names  = Array ("cat", "com","jim" , "scala" ,"spark")
// 从左到右遍历符合遇到不符合条件的终止,储存在新的集合中
names.takeWhile(_.startsWith("c"))

7.8.29Aggregate聚合

全局聚合

aggregate方法是一个聚合函数,接受多个输入,并按照一定的规则运算以后输出一个结果值,在2.13+版本中被foldLeft取代!

7.8.30集合间的转换函数

可变集合和不可变集合的转换

  • toArray  将其他类型的集合转换成数组
  • toList    将其他类型的集合转转成list
  • toSet     将其他类型的集合转换成Set
  • toSeq     将其他类型的集合转换成Seq序列
  • toMap     将对偶类型的集合转换成Map
  • toString    将其他类型转换成字符串

Scala的面向对象 ,构造器 , 代码块 , 集合 以及集合的常用方法.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/651109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

详解c++---map的介绍

目录标题 map容器的介绍pair的介绍map的构造函数insert函数make_pair函数find函数map的[ ]重载multimap map容器的介绍 通过之前的学习想必大家对set容器的理解应该非常的深刻了&#xff0c;我们知道他的底层是一个k结构的搜索二叉树&#xff0c;可以对数据进行去重并排序&…

Redis实现分布式锁详解

Redis实现分布式锁详解 一 分布式锁简介二 Redis实现分布式锁核心思路三 Redis实现分布式锁实践3.1 锁的基本接口3.2 加锁解锁逻辑3.3 修改业务逻辑3.4 单元测试观察结果 四 Redis分布式锁误删情况4.1.Redis分布式锁误删情况逻辑说明&#xff1a;4.2 解决Redis分布式锁误删问题…

当心健身跑步应用悄悄泄露用户住址

据BleepingComputer 6月11日消息&#xff0c;美国北卡罗来纳州立大学罗利分校的研究人员发现 Strava 应用程序的热图功能存在隐私风险&#xff0c;可能导致攻击者识别出用户的家庭住址。 Strava 是一款流行的跑步伴侣和健身追踪应用程序&#xff0c;在全球拥有超过 1 亿用户&a…

2个月“我“从功能测试进阶到自动化测试,offer收到麻了...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 自动化测试是将人…

C++【STL】之vector模拟实现

C vector类模拟实现 上一篇讲解了vector的使用&#xff0c;这一篇接着介绍vector的模拟实现&#xff0c;这里依然是讲解常用接口的模拟实现&#xff0c;话不多说&#xff0c;正文开始&#xff01; 文章目录&#xff1a; C vector类模拟实现1. 成员变量2. 默认成员函数2.1 构造…

使用lcov生成覆盖率报告

使用lcov生成覆盖率报告 1- 需要准备的东西1.1 工具lcov1.2 需要用到中间脚本 gcno gcda1.3 源文件 2- 生成覆盖率报告2.1 step1: 编译阶段2.2 step2: 数据收集与提取阶段2.3 step3: 报告形成阶段2.4 step4: lcov生成覆盖率报告结果info文件2.5 step5: genhtml 命令生成网页版的…

给定一个字符串比如“abcdef”,要求写个函数变成“defabc”,位数是可变的。

首先可以使用字符串切片的方法来实现这个需求。 具体做法是&#xff1a;① 定义一个整数变量 n 表示要切割的位置&#xff0c;本实例中为 3 。 ② 将字符串按照 n 分割成两个字串&#xff0c;即 “abc” 和 “def”。 ③ 将两个字符串颠倒顺序&#xff0c;即 “cba” 和 “fed…

数据结构 栈和队列

栈和队列基本概念 栈&#xff08;Stack&#xff09;和队列&#xff08;Queue&#xff09;都是常见的数据结构&#xff0c;用于存储和操作一组元素。它们在结构和操作方式上有所不同。 栈的基本概念&#xff1a; 栈是一种线性数据结构&#xff0c;具有后进先出&#xff08;L…

CentOS GCC 离线升级 编译安装 8.3.0

从系统自带的 gcc-4.8.5 版本升级至 gcc-8.3.0 版本 目录 下载源代码&#xff1a; 下载依赖&#xff1a; 编译&#xff08;约一个小时&#xff09; 重开控制台确认是否生效 下载源代码&#xff1a; https://ftp.gnu.org/gnu/gcc/gcc-8.3.0/gcc-8.3.0.tar.gzhttps://ftp.gn…

Nacos和Feign

Nacos配置管理 统一配置管理实现 1.引入Nacos的配置管理客户端依赖 <!--nacos的配置管理依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency…

国产开源中文大语言模型再添重磅玩家:清华大学NLP实验室发布100亿参数规模的开源可商用大语言模型CPM-Bee

5月27日&#xff0c;OpenBMB发布了一个最高有100亿参数规模的开源大语言模型CPM-BEE&#xff0c;OpenBMB是清华大学NLP实验室联合智源研究院成立的一个开源组织。该模型针对高质量中文数据集做了训练优化&#xff0c;支持中英文。根据官方的测试结果&#xff0c;其英文测试水平…

Python零基础入门(二)——IDE介绍以及Python+PyCharm的安装

系列文章目录 个人简介&#xff1a;机电专业在读研究生&#xff0c;CSDN内容合伙人&#xff0c;博主个人首页 Python入门专栏&#xff1a;《Python入门》欢迎阅读&#xff0c;一起进步&#xff01;&#x1f31f;&#x1f31f;&#x1f31f; 码字不易&#xff0c;如果觉得文章不…

docker容器介绍及安装

Docker介绍 Docker 起源于2013年。 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go语言开发&#xff0c;Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的系统。 优点&#xff1a; 可以用来快速交付应用。加…

SQL 的window开窗函数简单使用

背景&#xff1a; 开窗函数不论是spark的还是clickhouse的在日常的查询中是一个很常用的功能&#xff0c;特别是他想要解决的问题和group by的很类似&#xff0c;这两种容易引起混淆&#xff0c;本文就简单的描述下开窗函数的简单用法 使用详解 首先窗口函数和group by是完全…

caj文件在线转换成pdf方法,看这个就会了!

当需要将Caj文件转换为PDF格式时&#xff0c;有多种方法可供选择。本文将介绍三种常用的方法&#xff0c;以帮助您完成这个任务。 第一种方法&#xff1a;使用记灵在线工具 一种常用的方法是利用记灵在线工具&#xff0c;它是一款提供免费文件转换服务的在线工具。以下是使用…

消息队列RabbitMQ

1. 消息队列 RabbitMQ 消息队列是一种在应用程序之间发送和接收消息的方法&#xff0c;可以实现异步通信、解耦应用、提高系统性能等效果。RabbitMQ 是一款常用的开源消息中间件&#xff0c;它实现了 AMQP 协议规范&#xff0c;并提供了可靠性、灵活性、易用性等优秀特性。本文…

DBSyncer安装_配置postgresql和mysql_sqlserver_oracel全量增量同步---数据全量增量同步之DBSyncer001

国内做开源的大神做的,用了一下还可以,就是不能和Phoenix这种操作hbase等数据库一起用, https://gitee.com/ghi/dbsyncer#postgresql 这个是官网,下载安装非常简单,官网也有中文详细说明. 直接下载安装包: 然后解压到某个地方,主要要用unzip dbsyncer.zip -d /opt/module这样…

干翻Mybatis源码系列之第十篇:Mybatis拦截器基本开发、使用和细节分析

给自己的每日一句 不从恶人的计谋&#xff0c;不站罪人的道路&#xff0c;不坐亵慢人的座位&#xff0c;惟喜爱耶和华的律法&#xff0c;昼夜思想&#xff0c;这人便为有福&#xff01;他要像一棵树栽在溪水旁&#xff0c;按时候结果子&#xff0c;叶子也不枯干。凡他所做的尽…

微信小程序 method传参 和 页面传参

method传参 标签&#xff1a; <image src"/img/b1.jpg" classbannerImg mode"widthFix" bindtap"gotoMessage" data-flag"msg"></image> 使用data-参数Key 指定参数值 method: gotoMessage(e){ let flagName e.targe…

9. 子查询

9.1 概述 ​ 子查询指一个查询语句嵌套在另一个查询语句内部&#xff0c;这个特性从 MySQL 4.1 开始引入。 ​ 从相对位置来说&#xff0c;子查询又被称为内查询&#xff0c;主查询又被称为外查询 9.1.1 子查询的结构 子查询的结构如下所示&#xff1a; SELECT select_lis…