门清Scala高阶函数

本文深入探讨Scala中的高阶函数,尤其是foldLeft和foldRight的用法,通过实例解释它们的区别。同时,文章还涵盖了Scala中的类、抽象类、伴生类与对象、this的多种用途等核心概念,旨在帮助读者更好地理解和运用Scala。
摘要由CSDN通过智能技术生成

门清

Scala高阶函数,函数是Scala中最重要的重点

把函数体看成变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FaSO5MIc-1569812863336)(C:\Users\tt\AppData\Roaming\Typora\typora-user-images\1569307872942.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pWZN2ufZ-1569812863338)(C:\Users\tt\AppData\Roaming\Typora\typora-user-images\1569308182740.png)]

工厂方法 工厂变量 简单工厂

object MyhHello {
  //高阶函数最简单的工厂模式
  var humber = ()=>{
    //可以连接数据库,HBase,masql等等
    "我是汉堡包"
  }
  var checken = ()=> "我是鸡翅膀"

  def  kgc(foodname:String):()=>String = foodname match {
    case "humber" => humber
    case "cheken" => checken
    case  _=> null
  }

  def main(args: Array[String]): Unit = {
      println(kgc("cheken")())
  }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l3VKYtja-1569812863340)(C:\Users\tt\AppData\Roaming\Typora\typora-user-images\1569314418168.png)]

用高阶函数解决问题

为什么用设计模式–高内聚,低耦合,提高程序的健壮性,—2,3个模式最优的方法。

接口下面是具体的类,了多个类聚合在一起就合成了接口。(预埋接口,使用接口)好的设计模式会很优美。用工厂模式限制接口类型。

离散数学,

二维数组压平就变成了一维数组(变形的测试图)

reduce函数:两两相加,

Java方法重载 名字一样,参数类型不一样,方法名不能一样。 《柯里化 》
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IWOUdzia-1569812863341)(C:\Users\tt\AppData\Roaming\Typora\typora-user-images\1569316272057.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HCDYIoqx-1569812863342)(C:\Users\tt\AppData\Roaming\Typora\typora-user-images\1569316296661.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tIFzvOR6-1569812863342)(C:\Users\tt\AppData\Roaming\Typora\typora-user-images\1569316449504.png)]

scala:Array(集合,序列)

Scala高阶函数数组中 左子树,右子树奇数个 完整二叉树偶数 底层都是二叉树,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0taFnQb7-1569812863344)(C:\Users\tt\AppData\Roaming\Typora\typora-user-images\1569318876847.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zgHWzMzC-1569812863346)(C:\Users\tt\AppData\Roaming\Typora\typora-user-images\1569318963015.png)]

秒懂)图解scala的foldleft和foldright

foldLeft:

比如

List(1,7,2,9).foldLeft(0)(-)

其中0是初始值
一般情况下对于foldLeft可以这么解决:0-1-7-2-9 = -19
还可以画一个图(别吐槽):
在这里插入图片描述
本栗子的操作就是_-_,也就是各元素相减,所以我们从底端开始就得到(((0-1)-7)-2)-9= -19

foldRight

骚微变一下初值

List(1,7,2,9).foldRight(7)(-)

这个就比foldLeft复杂一点了,萌新就不能一眼看出结果了,那么我们可以一样的画个图(好累):
在这里插入图片描述
这个的话就要从下面看了,
先是(9-7)
然后 2 -(9-7)
然后7-(2-(9-7))以此类推得到
1-(7-(2-(9-7))) = -6
其他的情况也可以以此类推
对就是这样,同学们理解了吗
上面的函数比较丰富:

scala> val fun1:PartizlFunction[Any,Int]={case i:Int=>i*2}
scala> arr1
     :Array[Any] = Array(1,2,3,6,abc)
scala> arr1.collect(fun1)
	 :Array[Int] = Array(2,4,6,12) 
arr.collect()表示偏函数里面的过滤你想要的数据
柯里化,左子树,右子树,Hash分区等对应的函数

样例类,

流处理,批处理。

???????????

偏函数:对部分函数进行处理,附楼木配置文件怎么贴,卡夫卡是什么?Java多线程,上锁死锁,Java虚拟机怎么弄。java写设计模式,Scala写设计模式,简单工厂,单例模式,

9.25///偏函数:

类(class)

搜搜移动大厅练习,通过class关键字定义默认成员类为public,也支持private,protected

java 类,伴生类与伴生对象(动态/静态相互转换)

一个类里面既要成员方法又要静态方法,则使用样例类 ,伴生对象与伴生类

在Scala中有两类东西(1)类,类里面的方法全都时成员方法,它里面不能定义静态放方法(2)对象Object,其中Object中的方法都是静态方法:::::所以引出来的样例类:它既有成员方法也有静态方法。也就是伴生对象与伴生类

主构造器/辅助构造器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fhiCAykV-1569812863348)(C:\Users\tt\AppData\Roaming\Typora\typora-user-images\1569392461277.png)]

有参/无参构造器,有了有参构造,就不会自动生成无参构造器,狗哦早期可以卸载第一句,也可以卸载最后一句,位置不受限制。

this():在Java里面表示当前的对象,在Java里面有两种用法(1)this.调用当前对象的当前变量值或当前对象的方法(2)调用构造器

this不能写在方法外面,因为他只能调用成员或者方法,而写在外面既不是成员也不是方法,所以不行。this可以有多个。

var x:Int = xc var y:Int yc

//辅助构造器, 用this()代表当前对象,方法中可以写this默认传入的参数。

定义一个无参构造器:给上面的那个人传值。

主构造器:(线程:xc: Int,yc:Int)

def this() = {

this(0,0)

}

类的继承

Scala使用extends关键字来实现继承

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4SmAntFY-1569812863350)(C:\Users\tt\AppData\Roaming\Typora\typora-user-images\1569392959648.png)]

抽象类

接口解耦 斩断类和接口之间的关系, 接口的第二作用:就是约束。

抽象类关键字:abstract

重写:override

如果两个类中有相同的行为方法:则调用共同方法。

抽象方法是部分实现和部分

继承

什么叫解偶过程?什么叫做依赖过程?

//1.依赖---继承
//父类
public class Father{
	public void sayHello(){
		System.out.println("father hello")
	}
}
//子类
public class Son extends Father{
	public void eee(){
		System.out.println("son hello");
	}
}
/小结:Father和Son偶合性太强了。

//解耦合--用组合的方法
//换成与接口耦合了,接口是轻量级的,实现接口
//1.接口的作用就是解耦合,斩断类和类之间的依赖的时候使用此方法(斩断魔爪)
//2.接口还有另外一个作用:约束  (实现对象,保证自己因该有的方法)
//3.接口:实现多根继承,因外Java里面是单根继承,Scala里面的另外一个名字:特质
public interface IFather{
	public void sayHello();
}

public class Son{
	private IFather fat;
	public Son(IFather fat){
		this.fat = fat;
	}
	public void eee(){
	System.out.println("son hello");
	}
	public void sayHello(){
	fat.sayHello();
	}
}

public interface IFather{
	public void sayHello();
}
抽象类:

他依然是一个类,但是此类前面有关键字:abstract (代表抽象)

一个类在N个方法中有相同的行为动作,我们应该把这个类配成一个共同方法,让大家一起调用

在两个类中有共同的方法:使用抽父类,让下面两个类继承一个父类。

抽象方法:是部分实现,以及部分抽象(挣钱方法相同(抽象方法),花钱方法不同(标准的实际方法))这样就形成了一个父类,两个子类。实现半约束,半继承,就是用抽象类。

视频一小时位置???
伴生类与伴生对象 : ( Companion )
单例对象与同名类定义在同一文件中时形成绑定关系

​			1)同名类称为单例对象的伴生类(class)
​			2)单例对象称为同名类伴生对象(object)
伴生类与半生对象可相互访问各自私有成员
伴生对象可为半生类增加静态方法

//Student.scala
//伴生类
class Student(n: String, a: Int) {
  private var name = n    //私有变量,伴生对象可以访问
  private var age = a
}

//伴生对象
//使用伴生对象的apply()方法省掉new关键字,其中Student.apply()等价于Student()
object Student {
  def apply(n: String, a: Int): Student = new Student(n, a)
  def main(args: Array[String]): Unit = {
    val stu=Student("Jason",9)  //通过伴生对象的apply()方法创建实例
    println(stu.name)
  }
}
unapply():对象提取器
枚举
样例类
泛型类stack [T] 

需求说明书

概要设计

详细设计

编写接口

最后合并

考核测试

this的几种用法

调用其他构造函数
public class ThisDemo {

    private int age;

    private String name;

    public ThisDemo(String name) {
        this();
        this.name = name;
    }

    public ThisDemo() {
        this.age = 18;
    }
}

这里我们使用一个含参的构造函数调用了一个无参构造函数。有一点需要我们注意:
使用this()调用构造器,必须要放在第一行,如果可以放在其他行,当ThisDemo存在父类Father时,实例化过程如下:

  • 第一行没有this()或者super(),默认执行super()
  • 完成对父类对象的初始化
  • 返回到子类构造函数继续执行
  • 此时调用this(),将会再次调用super(),再次对父类对象初始化,这样就会产生两个对象,造成了资源的浪费

所以java为了保持对象的合理性,是禁止这种操作的。

获取当前对象的引用
public class ThisDemo {

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

这里我们调用了this的name属性,在方法中将形参name传递给成员变量name,使用this可以便于区分成员变量和局部变量,提高代码的可读性。

代表自身对象
public class ThisDemo {

    private String name;//私有化的全局变量
    
    private String age;
    
    public ThisDemo setName(String name) {//方法接收的参数
        this.name = name;//表示当前变量
        return this;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public static void main(String[] args) {
        ThisDemo demo = new ThisDemo();
        demo.setName("stalary").setAge(21);
    }

这里我们使用this来返回的当前的对象,可以把这个this当成一个类型为该类类型,名称为this的隐含成员变量。

引用溢出

@Data
class FinalReferenceEscape{

    final int i;

    int age;

    static FinalReferenceEscape object;

    public FinalReferenceEscape() {
        i = 1; // 写final域
        this.age = 18;
        object = this;// this引用溢出
    }

    public static void write() {
        new FinalReferenceEscape();
    }

    public static void read() {
        if (object != null) {
            System.out.println(object.i);
        }
    }

    public static void main(String[] args) {
        new Thread(() -> FinalReferenceEscape.write()).start();
        new Thread(() -> FinalReferenceEscape.read()).start();
        System.out.println(FinalReferenceEscape.object);
    }

}

结果

1
FinalReferenceEscape(i=1, age=18)

虽然写final域的重排序规则是可以确保的。
但是要除了要保证在引用变量为任意线程可见之前,该引用变量指向的对象的final域已经在构造函数中被正确初始化过,而且在构造函数内部,不能让这个引用为其他线程所见(对象引用不能在构造函数中溢出)

在上面的代码中:
一个线程执行write,一个线程执行read,这时就可能会发生下图的执行顺序

img

重排序.png

上图表示,在构造函数还没完成时,就已经读取到了不为null的对象,构造函数中的this造成了引用的溢出。
所以,在构造函数返回前,被构造对象的引用不能为其他线程可见,因为此时的 final 域可能还没有被初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值