2021-07-26Lambda 表达式、函数式接口

1.Lambda

1.1概述

Lambda表达式是一种没有名字的函数,也可称为闭包,是Java 8 发布的最重要新特性。

本质上是一段匿名内部类,也可以是一段可以传递的代码。

还有叫箭头函数的

1.2优点

是匿名内部类的简写方式,使代码更加简洁

1.3和匿名内部类对比

String[] strs = {"12","2","123","1"};
		// 转换为list
		List<String> strings = Arrays.asList(strs);
		// 匿名内部类
		Collections.sort(strings,new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				Integer i1 = Integer.valueOf(o1);
				Integer i2 = Integer.valueOf(o2);
				// 升序
				return i1 - i2;
			}
		});
		// 箭头函数
		Collections.sort(strings,(s1,s2)->{
			// 多条语句
			Integer i1 = Integer.valueOf(s1);
			Integer i2 = Integer.valueOf(s2);
			// 降序
			return i2 - i1;
		});

1.4语法结构

(参数,参数,参数...) -> {方法体}

1 无参和多参,小括号必须写

2 只有一个参数的时候,小括号可以不写

3 如果只有一条语句,大括号也可以不写,并且语句结尾不需要 分号

4 如果只有一条语句,并且也是返回值语句的话,return 也要省略

5 如果是多条语句,必须加{},就是正常编码,该写分号写分号,该写return就写return

1.5案例

public static void main(String[] args) {
		String[] strs = {"12","2","123","1"};
		// 转换为list
		List<String> strings = Arrays.asList(strs);
		// 匿名内部类
		Collections.sort(strings,new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				Integer i1 = Integer.valueOf(o1);
				Integer i2 = Integer.valueOf(o2);
				// 升序
				return i1 - i2;
			}
		});
		// 箭头函数
		Collections.sort(strings,(s1,s2)->{
			// 多条语句
			Integer i1 = Integer.valueOf(s1);
			Integer i2 = Integer.valueOf(s2);
			// 降序
			return i2 - i1;
		});
		System.out.println(strings);
	}
}
public static void main(String[] args) {
		Integer[] is = { 1, 4, 5, 2, 3, 7 };
		List<Integer> list = Arrays.asList(is);
		// 1.8之前写法
		Collections.sort(list, new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o2 - o1;
			}
		});
		// lambda写法
		Collections.sort(list, (x, y) -> x - y);
		System.out.println(list);
	}
}
public static void main(String[] args) {
		Integer[] is = { 1, 4, 5, 2, 3, 7 };
		List<Integer> list = Arrays.asList(is);
		// 1.8之前 常规写法
		for (Integer integer : list) {
			System.out.println(integer);
		}
		System.out.println("----");
		// 1.8 匿名内部类写法
		list.forEach(new Consumer<Integer>() {
			@Override
			public void accept(Integer t) {
				System.out.println(t);
			}
		});
		System.out.println("----");
		// 1.8 lambda写法
		list.forEach(x -> System.out.println(x));
	}
}

2.函数式接口

2.1概述

英文称为Functional Interface                   

其本质是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。                   

核心目标是为了给Lambda表达式的使用提供更好的支持,进一步达到函数式编程的目标,可通过运用函数式编程极大地提高编程效率。

其可以被隐式转换为 lambda 表达式。

2.2特点

函数式接口是仅制定一个抽象方法的接口                   

可以包含一个或多个静态或默认方法                   

专用注解即@FunctionalInterface 检查它是否是一个函数式接口,也可不添加该注解

如果有两个或以上 抽象方法,就不能当成函数式接口去使用,也不能添加@FunctionalInterface这个注解

如果只有一个抽象方法,那么@FunctionalInterface注解 加不加 都可以当做函数式接口去使用

2.3自定义

public static void main(String[] args) {
		// 子实现类的写法
		Test test = new Test();
		m1(test);
		// 匿名内部类
		m1(new MyFunction() {
			@Override
			public void print() {
				System.out.println("匿名内部类写法");
			}
		});
		// lambda写法
		m1(() -> System.out.println("lambda表达式写法"));
	}

	public static void m1(MyFunction function) {
		function.print();
	}
}

// 可以加也可以不加,
// 函数式接口中,只允许出现一个抽象方法,和N个非抽象方法
@FunctionalInterface
interface MyFunction {
	public void print();
}

class Test implements MyFunction {
	@Override
	public void print() {
		System.out.println("我是Test实现类");
	}
}

2.4JDK自带的函数式接口

Supplier : 表示供应商,有个get方法,无参,有返回值,一般用于获取数据

Consumer : 表示消费者,accept,有参,无返回值

Function ,函数操作, apply , 有参也有返回值

Predicate 断言,用于做判断校验操作,test,需要传入参数并返回boolean类型

3.方法、构造器、数组

3.1概述

Lambda表达式的另外一种形式

3.2方法引用

/**
 * 对象引用 :: 成员方法名
 * 
 * 
 */
public class FunCall_01 {
	public static void main(String[] args) {
		Integer i1 = 12;
		Supplier<String> supplier = i1::toString;
		System.out.println(supplier.get());
		System.out.println(i1.toString());
	}
}
**
 * 类名 :: 静态方法名
 * 
 
 */
public class FunCall_02 {
	public static void main(String[] args) {
		String string = "123";
		Function<String, Integer> function = Integer::parseInt;
		int value = function.apply(string);
		System.out.println(value);
	}
}
/**
 * 类名 :: 成员方法名
 * 
 
 */
public class FunCall_03 {
	public static void main(String[] args) {
		BiPredicate<String, String> predicate = String::equals;
		System.out.println(predicate.test("a", new String("a")));
	}
}

3.3构造器使用

public static void main(String[] args) {
		// 无参构造
		Supplier<Object> s1 = Object::new;
		System.out.println(s1.get());
		// 有参构造
		Function<String, String> f1 = String::new;
		System.out.println(f1.apply("zxc"));
	}
}

3.4数组引用

public static void main(String[] args) {
		// 泛型第一个是长度,第二个是返回值
		Function<Integer, Integer[]> fun = Integer[]::new;
		Integer[] arr = fun.apply(4);
		for (Integer integer : arr) {
			System.out.println(integer);
		}
	}
}

    4.Stream  API

4.1概述

 

数据渠道、管道,用于操作数据源(集合、数组等)所生成的元素序列。                 

集合讲的是数据,流讲的是计算

即一组用来处理数组,集合的API。

4.2特点

Stream 不是数据结构,没有内部存储,自己不会存储元素。                

Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。                  

Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。                

不支持索引访问。             

延迟计算            

支持并行                   

很容易生成数据或集合                  

支持过滤,查找,转换,汇总,聚合等操作。

4.3应用场景

流式计算处理,需要延迟计算、更方便的并行计算                   

更灵活、简洁的集合处理方式场景

4.4创建流的五种方式

public static void main(String[] args) {
		// 1 数组 , Stream.of
		String[] strings = {"a","b","c","d"};
		Stream<String> stream1 = Stream.of(strings);
		
		// 2 通过集合
		List<String> strings2  = Arrays.asList(strings);
		Stream<String> stream2 = strings2.stream();
		
		// 3 通过Stream.generate来创建
		// 创建一个无限流,里面全是1,并且通过limit 限制条数是5条
		Stream<Integer> generate = Stream.generate(()->1);
		generate.limit(5).forEach(x -> System.out.println(x));
		
		// 4 通过Stream.iterate来创建
		// 创建一个无限流,里面的数据有序,从2开始步长为3
		Stream<Integer> iterate = Stream.iterate(2, x->x+3);
		iterate.limit(5).forEach(x -> System.out.println(x));
		
		// 5 通过已有API
		String string = "abc";
		IntStream chars = string.chars();
		chars.forEach(x->System.out.println(x));
	}
}

4.5转换算子

4.5.1概述

转换算子,又称为 中间操作,所有的转换算子得到的都是一个新的流,所以一般用于链式调用
 * 常用的转换算子
 * limit : 取集合中的前几条数据
 * filter : 对元素进行过滤筛选,不符合条件的就不要了
 * distinct : 去除重复
 * skip : 跳过
 * map : 更改数据
 * sorted : 排序
 * 注意 : 只有转换算子,是不执行的,必须执行动作才会真正执行

4.5.3常用方法

public static void main(String[] args) {
		List<String> strings = Arrays.asList("a", "b", "c", "a");
		// 只要a
		Stream<String> stream = strings.stream();
		// collect 动作算子,把流中的数据转换为集合
		// filter 不符合条件的就不要了,返回false就是不要,true就是要
		List<String> value = stream.filter(x -> x.equals("a")).collect(
				Collectors.toList());
		System.out.println(value);
		// 不要偶数
		List<Integer> integers = Arrays.asList(1, 3, 5, 6, 8, 9, 11, 144, 25,
				257);
		Stream<Integer> stream1 = integers.stream();
		List<Integer> vaIue2 = stream1.filter(x -> x % 2 == 1).collect(
				Collectors.toList());
		System.out.println(vaIue2);

		// skip : 跳过元素
		stream1 = integers.stream();
		vaIue2 = stream1.skip(2).collect(Collectors.toList());
		System.out.println(vaIue2);
		
		
		// distinct : 去重
		stream = strings.stream();
		value = stream.distinct().collect(Collectors.toList());
		System.out.println(value);
		
		// map : 遍历过程中对元素进行操作,比如涨薪
		List<Double> sal = Arrays.asList(1152.2,2000.5,8888.8);
		Stream<Double> salStream  = sal.stream();
		List<Double> newSal  = salStream.map(x->x*10).collect(Collectors.toList());
		System.out.println(newSal);
		
		// limit 前几条,比如查看前两名
		salStream  = sal.stream();
		// sorted 进行排序 y-x 是降序 , x-y 是升序
		newSal = salStream.sorted((x,y)->{
			if(y>x){
				return 1;
			}else if (y == x) {
				return 0;
			}else{
				return -1;
			}
		}).limit(2).collect(Collectors.toList());
		System.out.println(newSal);
	}
}

4.6动作算子

public static void main(String[] args) {
		List<String> strings = Arrays.asList("a", "b", "c", "a");
		// 只要a
		Stream<String> stream = strings.stream();
		// collect 动作算子,把流中的数据转换为集合
		// filter 不符合条件的就不要了,返回false就是不要,true就是要
		List<String> value = stream.filter(x -> x.equals("a")).collect(
				Collectors.toList());
		System.out.println(value);
		// 不要偶数
		List<Integer> integers = Arrays.asList(1, 3, 5, 6, 8, 9, 11, 144, 25,
				257);
		Stream<Integer> stream1 = integers.stream();
		List<Integer> vaIue2 = stream1.filter(x -> x % 2 == 1).collect(
				Collectors.toList());
		System.out.println(vaIue2);

		// skip : 跳过元素
		stream1 = integers.stream();
		vaIue2 = stream1.skip(2).collect(Collectors.toList());
		System.out.println(vaIue2);
		
		
		// distinct : 去重
		stream = strings.stream();
		value = stream.distinct().collect(Collectors.toList());
		System.out.println(value);
		
		// map : 遍历过程中对元素进行操作,比如涨薪
		List<Double> sal = Arrays.asList(1152.2,2000.5,8888.8);
		Stream<Double> salStream  = sal.stream();
		List<Double> newSal  = salStream.map(x->x*10).collect(Collectors.toList());
		System.out.println(newSal);
		
		// limit 前几条,比如查看前两名
		salStream  = sal.stream();
		// sorted 进行排序 y-x 是降序 , x-y 是升序
		newSal = salStream.sorted((x,y)->{
			if(y>x){
				return 1;
			}else if (y == x) {
				return 0;
			}else{
				return -1;
			}
		}).limit(2).collect(Collectors.toList());
		System.out.println(newSal);
	}
}

          

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值