Java8新特性之Lambda表达式、函数式接口、Stream API(笔记)

1、Lambda表达式

Lambda是java8的新特性,使用Lambda可以替代只有一个抽象方法的接口(函数接口)实现,类似于匿名内部类。

1.1 、Lambda的语法格式

()-> {}
  • (): 用来描述参数列表。
  • {}:用来描述方法体、执行语句,当只有一条执行语句或只有返回值的时候可以省略。
  • -> :Lambda运算符

1.2、Lambda基本语法实例
创建多个接口

public interface LambdaInterface {
    int test1();
}

@FunctionalInterface
public interface LambdaInterface1 {
    int test2(int a);
}

@FunctionalInterface
public interface LambdaInterface2 {
   int test3(int a,int b);
}

@FunctionalInterface
public interface LambdaInterface3 {
    void test4();
}

@FunctionalInterface
public interface LambdaInterface4 {
  void test5(int a);
}


@FunctionalInterface
public interface LambdaInterface5 {
   void test6(int a,int b);
}

测试类

public class LambdaTest {
    public static void main(String[] args) {
        /**
         * 无参数,有返回值
         */

        //LambdaInterface test = () ->{return 200;};
        LambdaInterface test = () -> 200;
        int i2 = test.test1();
        System.out.println(i2);
        /**
         * 有单个参数,有返回值
         */
        //LambdaInterface1 test2 = (int a) ->{return a;};
        LambdaInterface1 test2 = a -> a;
        int i3 = test2.test2(200);
        System.out.println(i3);
        /**
         * 有多个参数,有返回值
         */
        //LambdaInterface2 test3 =(int a ,int b) -> {return a-b;};
        LambdaInterface2 test3 =(a,b) -> a-b;
        int i = test3.test3(20, 1);
        System.out.println(i);
        /**
         * 有参数,无返回值
         */
       // LambdaInterface4 test4 = a -> {System.out.println(a);};
        LambdaInterface4 test4 = a -> System.out.println(a);
        test4.test5(12);
        /**
         * 有多个参数,无返回值
         */
        //LambdaInterface5 test5 = (a, b) ->{System.out.println("a="+a+"  b="+b);};
        LambdaInterface5 test5 = (a, b) -> System.out.println(a+b);
        test5.test6(12,24);
        /**
         * 无参数,无返回值
         */
        LambdaInterface3 test6 = () -> System.out.println("无参数,无返回值!");
        test6.test4();
    }

}

输出结果
在这里插入图片描述
1.3、Lambda的方法引用

方法引用:若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用(可以理解为方法引用是Lambda表达式的另一种表现形式)
主要有三种语法格式:
对象::实例化方法名
类::静态方法名
类::实例方法名
注意:1、Lambda体中调用方法的参数列表于返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!
2、若Lambda参数列表中的第一参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以ClassName::method

  //对象::实例方法名
    @Test
    public  void test1(){
        //Consumer<String> con1 =(x) -> System.out.println(x);
        Consumer<String> con = System.out::println;
        con.accept("adcdef");
    }
    //类::静态方法名
    @Test
    public void test2(){
      //Comparator<Integer> com = (x ,y) ->Integer.compare(x,y);

      Comparator<Integer> com1 = Integer::compare;
    }
    //类::实例方法名
    @Test
    public void test3(){
        //BiPredicate<String,String> bp =(x,y) -> x.equals(y);
        BiPredicate<String,String> bp =String::equals;
    }
    //数组引用
    @Test
    public void test4(){
        //Function<Integer,String[]> fun =(x) ->new String[x];
        Function<Integer,String[]> fun = String[]::new;
        String[] strs = fun.apply(10);
        System.out.println(strs.length);
    }

}

输出结果
在这里插入图片描述
1.4、方法引用(构造函数)
创建实体类

public class Person {
    public String name;
    public int age;

    public Person(){
        System.out.println("这是无参构造方法");
    }
    public Person(String name,int age){
        System.out.println("这里是有参构造");
        this.name=name;
        this.age=age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

创建接口

interface LambdaInterfaceTest{
    Person getPerson();
}
interface LambdaInterfaceTest1{
    Person getPerson(String name,int age);
}

测试类


public class LambdaTest2 {
    public static void main(String[] args) {
        LambdaInterfaceTest test = ()-> new Person();
        test.getPerson();
        //构造方法的引用
        LambdaInterfaceTest test1 = Person::new;
        test1.getPerson();
        LambdaInterfaceTest1 test11 =Person::new;
        test11.getPerson("lzf",12);

    }
}

输出结果
在这里插入图片描述

2、函数式接口

1、Lambda表达式使用前提,接口必须是一个函数接口
2、函数式接口(FunctionalInterface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
3、函数式接口可以被隐式转换为 lambda 表达式。
4、 Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上
5、使用注解@FunctionalInterface

四大内置核心函数接口

public class Lambda5 {
    //Supplier<T>
    @Test
    public void test1(){
        List<Integer> numList = getNumList(10, () -> (int) (Math.random() * 100));
        for (Integer n:numList) {
            System.out.print(n+" ");
        }
    }
    //需求:产生指定个数的整数,并放入集合中
    public List<Integer> getNumList(int num, Supplier<Integer> sup){
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            Integer n = sup.get();
            list.add(n);
        }
        return list;

    }
    @Test
    //Predicate<T>
    public void test2(){
        List<String> list = Arrays.asList("kzf","sdad","sdada","hwidh");
        List<String> strings = filterStr(list, (s -> s.length() > 3));
        for (String a:strings) {
             System.out.print(a+" ");
        }
    }
    //将满足条件的字符串,放入集合中
    public List<String> filterStr(List<String> list, Predicate<String> pre){
        List<String> list1 = new ArrayList<>();
        for (String a: list) {
            if(pre.test(a)){
                list1.add(a);
            }
        }
        return list1;
    }
    //Consumer<T> :处理字符串
    @Test
    public void test3(){
        nihao("dci",(m)-> System.out.println("你好"+m));
    }
    public void nihao(String name, Consumer<String> con){
        con.accept(name);
    }

    //Function<T,R>函数型接口:
    @Test
    public void test4(){
        String s = strHandler("\t\t\t你好我他", (str) -> str.trim());
        System.out.println(s);

    }
    public String strHandler(String str, Function<String,String> fun){
        return fun.apply(str);
    }
}

输出结果

1、22 30 82 84 54 49 62 38 55 2
2、sdad sdada hwidh
3、你好dci
4、你好我他

系统内置的一些函数式接口

public class FunctionalInterface {
    public static void main(String[] args) {

        // Predicate<T>              :     参数是T 返回值boolean  
        // 在后续如果一个接口需要指定类型的参数,返回boolean时可以指向 Predicate
        //          IntPredicate            int -> boolean
        //          LongPredicate           long -> boolean
        //          DoublePredicate         double -> boolean

        // Consumer<T>               :      参数是T 无返回值(void)
        //          IntConsumer             int ->void
        //          LongConsumer            long ->void
        //          DoubleConsumer          double ->void

        // Function<T,R>             :      参数类型T  返回值R
        //          IntFunction<R>          int -> R
        //          LongFunction<R>         long -> R
        //          DoubleFunction<R>       double -> R
        //          IntToLongFunction       int -> long
        //          IntToDoubleFunction     int -> double
        //          LongToIntFunction       long -> int
        //          LongToDoubleFunction    long -> double
        //          DoubleToLongFunction    double -> long
        //          DoubleToIntFunction     double -> int

        // Supplier<T> : 参数 无 返回值T
        // UnaryOperator<T> :参数T 返回值 T
        // BiFunction<T,U,R> : 参数 T、U 返回值 R
        // BinaryOperator<T> :参数 T、T 返回值 T
        // BiPredicate<T,U> :  参数T、U  返回值 boolean
        // BiConsumer<T,U> :    参数T、U 无返回值

        /**
         * 常用的 函数式接口
         * Predicate<T>、Consumer<T>、Function<T,R>、Supplier<T>
         */
    }
}

3、Stream Api

创建stream的几种方法

public class LambdaTest6 {
    @Test
    public void test1(){
        //创建Stream
        //1、可以通过Collection系列集合提供的stream()或parallelStream()
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();

        //2.通过Stream类中的静态方法of()
        Stream<String> aa = Stream.of("aa", "bb", "cc");

        //3.通过Arrays中的静态方法stream()获取数据流
        Person[] person = new Person[10];
        Stream<Person> stream1 = Arrays.stream(person);

        //4.创建无限流
        Stream<Integer> iterate = Stream.iterate(0, (x) -> x + 2);
        iterate.limit(10).forEach(System.out::println);

        //5.生成
        Stream.generate(()->Math.random()*100).limit(10).forEach(System.out::println);
    }

生成测试数据

  List<Person> personList = Arrays.asList(
            new Person("张三", 14),
            new Person("李四", 28),
            new Person("王五", 38),
            new Person("张三", 59),
            new Person("张三", 75),
            new Person("张三", 75),
            new Person("张三", 75)
    );

筛选和切片


    //filter --接受Lambda,从流中排出某些元素
    @Test
    public void test1() {
        Stream<Person> stream = personList.stream()
                .filter((e) -> e.getAge() > 30);
        stream.forEach(System.out::println);
    }

    /**
     * 运行结果
     * Person{name='王五', age=38}
     * Person{name='张三', age=59}
     * Person{name='张三', age=75}
     * Person{name='张三', age=75}
     * Person{name='张三', age=75}
     */

    //limit--截断流,使其元素不超过给定数量
    @Test
    public void test2() {
        personList.stream()
                .filter((e) -> e.getAge() > 30)
                .limit(2)
                .forEach(System.out::println);
    }

    /**
     * 运行结果
     * Person{name='王五', age=38}
     * Person{name='张三', age=59}
     */

    //skip(n)跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与 limit(互补)
    @Test
    public void test3() {
        personList.stream()
                .filter((e) -> e.getAge() > 30)
                .limit(2)
                .skip(1)
                .forEach(System.out::println);
    }

    /**
     * 运行结果
     Person{name='张三', age=59}
     */

    //distinct --筛选,通过流所生成元素的hashCode()和equals()去除重复元素
    @Test
    public void test4() {
        personList.stream()
                .filter((e) -> e.getAge() > 30)
                .limit(2)
                .skip(1)
                .distinct()
                .forEach(System.out::println);
    }

    /**
     * 运行结果
     Person{name='张三', age=59}
     */


排序

 @Test
   @Test
    //自然排序
    public void test5(){
        List<Integer> list = Arrays.asList(1,2,3,4,5);
        list.stream()
                .sorted()
                .forEach(System.out::println);
    }
    /**
     * 运行结果
     * 1
     * 2
     * 3
     * 4
     * 5
     */

查找 / 匹配

   //findAny()和findFist()获取第一条数据,如果没有就返回为空。
    @Test
    public void test6() {
        Person person = personList.stream()
                .filter((e) -> e.getAge() > 30)
                .limit(2)
                .findAny()
                .orElse(null);
        System.out.println(person);
    }

    /**
     * 运行结果
     * Person{name='王五', age=38}
     */

    //map(T -> R):使用map取出姓名(字符串)
    @Test
    public void test7(){
        personList.stream()
                .map(Person::getName)
                .forEach(System.out::println);
    }

    /**
     * 运行结果
     * 张三
     * 李四
     * 王五
     * 张三
     * 张三
     * 张三
     * 张三
     */

判断方法

  • 判断List集合中是否有一个元素包含姓名为张三的元素
  • 判断List集合中是否所有实体名称都包含"张"这个字段。
  • 判断List集合中是否存在不包含"张"这个字段。
@Test
    public void test8(){
        boolean result = personList.stream().anyMatch((person -> person.getName().equals("张三")));
        boolean result1 = personList.stream().allMatch(person -> person.getName().contains("张"));
        boolean result2 = personList.stream().noneMatch(person -> person.getName().contains("张"));
        System.out.println(result);
        System.out.println(result1);
        System.out.println(result2);
    }
    /**
     * 运行结果
     * true
     * false
     * false
     */

统计方法

  • reduce((T, T) -> T) 和 reduce(T, (T, T) -> T)
@Test
    public void test9(){
        Integer max = personList.stream().map(Person::getAge).reduce(Integer::max).get();
        Integer min = personList.stream().map(Person::getAge).reduce(Integer::min).get();
        Integer sum = personList.stream().map(Person::getAge).reduce(0,Integer::sum);

        System.out.println(max);
        System.out.println(min);
        System.out.println(sum);
    }
    /**
     * 运行结果
     * 75
     * 14
     * 364
     */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值