【Java】Java基础之Lambda表达式和Stream流

目录

Lambda表达式

函数式接口

1、Supplier

2、Consumer

3、Predicate

4、Function

Stream流

Stream流的获取方式:

常用方法:


Lambda表达式

        Lambda表达式,也可以称为闭包,是Java8的重要特性。使用Lambda表达式可以是代码变得更加简洁紧凑。

   Lambda的格式:三个部分:

        1)一些参数          2)一个箭头          3)一些代码

标准格式:

         (参数)->{一些代码};

省略规则

  • 小括号中的参数数据类型可以直接省略

  • 如果小括号中只有一个参数,小括号可以直接省略

  • 如果大括号中只有一句代码,不管有没有返回值,可以同时省略return关键字,大括号以及分号。

// 1. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

// 2. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y 
  
// 4. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x 

// 5. 不需要参数,返回值为 
() -> 5  

使用lambda表达式的前提:

       1)使用lambda必须具有接口并且要求有且仅有一个抽象方法              无论是JDK内置的Runnable,Comparator接口还是自定义接口,只有当接口中的抽象方法存在且唯一是时才可以使用Lambda

        2)使用lambda表达式必须具有上下文推断                 即方法的参数或局部变量类型必须为lambda对应的接口类型,才能使用Lambda作为接口的实例 

        如果一个接口他的抽象方法只有一个,这个接口就叫做函数式接口(和其他非抽象方法无关)。如果不清楚这个是否为函数式接口,可以使用注解@FunctionalInterface检查当前接口是否为函数式接口

函数式接口

接下来介绍四种常见的函数式接口。

1、Supplier<T>

1)java.util.function.Supplier<T>:接口仅包含一个无参的方法,T get():用来获取一个泛型参数执行类型的对象数据,由于此接口是一个函数式接口,即对应的Lambda表达式需要提供一个符合泛型类型的对象的数据。

     此接口是一个生产型接口,指定接口的泛型是一个什么类型,那么接口中的get方法就会产生什么类型的数据

public class DemoSupplier {
    public static void main(String[] args) {
        //调用getString方法,方法参数supplier是一个函数式接口,所以可以传递lambda表达式
        String s=getString(()-> {
            //生产一个字符串,并返回
            return "James";
        });
        String s1 = getString(()->"Jerry");
        System.out.println(s);
        System.out.println(s1);
    }
    //定义一个方法,方法的参数 传递supplier<T>接口,泛型执行string,get方法就会返回一个string
    public  static  String getString(Supplier<String>supplier){
        return supplier.get();
    }
}

2、Consumer<T>

        java.util.function.Consumer<T>:此接口正好与Supplier接口相反,Supplier是一个生产数据的接口,而Consumer是一个消费数据的接口,其数据类型也由泛型决定。

        Consumer接口中包含抽象方法void accept(T t),意为消费一个指定泛型的数据

public class DemoConsumer {
    public static void main(String[] args) {
        //调用method犯法,传递字符串姓名,方法的另一个参数是Consumer接口,
        //是一个函数式接口,所以可以传递Lambda表达是
        method("James", (String name)->{
            //对传递的字符串进行消费
            //消费方式:直接输出字符串
            System.out.println (name);
            //翻转字符串
            String reName=new StringBuffer(name).reverse().toString();
            System.out.println( reName);
        });
    }
    public static void method(String name, Consumer<String>con){
        con.accept(name);
    }
}

3、Predicate<T>

java.util.function.Predicate<T>接口:用于对某种类型进行判断,从而得到一个boolean值,Predicate接口中包含一个抽象方法:boolean  test(T t).

public class DemoPredicate {
    public static void main(String[] args) {
        //定义一个字符串
        String s = "abcdefg";
        //调用checkstring方法对字符串进行校验,参数传递字符串和lambda表达式
        boolean b = checkString(s, (str) ->
                //对参数进行传递的字符串进行判断,判断字符串的长度是否大于5,并把判断的结果返回
                str.length() > 7);
        System.out.println(b);
    }

    public static boolean checkString(String s, Predicate<String> predicate) {
        return predicate.test(s);
    }
}

4、Function<T>

       java.util.function.Function<T   R>:该接口是用来根据一个类型的数据得到拎一个类型的数据,前者称之为前置条件,后者称之为后置条件。

        Function接口中最主要的抽象方法是R apply(T   t),根据类型T大的参数获取类型R的接口

public class DemoFunction {
    public static void main(String[] args) {
        //定义一个字符串类型整数
        String s="124";
        //调用change方法,传递字符串类型的整数和lambda表达式
        change(s,(str)->Integer.parseInt(s));
    }
    public static void change(String s,Function<String,Integer> function){
        int in=function.apply(s);
        System.out.println(in);
    }
}

Stream流

       Stream流用于解决已有集合类库的既有的弊端。Stream流得益于Lambda的功能,因为有了Lambda表达式才有了Stream流

Stream流的获取方式:

1)Collection单列集合:集合.stream()

2)数组:  Stream.of(数组)

3)Map双列集合:

        集合.keySet().stream()            ---》j键

        集合.values().stream()            ---》值

package com.itheima_06;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

public class Test01 {
    public static void main(String[] args) {
        //把集合和数组转化成Stream流

        //单列集合
        ArrayList<Integer> list = new ArrayList<>();
        list.add(123);
        list.add(456);
        list.add(789);

        //把单列集合转化成Stream流
        Stream<Integer> stream1 = list.stream();
        
        
        //双列集合(扩展)
        //双列集合不能转成Stream,需要把键和值单独转化
        Map<Integer,String> map = new HashMap<>();
        map.put(1,"柳岩");
        map.put(2,"张三");
        
        //把双列集合转成Stream流
        //键
        Stream<Integer> stream2 = map.keySet().stream();
        //值
        Stream<String> stream3 = map.values().stream();
        
        //数组
        Integer[] arr = {11,22,33,44};

        Stream<Integer> stream4 = Stream.of(arr);
    }
}

常用方法:

1、终结方法:意味着调用之后就不能再调用流的其他方法了。

  • count():返回流中元素的个数
  • forEach():遍历元素---》forEach传递的参数就是Consumer<T>接口
//forEach使用
public class Demo01 {
    public static void main(String[] args) {
        //创建list集合
        List<String >list = new ArrayList<>();
        Collections.addAll(list,"张三丰","王思聪","张飞","刘晓敏","张靓颖");
        //使用stream流打印数据
        Stream<String> stream = list.stream();
        stream.forEach(s-> System.out.println(s));
    }
}

//count使用
public class Demo03 {
    public static void main(String[] args) {
        //创建list集合
        List<String > list = new ArrayList<>();
        Collections.addAll(list,"张三丰","王思聪","张飞","刘晓敏","张靓颖");
        //使用stream流打印数据
        Stream<String> stream = list.stream();
        //筛选所有“张"姓学员
        long l = stream.filter(s -> s.startsWith("张")).count();
        System.out.println("张姓学员为"+l+"个");
    }
}

非终结方法:指stream流调用之后可以继续调用流的其他方法

  • filter():过滤方法   ----》filter传递的参数是Predicate接口
  • limit():取用前几个
  • skip():跳过前几个
  • map():映射方法,可以把元素从一种类型转成另一种类型  ----》map传递的接口是Function接口
  • static  concat():把两个stream流合并成一个Stream
public class Demo02 {
    public static void main(String[] args) {
        //创建list集合
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "张三丰", "王思聪", "张飞", "刘晓敏", "张靓颖");
        //使用stream流打印数据
        Stream<String> stream = list.stream();
        stream.filter(s -> s.startsWith("张")).forEach(s ->System.out.println(s));
    }
}


public class Demo04 {
    public static void main(String[] args) {
        //创建list集合
        List<String > list = new ArrayList<>();
        Collections.addAll(list,"张三丰","王思聪","张飞","刘晓敏","张靓颖","王敏");
        //使用stream流打印数据
        Stream<String> stream = list.stream();
        //筛选集合中所有张姓学员
        stream.filter(s->s.startsWith("张")).limit(2).forEach(s-> System.out.println(s));
        System.out.println("=============================");
        //重新获取stream流
        Stream<String>stream1= list.stream();
        //筛选所有王姓人员
        stream1.filter(s->s.startsWith("王")).skip(1).forEach(s-> System.out.println(s));
    }
}



public class Demo05 {
    public static void main(String[] args) {
        //创建list集合
        List<String > list = new ArrayList<>();
        Collections.addAll(list,"张三丰","王思聪","张飞","刘晓敏","张靓颖","王敏");
        //使用stream流打印数据
        Stream<String> stream = list.stream();
        //使用map()方法将每个元素封装为一个Person对象(创建一个Person类,name属性)
        List<Person> collect = stream.map(s -> new Person(s)).collect(Collectors.toList());
        System.out.println(collect);
    }
}


public class Demo05 {
    public static void main(String[] args) {
        //创建list集合
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "张三丰", "王思聪", "张飞", "刘晓敏", "张靓颖", "王敏");
        //使用stream流打印数据
        Stream<String> stream = list.stream();
        //筛选集合中所有张姓学员
        stream = stream.filter(s -> s.startsWith("张"));
        System.out.println("=============================");
        //重新获取stream流
        Stream<String> stream1 = list.stream();
        //筛选所有王姓人员
        stream1 = stream1.filter(s -> s.startsWith("王"));
        //合并流
        Stream<String> stream2 = Stream.concat(stream, stream1);
        stream2.forEach(s -> System.out.println(s));
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43267344/article/details/108095511