Java基础编程-Lambda

Lambda简介

1.1 什么是Lambda?
  • Lambda是JAVA 8添加的一个新特性。Lambda就是一个匿名函数
1.2 为什么要使用Lambda?
  • 使用Lambda表达式可以对一个接口进行非常简介的实现。
1.3 Lambda对接口的要求?
  • 要求接口中定义的必须要实现的抽象方法只能是一个

在JAVA8中对接口加了一个新特性:default
可以使用default对接口方法进行修饰,被修饰的方法在接口中有一个默认实现。这样的方法实现类可以实现,也可以不实现。所以default修饰的方法对Lambda没有影响。

1.4 @FunctionalInterface
  • 修饰函数式接口,接口中的抽象方法只有一个。
public class Program {
    public static void main(String[] args) {
        // 1.使用接口实现类
        Comparator comparator = new MyComparator();
        // 2.使用匿名内部类
        Comparator comparator1 = new Comparator() {
            @Override
            public int compare(int a, int b) {
                return a - b;
            }
        };
        // 3.使用Lambda表达式实现接口
        Comparator comparator2 = (a, b) -> a - b;
    }
}
class MyComparator implements Comparator {

    @Override
    public int compare(int a, int b) {
        return a - b;
    }
}
@FunctionalInterface
interface Comparator {
    int compare(int a, int b);
}

Lambda基础语法

2.1 准备工作 创建6个接口

6个接口

2.2 Lambda表达式基本语法
    public static void main(String[] args) {
        // 1.Lambda表达式的基础语法:
        // 函数:返回值类型 方法名 参数列表 方法体
        // Lambda是一个匿名函数,关注参数列表和方法体

        // ( ):用来描述参数列表
        // { }:用来描述方法体
        // -> :Lambda运算符,读作goes to

        // 1.1.无参无返回
        LambdaNoneReturnNoneParameter lambda1 = () -> {
            System.out.println("hello world");
        };
        lambda1.test(); //hello world

        // 1.2.无返回值、单个参数
        LambdaNoneReturnSingleParameter lambda2 = (int a)->{
            System.out.println(a);
        };
        lambda2.test(10); //10

        // 1.3.无返回值、多个参数
        LambdaNoneReturnMutipleParemeter lambda3 = (int a,int b)->{
            System.out.println(a+b);
        };
        lambda3.test(10,20); //30

        // 2.1.无参、有返回值
        LambdaSingleReturnNoneParameter lambda4 = ()->{
            System.out.print("lambda4 ");
            return 100;
        };
        int ret = lambda4.test();
        System.out.println(ret); //lambda4 100

        // 2.2.有返回值、单个参数
        LambdaSingleReturnSingleParameter lambda5 = (int a)->{
            return a*2;
        };
        int ret2 = lambda5.test(10);
        System.out.println(ret2); //20

        // 2.3.有返回值、多个参数
        LambdaSingleReturnMutipleParameter lambda6 = (int a,int b)->{
            return a+b;
        };
        int ret3 = lambda6.test(20, 30);
        System.out.println(ret3); //50
    }

Lambda语法精简

    public static void main(String[] args) {

        // 语法精简:
        // 1.参数类型:
        // 由于在接口的抽象方法中,已经定义了参数的数量和类型。
        // 所以在Lambda表达式中,参数类型可以省略
        // 备注:如果需要省略类型,则每一个参数类型都要省略。千万不要出现有的省略,有的不省略。

        LambdaNoneReturnMutipleParemeter lambda1 = (a, b) -> {
            System.out.println("hello world");
        };

        // 2.参数小括号
        // 如果参数列表中,参数的数量只有一个。此时小括号可以省略
        LambdaNoneReturnSingleParameter lambda2 = a -> {
            System.out.println("hello world");
        };

        // 3.方法大括号
        // 如果方法体只有一条语句,此时大括号可以省略
        LambdaNoneReturnSingleParameter lambda3 = a -> System.out.println("hello world");

        // 4.如果方法体中唯一的一条语句是一个返回语句,则在省略大括号的同时,也必须省略掉return
        LambdaSingleReturnNoneParameter lambda4 = () -> 10;


        // 精简前:
        LambdaSingleReturnMutipleParameter lambda5 = (int a,int b)->{
            return a+b;
        };

        // 精简后:
        LambdaSingleReturnMutipleParameter lambda6 = (a, b) -> a + b;
    }

Lambda语法进阶

4.1.方法引用
    public static void main(String[] args) {
        // 方法引用:
        // 可以快速的将一个Lambda表达式的实现只想一个已经实现的方法。
        // 语法:方法的隶属者::方法名

        // 注意:
        // 1.参数数量和类型一定要和接口中定义的方法一致
        // 2.返回值的类型页一定要和接口中定义的方法一致

        LambdaSingleReturnSingleParameter lambda1 = a -> change(a);

        // 方法引用:引用了change方法的实现。
        LambdaSingleReturnSingleParameter lambda2 = Syntax3::change;

    }
    private static int change(int a) {
        return a * 2;
    }

4.2.构造方法引用
public class Syntax4 {

    public static void main(String[] args) {

        PersonCreater creater = ()->new Person();

        // 构造方法的引用:
        // 无参构造方法引用
        PersonCreater creater1 = Person::new;
        Person person = creater1.getPerson();
        // 有参构造方法引用
        PersonCreater2 creater2 = Person::new;
        Person person1 = creater2.getPerson("zhangsan",10);
    }
}

// 原始写法
class PersonDemo implements PersonCreater{
    @Override
    public Person getPerson() {
        return new Person();
    }
}

// 需求:
interface PersonCreater{
	// 无参方法
    Person getPerson();
}
interface PersonCreater2{
	// 有参方法
    Person getPerson(String name,int age);
}

Lambda综合案例

5.1.案例一:Lambda实现Comparator接口进行ArrayList集合排序
public class Exercise1 {
    // 集合排序:
    // ArrayList<>
    public static void main(String[] args) {
        // 需求:已知在一个ArrayList中有若干个Person对象,
        // 将这些Person对象按年龄进行降序排序
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("cc", 10));
        list.add(new Person("zz", 17));
        list.add(new Person("jj", 20));
        list.add(new Person("bb", 33));
        list.add(new Person("mm", 19));
        list.add(new Person("ww", 12));
        list.add(new Person("uu", 40));
		
		// Comparator接口
//        @FunctionalInterface
//        public interface Comparator<T> {
//            int compare(T o1, T o2);
//        }

        // 实现:
        list.sort((o1, o2) -> o2.age - o1.age);
    }
}
5.2.案例二:Lambda实现Comparator接口进行TreeSet集合排序
public class Exercise2 {
    public static void main(String[] args) {

        // TreeSet
        // TreeSet带参构造方法,需要实现Comparator接口
//        public TreeSet(Comparator<? super E> comparator) {
//            this(new TreeMap<>(comparator));
//        }

        // 使用Lambda表达式来实现Comparator接口,并实例化一个TreeSet对象
        TreeSet<Person> set = new TreeSet<>((o1,o2)->{
            if (o1.age >= o2.age){
                return -1;
            }else {
                return 1;
            }
        });
        set.add(new Person("cc", 10));
        set.add(new Person("zz", 17));
        set.add(new Person("jj", 20));
        set.add(new Person("bb", 33));
        set.add(new Person("mm", 19));
        set.add(new Person("ww", 12));
        set.add(new Person("vv", 12));
        set.add(new Person("uu", 40));
        System.out.println(set);
    }

}

5.3.案例三:Lambda实现Consumer接口进行集合遍历
public class Exercise3 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,1,2,3,4,5,6,7,8,9,0);
        // 集合遍历
//        @FunctionalInterface
//        public interface Consumer<T> {
//            void accept(T t);
//        }
        // 将集合中的每一个元素都带入到方法accept中。
        // list.forEach(System.out::println);

        // 输出集合中所以的偶数
        list.forEach(ele ->{
            if (ele %2 ==0){
                System.out.println(ele);
            }
        });
    }
}
5.4.案例四:Lambda实现Predicate接口根据条件删除集合元素
public class Exercise4 {
    public static void main(String[] args) {

        // 需求:删除集合中满足条件的元素
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("cc", 10));
        list.add(new Person("zz", 17));
        list.add(new Person("jj", 20));
        list.add(new Person("bb", 33));
        list.add(new Person("mm", 19));
        list.add(new Person("ww", 12));
        list.add(new Person("uu", 40));

        // 题目:删除集合中年龄>30的元素

        // 原始写法
        ListIterator<Person> iterator = list.listIterator();
        while (iterator.hasNext()){
            Person ele = iterator.next();
            if (ele.age>30){
                iterator.remove();
            }
        }

        // 将集合每一个元素都带入到test方法中,如果返回值是true,则删除这个元素
//        @FunctionalInterface
//        public interface Predicate<T> {
//            boolean test(T t);
//        }

        // Lambda实现
        list.removeIf(ele->ele.age>30);
    }
}
5.5.案例五:Lambda实现Runnable接口
public class Exercise5 {
    public static void main(String[] args) {

        // 需求:开辟一条线程。做一个数字的输出。

//        @FunctionalInterface
//        public interface Runnable {
//            public abstract void run();
//        }

        Thread t = new Thread(()->{
            for (int i = 0; i < 100; i++) {
                System.out.println(i);
            }
        });
        t.start();
    }
}

系统内置函数式接口

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

        Predicate<T>{ boolean test(T t);} :参数T  返回值boolean
        Consumer<T> { void accept(T t);} :参数T  返回值void
        Function<T, R> { R apply(T t);} :参数T 返回值R
        BiPredicate<T, U> {boolean test(T t, U u);} :参数T,U 返回值boolean
        BiConsumer<T, U> {void accept(T t, U u);} :参数T,U 返回值void
        BiFunction<T, U, R> { R apply(T t, U u);} :参数T,U 返回值R

        Supplier<T> { T get();} :无参 返回值T
        UnaryOperator<T> extends Function<T, T> { } :参数T 返回值T
        BinaryOperator<T> extends BiFunction<T,T,T> {} :参数T,T 返回值T

闭包问题

7.1.闭包问题
  • Lambda表达式实现接口的方法时,如果使用到局部变量,则会默认将其添加一个fianl属性,使其变成常量,并提升生命周期

闭包中引用的一定是常亮,如果不是,系统会自动添加fianl属性,使其变成常亮

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

        Integer i = getNumber().get();
        System.out.println(i); // 10
        // 因为闭包,提升了num局部变量的声明周期,输出仍然为num的值
    }

    // 闭包情况
    private static Supplier<Integer> getNumber(){

        int num = 10;

        return ()->num;  // 闭包
    }
}
public class ClosureDemo2 {
    public static void main(String[] args) {

        int a = 10;  // a为局部变量

        Consumer<Integer> c = ele->{
            System.out.println(a); // 闭包情况,a变成常量
        };
        // 因为a变量在闭包中,变为了常亮,所以不可以进行运算和赋值操作
        // 所以闭包中a报错 Variable used in lambda expession should be final or fectively fnal
        a++;
        c.accept(1);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值