ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

012—JAVA8新特性(lambda表达式)

2021-11-07 00:02:50  阅读:181  来源: 互联网

标签:void System JAVA8 012 println new lambda public out


函数式编程(lambda表达式 @FunctionalInterface)

        思想:(函数式编程VS面向对象)

函数就是有输入量、输出量的一套计算方案,也就是“拿什么东西做什么事情”。编程中的函数,也有类似的概念,你调用我的时候,给我实参为形参赋值,然后通过运行方法体,给你返回一个结果。对于调用者来做,关注这个方法具备什么样的功能。相对而言,面向对象过分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以什么形式做

面向对象的思想:

        做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情.

函数式编程思想:

        只要能获取到结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程

优点:

        目的是简化匿名内部类 

        Lambda写的好可以极大的减少代码冗余,同时可读性也好过冗长的匿名内部类。

 冗余的匿名内部类

public class Demo01Runnable {
	public static void main(String[] args) {
    	// 匿名内部类
		Runnable task = new Runnable() {
			@Override
			public void run() { // 覆盖重写抽象方法
				System.out.println("多线程任务执行!");
			}
		};
		new Thread(task).start(); // 启动线程
	}
}

分析弊端:

对于Runnable的匿名内部类用法,可以分析出几点内容:

  • Thread类需要Runnable接口作为参数,其中的抽象run方法是用来指定线程任务内容的核心;

  • 为了指定run的方法体,不得不需要Runnable接口的实现类;

  • 为了省去定义一个RunnableImpl实现类的麻烦,不得不使用匿名内部类;

  • 必须覆盖重写抽象run方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错;

  • 而实际上,似乎只有方法体才是关键所在

编程思想转换

        做什么,而不是谁来做,怎么做 (关注点不同)

我们真的希望创建一个匿名内部类对象吗?不。我们只是为了做这件事情而不得不创建一个对象。我们真正希望做的事情是:将run方法体内的代码传递给Thread类知晓。

传递一段代码——这才是我们真正的目的。而创建对象只是受限于面向对象语法而不得不采取的一种手段方式。那,有没有更加简单的办法?如果我们将关注点从“怎么做”回归到“做什么”的本质上,就会发现只要能够更好地达到目的,过程与形式其实并不重要。

函数式编程面向的主要场景是,针对于函数式接口(@FunctionalInterface,即接口中只含有一个抽象方法,对于静态方法和default方法没有限制).

了解函数式接口:

写法:

针对于抽象方法,省略方法声明,只要参数,和方法体,如果方法体只有一个语句也可以省略{},否则可以省略。

()->{}
    ():形参
    ->: 语法标识
    {}:方法体

注意:
    1.如果方法重写后 仅有一行代码 可以省略{}
    2.()数据类型可以省略
    3.如果带返回值的方法 只有一行返回语句
      那么可以省略 return {};

 

  • (形参列表)它就是你要赋值的函数式接口的抽象方法的(形参列表),照抄

  • {Lambda体}就是实现这个抽象方法的方法体

  • ->称为Lambda操作符(减号和大于号中间不能有空格,而且必须是英文状态下半角输入方式)

优化:Lambda表达式可以精简

  • 当{Lambda体}中只有一句语句时,可以省略{}和{;}

  • 当{Lambda体}中只有一句语句时,并且这个语句还是一个return语句,那么return也可以省略,但是如果{;}没有省略的话,return是不能省略的

  • (形参列表)的类型可以省略

  • 当(形参列表)的形参个数只有一个,那么可以把数据类型和()一起省略,但是形参名不能省略

  • 当(形参列表)是空参时,()不能省略

 

lambda表达式其实就是实现SAM接口的语法糖,所谓SAM接口就是Single Abstract Method,即该接口中只有一个抽象方法需要实现,当然该接口可以包含其他非抽象方法。为了简化匿名内部类的写的方式

其实只要满足“SAM”特征的接口都可以称为函数式接口,都可以使用Lambda表达式,但是如果要更明确一点,最好在声明接口时,加上@FunctionalInterface。一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。

之前学过的SAM接口中,标记了@FunctionalInterface的函数式接口的有:Runnable,Comparator 。

Java8在java.util.function新增了很多函数式接口:主要分为四大类,消费型、供给型、判断型、功能型。基本可以满足我们的开发需求。当然你也可以定义自己的函数式接口。

函数式编程只关注结果

函数式接口的分类:

(一)自定义函数式接口

系统类的函数式接口:
       @FunctionalInterface
       public interface Runnable {}
       @FunctionalInterface
       public interface Comparator<T> {}

       public interface Comparable<T> {}只有一个抽象方法

系统函数式接口的分类:
   消费型           貔貅   只进不出      只接受数据 不返回数据
   供给型接口        雷锋  只奉献不索取   只返回数据 不接受数据
   判断/断言型接口   法官   判断对错      无论接受什么数据 都只返回 boolean

   功能型接口       普通人    有来有往    既接受数据  也返回数据

只要确保接口中有且仅有一个抽象方法即可。

public class AutoDefination {
    public static void main(String[] args) {
        A a = new A() {
            @Override
            public void add(int a, int b) {
                System.out.println(a + b);
            }
        };
        a.add(100, 200);

    }
    @Test
    public void test02(){
        //lambda表达式只对抽象接口起作用
        testAdd(100, 200, (a,b) -> System.out.println(a + b));
    }
    @Test
    public void test01(){
    testAdd(100, 200, new A() {
        @Override
        public void add(int a, int b) {
            System.out.println(a + b);
        }
    });

    }

    public static void testAdd(int a,int b,A c){
        c.add(a, b);
    }
}

@FunctionalInterface
interface A{
    //创建抽象方法
    void add(int a,int b);
}

(二)消费型接口

消费型接口的抽象方法特点:有形参,但是返回值类型是void

 举例(list遍历和map遍历lambda)

list遍历

public class ConsumerTest {
        ArrayList<String> list = new ArrayList<>();
    @Before
    public void test00(){
        Collections.addAll(list, "A","B","C","D","E");
    }
    @Test
    public void test06(){
    }

    @Test
    public void test05(){
        list.forEach((s) -> System.out.println(s));
        ;
    }
   
    @Test
    public void test03(){
        //会从传入参数的前一个位置开始遍历
        ListIterator<String> listIterator = list.listIterator(list.size());

        while (listIterator.hasPrevious()){
            String current = listIterator.previous();
            System.out.println("current = " + current);
        }


    }

    @Test
    public void test02(){
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            String next = iterator.next();
            System.out.println("next = " + next);
        }


    }
    @Test
    public void test01(){
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));

        }
        
    }
}

map遍历

public class TestMap {
        Map<Integer, String> map = new HashMap<>();
    @Before
    public void test00(){
        map.put(1, "A");
        map.put(2, "B");
        map.put(3, "C");
        map.put(4, "D");
        map.put(5, "E");

    }
    @Test
    public void test03(){
        map.forEach(new BiConsumer<Integer, String>() {
            @Override
            public void accept(Integer integer, String s) {
                System.out.println(integer + "--->" + s);
            }
        });

    }
    @Test
    public void test02(){

        map.forEach((k , v) -> System.out.println(k +  "---->" + v));
    }
    @Test
    public void test01(){
        Set<Integer> keys = map.keySet();
        keys.forEach((key) -> System.out.println(key +"---->" + map.get(key)));

    }
}

 (三)供给型接口

这类接口的抽象方法特点:无参,但是有返回值

public class SupplierTest {
    @Test
    public void test03(){
        // //生成数据 将数据进行展示  无限生成
        /*Stream.generate(new Supplier<Object>() {
            @Override
            public Object get() {
                return new Date();
            }
        }).forEach(new Consumer<Object>() {
            @Override
            public void accept(Object o) {
                System.out.println("o = " + o);
            }
        });*/

        Stream.generate(() -> new Date()).forEach(System.out::println);

    }



    @Test
    public void test02(){
        /*Supplier<Double> supplier = new Supplier<Double>() {
            @Override
            public Double get() {
                return Double.valueOf(Math.PI);
            }
        };*/
        Supplier<Double> supplier = () -> Double.valueOf(Math.PI);
        Double aDouble = supplier.get();
        System.out.println("aDouble = " + aDouble);

    }

    @Test
    public void test01(){
        /*//返回一个对象
        Supplier supplier = new Supplier() {
            @Override
            public Object get() {
                return new String("供给型接口作用是返回一个对象");
            }
        };*/
        Supplier supplier = () -> new String("供给型接口作用是返回一个对象");


        Object o = supplier.get();
        System.out.println("o = " + o);

    }
}

 (四)判断型 (用于过滤数据)

这里接口的抽象方法特点:有参,但是返回值类型是boolean结果。

 

public class PredicateTest {
    ArrayList<Integer> list = new ArrayList<Integer>();
    @Before
    public void test00(){
        Collections.addAll(list, 1,2,3,4,5,6,7,8,9,10);
        list.forEach((n)-> System.out.print(n + " "));
        System.out.println();
        System.out.println("-------------数据添加完毕-----------------");

    }
    @Test
    public void test01(){
        //删除 经过检验 返回值为true的值
        /*
        //方式一
        list.removeIf(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                //删除偶数
                if (integer % 2 == 0){
                    return true;
                }else {
                    return false;
                }
            }
        });*/
        //方式二
//        list.removeIf((integer) -> integer % 2 == 0? true:false);
        //方式三
        list.removeIf((integer)->integer%2==0);

    }


    @After
    public void test000(){
        System.out.println("------------数据处理完打印----------------");
        list.forEach((n)-> System.out.print(n+ " "));


    }


}

 

(五)功能型

这类接口的抽象方法特点:既有参数又有返回值

public class FunctionTest {
    HashMap<Integer, String> map = new HashMap<>();

    @Before
    public void test00() {

        map.put(1, "李白");
        map.put(2, "安琪拉");
        map.put(3, "白居易");
        map.put(4, "李商隐");
        map.put(5, "嬴政");
        map.forEach((k, v) -> System.out.println(k + "--->" + v));

    }
    @Test
    public void test04() {
        map.replaceAll((k,v)-> v.contains("李")?"妲己":v);
    }

    @Test
    public void test03() {
        map.replaceAll((k,v) -> {
          return v.contains("李")?"妲己":v;
        });



    }
    @Test
    public void test02() {
        map.replaceAll((k, v) -> {
            if (v.contains("李")) {
                return "妲己";
            } else {
                return v;
            }
        });
    }


    @Test
    public void test01() {


        map.replaceAll(new BiFunction<Integer, String, String>() {
            @Override
            public String apply(Integer key, String value) {
//                System.out.println(key + "------>" + value);
                //只要value中有白 ,就要将此value替换成妲己
                if (value.contains("白")) {
                    return "妲己";
                }
                //返回值会替换原有的value
                return value;
            }
        });

    }

    @After
    public void test000() {
        System.out.println("-----------------");

        map.forEach((k, v) -> System.out.println(k + "--->" + v));


    }
}

判断型接口 练习

public class Employee {
    private int id;
    private String name;
    private char gender;
    private int age;
    private double salary;

    public Employee(int id, String name, char gender, int age, double salary) {
        super();
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.salary = salary;
    }
    public Employee() {
        super();
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", gender=" + gender + ", age=" + age + ", salary=" + salary
                + "]";
    }
}

 

public class EmployeeSerice {
    ArrayList<Employee> all;

    public EmployeeSerice() {
        all = new ArrayList<Employee>();
        all.add(new Employee(1, "张三", '男', 33, 8000));
        all.add(new Employee(2, "翠花", '女', 23, 18000));
        all.add(new Employee(3, "无能", '男', 46, 8000));
        all.add(new Employee(4, "李四", '女', 23, 9000));
        all.add(new Employee(5, "老王", '男', 23, 15000));
        all.add(new Employee(6, "大嘴", '男', 23, 11000));
    }

    ArrayList<Employee> get(Predicate<Employee> p) {
        //在EmployeeSerice员工管理类中,声明一个方法:
        // ArrayList<Employee> get(Predicate<Employee> p),
        // 即将满足p指定的条件的员工,添加到一个新的ArrayList<Employee> 集合中返回。
        ArrayList<Employee> emp = new ArrayList<>();
        for (Employee employee : all) {
            //底层Predicate接口中有个抽象方法  boolean test(T t); 推断型接口返回类型为Boolean
            if (p.test(employee)) {
                emp.add(employee);
            }
        }
        return emp;
    }


}
class EmployeeTest {
    public static void main(String[] args) {
        EmployeeSerice es = new EmployeeSerice();
       /* es.get(new Predicate<Employee>() {
            @Override
            public boolean test(Employee employee) {
                System.out.println(employee);
                return true;
            }
        });*/
        //- 所有员工对象
        es.get((e)-> true).forEach((s) -> System.out.println(s));
        System.out.println("-----------");
        //        - 所有年龄超过35的员工
        es.get((e) -> e.getAge() > 35 ).forEach(System.out::println);
        //        - 所有薪资高于15000的女员工
        System.out.println("-------------------");
        es.get((e) -> e.getSalary()>15000).forEach(System.out::println);
        //        - 所有编号是偶数的员工
        es.get((e) -> e.getId() % 2 == 0).forEach(System.out::println);
        //        - 名字是“张三”的员工
        es.get((e) -> e.getName().equals("张三")).forEach(System.out::println);
        //        - 年龄超过25,薪资低于10000的男员工
        es.get((e) -> e.getAge()>25 && e.getSalary()<10000).forEach(System.out::println);



    }


}

标签:void,System,JAVA8,012,println,new,lambda,public,out
来源: https://blog.csdn.net/xiaodi2016/article/details/121176187

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有