Lambda表达式是一种没有名字的函数,也可称为闭包,是Java 8 发布的最重要新特性。
本质上是一段匿名内部类,也可以是一段可以传递的代码。
闭包的本质就是将函数内部和函数外部链接起来的桥梁
1、(parameters) -> expression
2、(parameters) ->{ statements; }
// 1. 不需要参数,返回值为 5 () -> 5 // 2. 接收一个参数(数字类型),返回其2倍的值 x -> 2*x // 3. 接受2个参数(数字),并返回他们的差值 (x, y) -> x – y // 4. 接收2个int型整数,返回他们的和 (int x, int y) -> x + y // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) (String s) -> System.out.print(s)
public static void main(String[] args) { String[] arr = { "one", "two", "three" }; List<String> list = Arrays.asList(arr); // jdk1.7-老版写法 for (String ele : list) { System.out.println(ele); } System.out.println("---"); // jdk1.8-新版写法 list.forEach(x -> { System.out.println(x); }); // 就类似于这种写法,相当于自己创建了一个方法,然后遍历调用这个方法 // 把 集合中每个元素作为参数传递进去,并打印参数 for (String string : list) { m1(string); } } public static void m1(String x) { System.out.println(x); }
public static void main(String[] args) { Integer[] arr = { 9, 8, 10, 1, 3, 5 }; // 把数组转换为list List<Integer> list = Arrays.asList(arr); // jdk1.7-旧版写法,使用比较器进行排序 list.sort(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1 - o2; } }); System.out.println(list); // jdk1.8-新版写法 // 把数组转换为list list = Arrays.asList(arr); list.sort((x, y) -> x - y); System.out.println(list); }
其本质是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
核心目标是为了给Lambda表达式的使用提供更好的支持,进一步达到函数式编程的目标,可通过运用函数式编程极大地提高编程效率。
函数式接口是仅制定一个抽象方法的接口
可以包含一个或多个静态或默认方法
专用注解即@FunctionalInterface 检查它是否是一个函数式接口,也可不添加该注解
如果有两个或以上 抽象方法,就不能当成函数式接口去使用,也不能添加@FunctionalInterface这个注解
如果只有一个抽象方法,那么@FunctionalInterface注解 加不加 都可以当做函数式接口去使用
简单来说就是回调函数,方法的参数是一个方法,在这个方法中对传递的方法进行调用
//无参情况 public class FunInterface_01 { // 自定义静态方法,接收接口对象 public static void call(MyFunctionInter func) { // 调用接口内的成员方法 func.printMessage(); } public static void main(String[] args) { // 第一种调用 : 直接调用自定义call方法,传入函数 FunInterface_01.call(() -> { System.out.println("HelloWorld!!!"); }); // 第二种调用 : 先创建函数对象,类似于实现接口的内部类对象 MyFunctionInter inter = () -> { System.out.println("HelloWorld2!!!!"); }; // 调用这个实现的方法 inter.printMessage(); } } // 函数式接口 @FunctionalInterface interface MyFunctionInter { void printMessage(); } //有参情况 public class FunInterface_02 { // 自定义静态方法,接收接口对象 public static void call(MyFunctionInter_02 func, String message) { // 调用接口内的成员方法 func.printMessage(message); } public static void main(String[] args) { // 调用需要传递的数据 String message = "有参函数式接口调用!!!"; // 第一种调用 : 直接调用自定义call方法,传入函数,并传入数据 FunInterface_02.call((str) -> { System.out.println(str); }, message); // 第二种调用 : 先创建函数对象,类似于实现接口的内部类对象 MyFunctionInter_02 inter = (str) -> { System.out.println(str); }; // 调用这个实现的方法 inter.printMessage(message); } } // 函数式接口 @FunctionalInterface interface MyFunctionInter_02 { void printMessage(String message); }
无输入只返回值
public class _03_JdkOwn_01 { private static String getResult(Supplier<String> function) { return function.get(); } public static void main(String[] args) { // 1 String before = "张三"; String after = "你好"; // 把两个字符串拼接起来 System.out.println(getResult(() -> before + after)); // 2 //创建Supplier容器,声明为_03_JdkOwn类型 // 此时并不会调用对象的构造方法,即不会创建对象 Supplier<_03_JdkOwn_01> sup = _03_JdkOwn_01::new; _03_JdkOwn_01 jo1 = sup.get(); _03_JdkOwn_01 jo2 = sup.get(); } public _03_JdkOwn_01() { System.out.println("构造方法执行了"); } }
只有输入无返回
public class _04_JdkOwn_02 { private static void consumeResult(Consumer<String> function, String message) { function.accept(message); } public static void main(String[] args) { // 传递的参数 String message = "消费一些内容!!!"; // 调用方法 consumeResult(result -> { System.out.println(result); }, message); } }
既有输入也有输出
public class _05_JdkOwn_03 { // Function<参数, 返回值> public static void convertType(Function<String, Integer> function, String str) { int num = function.apply(str); System.out.println(num); } public static void main(String[] args) { // 传递的参数 String str = "123"; // s是说明需要传递参数, 也可以写 (s) convertType(s -> { int sInt = Integer.parseInt(s); return sInt; }, str); } }
断言,有输入,但输出只能是布尔类型。
public class _06_JdkOwn_04 { // 自定义方法,并且 Predicate 接收String字符串类型 public static void call(Predicate<String> predicate, String isOKMessage) { boolean isOK = predicate.test(isOKMessage); System.out.println("isOK吗:" + isOK); } public static void main(String[] args) { // 传入的参数 String input = "ok"; call((String message) -> { // 不区分大小写比较,是ok就返回true,否则返回false if (message.equalsIgnoreCase("ok")) { return true; } return false; }, input); } }
public static void main(String[] args) { Integer intObj = new Integer(123456); // 常规lambda写法 Supplier<String> su = () -> intObj.toString(); System.out.println(su.get()); // 方法引用写法 Supplier<String> su1 = intObj::toString; System.out.println(su1.get()); }
public static void main(String[] args) { // 常规lambda写法 // 前两个泛型是参数类型,第三个是返回值类型 BiFunction<Integer, Integer, Integer> bi = (x, y) -> Integer.max(x, y); int apply = bi.apply(10, 11); System.out.println(apply); // 方法引用写法 BiFunction<Integer, Integer, Integer> bif = Integer::max; int apply2 = bif.apply(10, 11); System.out.println(apply2); }
public static void main(String[] args) { // 常规lambda写法 // 两个泛型都是参数类型 BiPredicate<String, String> predicate = (x, y) -> x.equals(y); System.out.println(predicate.test("a", "a")); // 方法引用写法 // 使用第一个参数调用成员方法把第二个参数传入 // ::前面的类型 要和 第一个参数的类型一致 BiPredicate<String, String> predicate2 = String::equals; System.out.println(predicate2.test("a", "b")); }
public static void main(String[] args) { // 无参构造器 // 常规lambda写法 Supplier<Object> objSup = () -> new Object(); System.out.println(objSup.get()); // 方法引用写法 Supplier<Object> s1 = Object::new; System.out.println(s1.get()); // 有参构造器 // 常规lambda写法 Function<String, Integer> func = (x) -> new Integer(x); System.out.println(func.apply("123456")); // 方法引用写法 Function<String, Integer> func2 = Integer::new; System.out.println(func2.apply("123456")); }
public static void main(String[] args) { // lambda传统写法 Function<Integer, Integer[]> fun = (n) -> new Integer[n]; Integer[] intArray1 = fun.apply(5); intArray1[0] = 100; System.out.println(intArray1[0]); // 数组引用新写法 Function<Integer, Integer[]> fun1 = Integer[]::new; Integer[] intArray = fun1.apply(5); intArray[0] = 100; System.out.println(intArray[0]); }
数据渠道、管道,用于操作数据源(集合、数组等)所生成的元素序列。
集合讲的是数据,流讲的是计算
即一组用来处理数组,集合的API。
Stream 不是数据结构,没有内部存储,自己不会存储元素。
Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
不支持索引访问。
延迟计算
支持并行
很容易生成数据或集合
支持过滤,查找,转换,汇总,聚合等操作。
Stream分为源source,中间操作,终止操作。
流的源可以是一个数组,集合,生成器方法,I/O通道等等。
一个流可以有零个或多个中间操作,每一个中间操作都会返回一个新的流,供下一个操作使用,一个流只会有一个终止操作。
中间操作也称为转换算子-transformation
Stream只有遇到终止操作,它的数据源会开始执行遍历操作。
终止操作也称为动作算子-action
因为动作算子的返回值不再是 stream,所以这个计算就终止了
只有碰到动作算子的时候,才会真正的计算
public static void main(String[] args) { // 1 通过数组,Stream.of() String[] str = { "a", "b", "c" }; Stream<String> str1 = Stream.of(str); // System.out.println(str1); // 2 通过集合 List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream(); System.out.println(stream); // 3 通过Stream.generate方法来创建 // 这是一个无限流,通过这种方法创建在操作的时候最好加上limit进行限制 Stream<Integer> generate = Stream.generate(() -> 1); generate.limit(10).forEach(x -> System.out.println(x)); // 4 通过Stream iterate Stream<Integer> iterate = Stream.iterate(1, x -> x + 2); iterate.limit(100).forEach(x -> System.out.println(x)); // 5 通过集合等数据源生成 String string = "ABCD"; IntStream intStream5 = string.chars(); intStream5.forEach(x -> System.out.println(x)); }
常用转换算子 filter,distinct,map,limit,skip,flatMap等
filter : 对元素进行过滤筛选,不符合的就不要了
distinct : 去掉重复的元素
skip : 跳过多少元素
limit : 取一个集合的前几条数据
map :
可以理解是在遍历集合的过程中,对元素进行操作,比如判断集合元素是否是a 返回boolean
因为 map的返回值,就是新集合中的元素,所以也可以在遍历的时候对集合的数据进行更改,比如都加 –
flatMap :
解决一个字符串数组 返回单一的字符串使用flatMap
本来集合中有两个数组,可以通过flatMap 把数组中的每一个元素都放到集合中,然后把数组去掉
**注意只用此算子是不会真正进行计算的,只有后边调用动作算子才会真正计算。**
循环 forEach
计算 min、max、count、average
匹配 anyMatch、allMatch、noneMatch、findFirst、findAny
汇聚 reduce
收集器 collect