Spring Webflux

预备知识:

函数式编程,就是充分利用已经写好的函数,重点在于如何用这些函数实现功能

传统的命令式编程,就是要思考如何用一行行的代码实现功能

可以这样理解,传统的命令式编程就是在用代码实现函数功能,函数式编程是直接调用函数实现功能。

例子:命令式编程:通过for循环进行累加求和,这样就是去实现了求和的逻辑

函数式编程:直接通过excel的求和工具一步到位,不用关注求和的细节

函数式编程首先要了解lambda表达式,可以让代码更加简短。

Lambda表达式

实例:

匿名内部类省去了创建类的过程,而lambda表达式可以使这一过程更加简洁

public static void main(String args[]) {
    new Thread(){
        @Override
        public void run() {
            System.out.pringln("OK");
        }
    }.start();
    或
    new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println("ok");
            }
        }).start();
}

使用lambda表达式:
public static void main(String args[]) {
    new Thread(()-> System.out.println("ok")).start();
    
}

lambda本质是一个函数接口,用于快捷的创建一个接口实例并实现接口方法

表达式为:
()-> 方法

等价于
public class A implements B(){
    @Override
    public void kk() {
        。。。;
    }
}

 有几个注意事项:

①lambda仅适用于只有一个需要重写方法的接口,这种接口也可称为函数式接口,如果有多个方法需要重写,就不能明确lambda表达式所编写的方法是重写的哪一个方法,只有一个需要重写方法的概念用下面的例子解释

下例中,虽然接口A有两个方法,但是仅有一个write方法需要重写,read为default方法不需要重写,所以A接口仍然可以用lambda表达式实现。

public class test {
    public static void main(String[] args) {
        A a = ()-> System.out.println("write");
        a.read();
        a.write();
    }
}

//对于函数式接口,可以加上@FunctionalInterface 加以标注,以表示其为一个函数式接口
@FunctionalInterface
interface A {
    public void write();
    default void read(){
        System.out.println("read");
    }
}

②lambda表达式实际返回的是实现接口的实例,所以必须用函数接口接收lambda表达式返回值

上例中,如果使用
Object a = ()-> System.out.println("write");
则会报错,因为Object并不是一个函数接口
可以强转类型解决
Object a = (A)()-> System.out.println("write");

以实现Runnable接口为例:
public class test {
    public static void main(String[] args) {
        Object r = (Runnable) ()-> System.out.println("run");
        Thread t = new Thread((Runnable)r);//传入的r也需要转换为Runnable类型
        t.start();
    }
}

下面介绍实现方法有参数的情况 该如何编写lambda表达式:

public class test {
    public static void main(String[] args) {
        //如果参数只有一个可以不写括号
        A a = (i, str)-> System.out.println(i + str);
        a.write(10,"strstr");
        //如果实现的方法体中有多行代码就需要加上{}
        A a = (i, str)-> {
            System.out.println(i + str);
            System.out.println("aa");
        };
        //方法有返回值,如果代码仅有一行 可以省略return,直接写返回值
        B b1 = (i, str)-> i * 2;
        System.out.println(b.read(20, "read"));
        //方法有返回,且有多行
        B b = (i, str)-> {
            System.out.println(str);
            return 2;
        };
        b.read(2, "read");
    }
}

interface A {
    public void write(int i,String str);
}
interface B {
    public int read(int i, String str);
}

Jdk1.8的函数接口

使用lambda表达式可以很快捷的创建接口实例,但是对于一个函数接口,我们更关注接口方法实现什么样的功能,关注接口内函数的输入和输出,而不必关注接口叫什么名字,因此可以考虑是否可以不创建接口就得到一个接口的实例!

jdk1.8提供了很多函数接口,不需要定义特定的接口,只需要创建出具备输入输出的函数就可以

public static void main(String[] args) {
        //创建了一个接口实例a,所实现的方法是输入一个Integer类型的参数
        //输出为一个String类型的参数
        Function<Integer, String> a = (i)-> "aaa" + i;
        //使用apply方法调用所实现的接口方法
        String apply = a.apply(4);
        System.out.println(apply);
    }

//

Function<T, R> 可以用于创建一个输入为T类型,输出为R类型的函数

Customer<T> 用于创建一个有输入没输出的函数,消费者函数接口

Supplier<T> 用于创建一个有输出没输入的函数,生产者函数接口

参照上表以此类推

方法引用

 若Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用,即Lambda的另外一种表现形式。方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致。

①  对象引用::实例方法名

@Test
public void testT1() {
	// 创建一个User类,属性为name和age
	User user = new User("LCY", 22);
	// Lambda表达式
	Supplier<String> sup1 = () -> user.getName();
	System.out.println(sup1.get());
	// 方法引用方式
	Supplier<Integer> sup2 = user::getAge;
	System.out.println(sup2.get());
}

②类名::静态方法名

@Test 
public void testT2() {
	Comparator<Integer> com1 = (x,y) -> Integer.compare(x, y);
	System.out.println(com1.compare(1, 2));
	Comparator<Integer> com2 = Integer::compare;
	System.out.println(com2.compare(7, 6));
}

③类名::实例方法名

@Test
public void testT3() {
	BiPredicate<String, String> bp1 = (x,y) -> x.equals(y);
	System.out.println(bp1.test("abcd", "dcba"));
	// 参数1是调用equals的,参数2是equals方法的参数
	// 因此可以使用类名::方法名
	BiPredicate<String, String> bp2 = String::equals;
	System.out.println(bp2.test("123", "123"));
}

 类型判断:

package lambda;

@FunctionalInterface
interface IMath {
	int add(int x, int y);
}

@FunctionalInterface
interface IMath2 {
	int sub(int x, int y);
}


public class TypeDemo {

	public static void main(String[] args) {
		// 变量类型定义
		IMath lambda = (x, y) -> x + y;

		// 数组里
		IMath[] lambdas = { (x, y) -> x + y };

		// 强转
		Object lambda2 = (IMath) (x, y) -> x + y;
		
		// 通过返回类型
		IMath createLambda = createLambda();
		
		TypeDemo demo = new TypeDemo();
		// 当有方法重写,存在二义性的时候,使用强转对应的接口解决
		demo.test( (IMath2)(x, y) -> x + y);
	}
	
	public void test(IMath math) {
		
	}
	
	public void test(IMath2 math) {
		
	}
	
	public static IMath createLambda() {
		return  (x, y) -> x + y;
	}

}

Jdk8 新特性Stream流编程 

概念:通过Stream流的方法实现更高级的特性

外部迭代 和 内部迭代

实现数组内数字的累加
外部迭代:
int[] nums = {1, 2, 3};
int sum = 0;
for (int num :nums) {
    sum += num;
}

内部迭代:
int sum = IntStream.of(nums).sum();
通过流实现的方法更快捷的实现一些需求

中间操作/终止操作,惰性求值

int sum2 = IntStream.of(nums).map(i-> i * 2).sum();

System.out.println(sum2);

map就是一个中间操作返回一个Stream操作, sum就是一个终止操作,返回一个结果


public static void main(String[] args) {
        int[] nums = {1, 4, 3};

        IntStream intStream = IntStream.of(nums).map(i -> i * 2);
        System.out.println(intStream.sum());
    }

返回流的是中间操作,  返回结果的是终止操作

使用Stream操作的步骤:

①创建流

public static void main(String[] args) {
		List<String> list = new ArrayList<>();

		// 从集合创建
		list.stream();
		list.parallelStream();//并行流

		// 从数组创建
		Arrays.stream(new int[] { 2, 3, 5 });

		// 创建数字流
		IntStream.of(1, 2, 3);
		IntStream.rangeClosed(1, 10);

		// 使用random创建一个无限流
		new Random().ints().limit(10);
		Random random = new Random();

		// 自己产生流
		Stream.generate(() -> random.nextInt()).limit(20);

	}

②中间操作:

 ③终止操作

 分为短路和非短路操作

短路操作:需要将整个流执行完,返回一个最终结果

短路操作:在执行流的过程中找到符合条件的结果并返回

并行流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Meikesibondwell

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值