门清
Scala高阶函数,函数是Scala中最重要的重点
把函数体看成变量
工厂方法 工厂变量 简单工厂
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")())
}
}
用高阶函数解决问题
为什么用设计模式–高内聚,低耦合,提高程序的健壮性,—2,3个模式最优的方法。
接口下面是具体的类,了多个类聚合在一起就合成了接口。(预埋接口,使用接口)好的设计模式会很优美。用工厂模式限制接口类型。
离散数学,
二维数组压平就变成了一维数组(变形的测试图)
reduce函数:两两相加,
Java方法重载 名字一样,参数类型不一样,方法名不能一样。 《柯里化 》
scala:Array(集合,序列)
Scala高阶函数数组中 左子树,右子树奇数个 完整二叉树偶数 底层都是二叉树,
秒懂)图解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中的方法都是静态方法:::::所以引出来的样例类:它既有成员方法也有静态方法。也就是伴生对象与伴生类
主构造器/辅助构造器
有参/无参构造器,有了有参构造,就不会自动生成无参构造器,狗哦早期可以卸载第一句,也可以卸载最后一句,位置不受限制。
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关键字来实现继承
抽象类
接口解耦 斩断类和接口之间的关系, 接口的第二作用:就是约束。
抽象类关键字: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,这时就可能会发生下图的执行顺序
重排序.png
上图表示,在构造函数还没完成时,就已经读取到了不为null的对象,构造函数中的this造成了引用的溢出。
所以,在构造函数返回前,被构造对象的引用不能为其他线程可见,因为此时的 final 域可能还没有被初始化。