• Java8 Lambda表达式


    资料 :
      1.java8新特性(拉姆达表达式lambda) *****
        https://blog.csdn.net/qq_35805528/article/details/53264301
      1.Java8 Lambda表达式教程  ***
        https://blog.csdn.net/ioriogami/article/details/12782141
      2.【java8新特性】兰姆达表达式  ***
        https://blog.csdn.net/DJuan15732626157/article/details/80251401

    我们要注意的是:lambda表达式需要“函数式接口”的支持,那么什么是函数式接口呢?
    函数式接口:接口只有一个抽象方法的接口,

    java 8提供 @FunctionalInterface作为注解,这个注解是非必须的,只要接口符合函数式接口的标准(即只包含一个方法的接口),虚拟机会自动判断,

    但最好在接口上使用注解@FunctionalInterface进行声明,以免团队的其他人员错误地往接口中添加新的方法。

    这是Java8新引入的概念。它的定义是:一个接口,如果只有一个显式声明的抽象方法,那么它就是一个函数接口。一般用@FunctionalInterface标注出来(也可以不标)。
    举例如下:     @FunctionalInterface    
    public interface Runnable { void run(); }         public interface Callable<V> { V call() throws Exception; }         public interface ActionListener { void actionPerformed(ActionEvent e); }         public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); } 注意最后这个Comparator接口。它里面声明了两个方法,貌似不符合函数接口的定义,但它的确是函数接口。这是因为equals方法是Object的,
    所有的接口都会声明Object的public方法——虽然大多是隐式的。所以,Comparator显式的声明了equals不影响它依然是个函数接口。 你可以用一个lambda表达式为一个函数接口赋值:       Runnable r1
    = () -> {System.out.println("Hello Lambda!");};     然后再赋值给一个Object:     Object obj = r1;     但却不能这样干:     Object obj = () -> {System.out.println("Hello Lambda!");}; // ERROR! Object is not a functional interface! 必须显式的转型成一个函数接口才可以:     Object o = (Runnable) () -> { System.out.println("hi"); }; // correct     一个lambda表达式只有在转型成一个函数接口后才能被当做Object使用。所以下面这句也不能编译:     System.out.println( () -> {} ); //错误! 目标类型不明     必须先转型:     System.out.println( (Runnable)() -> {} ); // 正确 假设你自己写了一个函数接口,长的跟Runnable一模一样:     @FunctionalInterface     public interface MyRunnable {         public void run();     }     那么     Runnable r1 =    () -> {System.out.println("Hello Lambda!");};     MyRunnable2 r2 = () -> {System.out.println("Hello Lambda!");}; 都是正确的写法。这说明一个lambda表达式可以有多个目标类型(函数接口),只要函数匹配成功即可。 但需注意一个lambda表达式必须至少有一个目标类型。

    lambda语法

    包含三部分:
      1、一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数
      2、一个箭头符号:->
      3、方法体,可以是表达式和代码块。

    public class Demo1 {
    	public static void main(String[] args) {
    		runThreadByLambda();
    		runThreadByInnerClass();
    	}
    
    	public static void runThreadByLambda() {
    		/*
    		 Runnable就是一个函数式接口:他只有一个方法run()方法。
    		 1、因为run()方法没有参数,所以   ->前面的()中不需要声明形参
    		 2、run返回的是void,所以不需要return。
    		 3、->后面写的代码其实就是定义在run方法内的代码。因为此处代码只有一行,所以{}也可以省略。如果此处多与一行,则无法省略。
    		 */
    		Runnable runnable = () -> System.out.println("这个是用拉姆达实现的线程");
    		new Thread(runnable).start();
    	}
    
    	public static void runThreadByInnerClass() {
    		Runnable runnable = new Runnable() {
    
    			@Override
    			public void run() {
    				System.out.println("这个是用内部类实现的线程");
    
    			}
    		};
    		new Thread(runnable).start();
    	}
    }
    

      

    lambda方法引用

      其实是lambda表达式的一种简化写法。所引用的方法其实是lambda表达式的方法体实现,语法也很简单,左边是容器(可以是类名,实例名),中间是"::",右边是相应的方法名。

      一般方法的引用格式:

        如果是静态方法,则是ClassName::methodName。如 Object ::equals
        如果是实例方法,则是Instance::methodName。如Object obj=new Object();obj::equals;
        构造函数.则是ClassName::new

    public class Demo2 {
    
    	public static void main(String[] args) {
    		/*
    		 * 方法引用
    		 */
    		Runnable runnable = Demo2::run;
    		new Thread(runnable).start();
    	}
    	
    	public static void run(){
    		System.out.println("方法引用的代码...");
    	}
    }
    

      

    使用lambda改进的集合框架

    import java.util.ArrayList;
    import java.util.List;
    
    public class Demo3 {
    	public static void main(String[] args) {
    		List<User> users = new ArrayList<User>();
    		users.add(new User(20, "张三"));
    		users.add(new User(22, "李四"));
    		users.add(new User(10, "王五"));
    
    		users.forEach((User user) -> System.out.println(user.getAge()));
    	}
    }
    

      

    Stream API

    流(Stream)仅仅代表着数据流,并没有数据结构,所以他遍历完一次之后便再也无法遍历(这点在编程时候需要注意,不像Collection,遍历多少次里面都还有数据),它的来源可以是Collection、array、io等等。

    流作用是提供了一种操作大数据接口,让数据操作更容易和更快。它具有过滤、映射以及减少遍历数等方法,这些方法分两种:中间方法和终端方法,“流”抽象天生就该是持续的,中间方法永远返回的是Stream,

    因此如果我们要获取最终结果的话,必须使用终点操作才能收集流产生的最终结果。区分这两个方法是看他的返回值,如果是Stream则是中间方法,否则是终点方法。

    filter

    在数据流中实现过滤功能是首先我们可以想到的最自然的操作了。Stream接口暴露了一个filter方法,它可以接受表示操作的Predicate实现来使用定义了过滤条件的lambda表达式。

    import java.util.stream.Stream;
    
    public class StreamDemo {
    	public static void main(String[] args) {
    		List<User> users = new ArrayList<User>();
    		users.add(new User(20, "张三"));
    		users.add(new User(22, "李四"));
    		users.add(new User(10, "王五"));
    		
    		Stream<User> stream = users.stream();
    		stream.filter(p -> p.getAge() > 20); //过滤年龄大于20的
    	}
    }
    

      

    map

    假使我们现在过滤了一些数据,比如转换对象的时候。Map操作允许我们执行一个Function的实现(Function<T,R>的泛型T,R分别表示执行输入和执行结果),它接受入参并返回。

    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Stream;
    
    public class StreamDemo {
    	public static void main(String[] args) {
    		List<User> users = new ArrayList<User>();
    		users.add(new User(20, "张三"));
    		users.add(new User(22, "李四"));
    		users.add(new User(10, "王五"));
    		
    		Stream<User> stream = users.stream();
    		 //所有的年龄大于20岁的User对象,转换为字符串50对象。现在流中只有字符串对象了。
    		stream.filter((User user) ->  user.getAge() > 20).map((User user) -> {return "50";});
    	}
    }
    

      

    count

    count方法是一个流的终点方法,可使流的结果最终统计,返回long

    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collector;
    import java.util.stream.Stream;
    
    public class StreamDemo {
    	public static void main(String[] args) {
    		List<User> users = new ArrayList<User>();
    		users.add(new User(20, "张三"));
    		users.add(new User(22, "李四"));
    		users.add(new User(10, "王五"));
    		
    		Stream<User> stream = users.stream();
    		long count = stream.filter((User user) ->  user.getAge() >= 20).map((User user) -> {return "50";})
    		.count(); //返回流中元素的个数。
    		System.out.println(count);	
    	}
    }
    

      

  • 相关阅读:
    Soap 教程
    MAC mysql install
    PHP date
    MAC 终端terminal颜色
    MAC 终端颜色设置
    MAC brew软件安装
    PHP iconv函数
    Java----前端验证之验证码额实现
    Java---Ajax在Struts2框架的应用实例
    Java基础—标识符及命名规范
  • 原文地址:https://www.cnblogs.com/jiuya/p/11810750.html
Copyright © 2020-2023  润新知