函数式编程

与面向对象的区别

面向对象编程
需要某个结果→找到能实现改该功能的类→创建对象→调用方法
函数式编程
需要某个结果→去做,实现这个结果

使用

写法 ( ) - > { }

( ) 接口中的唯一方法的参数列表
- > 传递参数给方法体
{ } 重写的方法体

省略写法及注意事项

  1. 当参数列表为空时,小括号内容空置即可
  2. 参数的类型可以一一对应时,可以不写类型名,只写传递的形参变量名(必须是形参,不能写实参!
  3. 有且只有一个参数时,()可以省略,直接写形参名
  4. 当方法体只有一句话,方法体前后的{}可以省略,分号也必须省略(如果是返回语句,return 也必须省略)
  5. 能够被以lambda表达式书写的,必须是 函数式接口
String s ="aaa";
new Thread(()->System.out.println(s)).start();
//等价于
new Thread(new Runnable(String s){
	@override
	public void run(){
		System.out.println("aaa");
	}
}
  1. 被重写的一定是唯一的那个抽象函数,但执行的方法是哪个,根据调用的是哪个方法决定。
public class Test {
	public static void main(String[] args) {
		//重写抽象方法t2仅表明此处传递的是T的实现类对象
		f(8,(i)->System.out.print(i+i+i));
		
	}
	public static void f(int i,T t) {
		//调用哪个方法,执行的就是哪个(执行的是默认方法t1而非被重写的抽象方法t2
		t.t1(i);
	}
}

interface T{
	default void t1(int i){
		System.out.println(i*i);
	}
	
	void t2(int i);
}

优点

  1. 简化写法
  2. 简化实现类/对象的创建,并省去相关class文件的生成,节约空间提升性能
  3. 延迟加载,省去不必要的执行动作
interface F{
	String print(int i);
}

public class Test {
	public static void main(String[] args) {
		String a = "1";
		String b = "2";
		String c = "3";
		
		printF(1, (i)->a+b+c);
		printF(2, (i)->a+b+c);//不符合条件根本不会进入重写的print方法,免去了计算a+b+c
		
	}
	
	public static void printF(int i,F f){
		if(i==1){
			System.out.println(f.print(i));
		}
	}

}

常用场景

线程、比较器等

  • 实例:比较器
package com.qf.study;

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

public class Test {
	public static void main(String[] args) {
		
		List<Stu> stus = new ArrayList<>();
		stus.add(new Stu("f",31));
		stus.add(new Stu("t",12));
		stus.add(new Stu("a",23));
		
		//方法1:实体类直接实现comparable接口并重写compareTo方法
//		System.out.println("1:"+stus);
//		Collections.sort(stus);
//		System.out.println("1:"+stus);
		
		//方法2:Collections工具类调用sort方法时传入一个比较器对象作为参数。匿名创建Comparator接口的子类对象并重写compare方法
//		System.out.println("2:"+stus);
//		Collections.sort(stus, new Comparator<Stu>() {
//			@Override
//			public int compare(Stu o1, Stu o2) {
//				return o1.age-o2.age;
//			}
//		});
//		System.out.println("2:"+stus);
		

		//方法3:lambda表达式,直接重写comparator接口的唯一抽象方法实现比较功能
		System.out.println("3:"+stus);
		Collections.sort(stus, (o1,o2)->o1.age-o2.age);
		System.out.println("3:"+stus);
	}
	
}

class Stu {//方法1:implements Comparable<Stu>
	String name;
	int age;
	public Stu(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	//方法1:实体类实现comparable接口并重写compareTo方法
//	@Override
//	public int compareTo(Stu o) {
//		return o.age-this.age;
//	}
	
	@Override
	public String toString() {
		return name + "-" + age;
	}
}

函数式接口FunctionalInterface

概念

内部有且只有一个抽象方法的接口。(可以有多个静态/普通/私有方法)

写法

使用@FunctionalInterface注解声明

	@FunctionalInterface
	interface A{
		void a();
		
		static void b(){
		}
		
		private void c(){
		}
		
		String void d(){
		}
		
	}

常用的函数式接口

生产型 Supplier<T>

指定返回类型
意义:限制返回一个指定的类型T t的对象,但避免了冗余代码
使用场景:需要一个T类型的结果

  • get();
public class Test {
	public static void main(String[] args) {
		String str = "wrgryvchxe";
		f(str,()->{
			String newStr = str.substring(str.length()-4,str.length());
			return newStr;
		});
	}
	
	public static void f(String str,Supplier<String> sup) {
		String s = sup.get();
		System.out.println(s);
	}
}

消费型 Consumer<T>

指定参数类型
意义:限制必须通过accept(T t)对指定的参数类型进行操作
使用场景:已有T t ,需要对t 进行操作

  • accept()
public class Test {
	public static void main(String[] args) {
		String str = "wrgryvch88xe";
		f(str,s->System.out.println(s.substring(s.length()-4,s.length())));
	}
	
	public static void f(String str,Consumer<String> consumer) {
		consumer.accept(str);
	}
}
  • 【默认方法】andThen()
    意义:将多步操作组合在一起
    使用方式:consumer1.andthen(consumer2).accept()
    方法的源码理解:①返回的是一个,重写了accept方法的consumer对象②重写的方法内容是:先调用自己的accept,再调用参数的accept
//consumer<T及其子类> 接口的实现类对象 after作为参数
//consumer<T>作为返回值
default Consumer<T> andThen(Consumer<? super T> after) {
		//非空限制
        Objects.requireNonNull(after);
        //该default方法需要return 一个consumer<T>,使用lambda表达式重写其唯一的accept方法:(T t)->{}
        return (T t) -> { 
        	//重写的方法体中,首先调用this.accept(),执行自己的accept
        	accept(t); 
        	//然后调用after对象的accept方法,即拼接进行下一个步骤
        	after.accept(t); 
        	};
    }

andthen的源码等价于

default Consumer<T> andThen(Consumer<? super T> after) {
		Objects.requireNonNull(after);
		return new Consumer<T>(){
			@override
			public void accept(){
				this.accept(t); 
				after.accept(t); 
			}
		}
}

Predictcate

对指定参数类型进行判断,返回Boolean

  • test()
package com.qf.study;

import java.util.function.Predicate;

public class Test {
	public static void main(String[] args) {
		String username="a1jwiqo7y";
		String pw="1122344";
		f(s->(s.charAt(0)+"").matches("[a-zA-z]")
		, s->s.length()>6&& s.length()<12
			, username, pw);
		
		
	}
	
	public static void f(Predicate<String> pred,Predicate<String> pred2,String un,String pw){
		System.out.println(pred.test(un) && pred2.test(pw) ? "注册成功" : "注册失败");
	}
}

  • and() or() negate()

Function<T,R>

  • R apply(T t)根据指定类型的数据转换为其他指定类型,返回其他指定类型
package com.qf.study;

import java.util.function.Function;

public class Study {
	public static void main(String[] args) {
		
		String stuInfo="迪丽热巴,12,女";
		Stu s1 = stuBuilder(s->new Stu(s.split(",")[0],Integer.valueOf(s.split(",")[1]),s.split(",")[2]), stuInfo);
		System.out.println(s1);
		//Stu [name=迪丽热巴, age=12, sex=女]
		
	}
	public static Stu stuBuilder(Function<String, Stu> f,String info) {
		return f.apply(info);
	}
}

class Stu{
	String name;
	int age;
	String sex;
	@Override
	public String toString() {
		return "Stu [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}
	public Stu(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	public Stu() {
		super();
	}
	
}

方法引用

使用条件
可以用lambda表达式的场景
必须有已存在对象和方法

使用方式
对象 : : 方法即可 简单替代 lambda表达式

package com.qf.study;

public class Study {
	public static void main(String[] args) {
		
		String name="张热巴";
		CN cn =new CN();
		System.out.println(checkName(cn::check, name));
		
	}
	public static boolean checkName(Check c,String name) {
		return c.check(name);
	}
}
interface Check{
	boolean check(String name);
}

class CN implements Check{

	@Override
	public boolean check(String name) {
		
		return name.length()>=3 && (name.charAt(0)+"").equals("张");
	}
	
}

适用场景
调用静态方法时(因为直接使用类对象调用即可)
调用构造函数时(如 类名::new ; int[]::new)

参数传递
自动按调用接口方法的时候的参数传递进行传递

	//函数式接口
	interface  A{
		void d(int b,int c);
	}
	//调用接口
	public static void e(A a,int b,int c){
		 a.d(b,c);
	}
	//方法引用
	public static void main(String[] args){
		int q =2;
		int p = 3;
		e(Math::pow,q,p);
		//自动按e方法中写的方式传递,q传递给b作为重写的接口的d方法的第一个参数,p传递给c作为第二个参数,结果是8
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值