zoukankan      html  css  js  c++  java
  • Java8实用指北1-lambda表达式与函数式接口

    直接开干前,最好知道的几点

    lambda表达式与函数式编程

    • 函数式编程(Functional Programming)在JavaScript中到处都是(各种回调匿名函数),Java8的lambda表达式语法与ES6的箭头函数尤其相像,但是不能简单地将lambda当作语法糖看待(比如干掉匿名内部类)。
    • 函数式编程优点多多,简单的说就是:
      将函数当成对象作为方法参数传递,开发更加灵活开放,并且语法更加简洁紧凑。
    • lambda表达式是Java支持函数式编程的关键标志,是推动Java8发布的最重要的特性

    lambda表达式与函数式接口

    • lambda表达式本身是中性的,只有在真正的语境下才有它的实现代表类型。
    • 至于lambda表达式可以是哪些类型,为此Java8没有选择新增一个单独的类或者接口,而是新增了函数式接口(Functional Interface)的概念。
    • 函数式式接口就是原来的interface,只是它有一个标记和一个限制。
      标记就是一个@FunctionalInterface注解,限制就是有且仅有一个抽象方法。
    • 使用lambda表达式很容易得到一个函数式接口的实现,因此绝大多数匿名内部类的场合都可以使用lambda表达式取代,这也是我们最常使用它的场景。
    • Java8对原先的一些接口进行了函数式化,比如java.lang.Runnablejava.util.Comparator等,并提供了典型常用的函数式接口集,它们都在java.util.function包下,之后会进一步说明和应用。

    开始lambda表达式

    从匿名内部类开始

    • 对一个bean集合进行排序
    • 代码
      @Test
      public void testLambdaAndAnonymousClass1() {
      	List<TestBean> list = TestBean.list();
      	//初始顺序(即加入list的顺序)
      	list.forEach(o -> System.out.print(o.getName() + " "));
      	System.out.println("
      =============================");
      	
      	//根据名称排序,匿名内部类方式
      	list.sort(new Comparator<TestBean>() {
      		@Override
      		public int compare(TestBean o1, TestBean o2) {
      			return o1.getName().compareTo(o2.getName());
      		}
      	});
      	
      	//操作后顺序
      	list.forEach(o -> System.out.print(o.getName() + " "));
      }
      
      //Bean类
      public class TestBean extends  SerializableBean{
      private static final long serialVersionUID = 2394995648350379173L;
      
      private Integer id;
      private String name;
      
      public static List<TestBean> list(){
      	return Arrays.asList(
      		new TestBean(1, "Richard")
      		,new TestBean(2, "Ben")
      		,new TestBean(3, "Jack")
      		,new TestBean(4, "Jet")
      		,new TestBean(5, "Dicky")
      	);
      }
      
    • 输出
      Richard Ben Jack Jet Dicky 
      =============================
      Ben Dicky Jack Jet Richard 
      

    用lambda实现函数式接口,代替匿名内部类

    • Comparator接口是函数式接口
      @FunctionalInterface
      public interface Comparator<T> {}
      
    • lambda实现函数式接口,作为参数传入
      @Test
      public void testLambdaAndAnonymousClass2() {
      	List<TestBean> list = TestBean.list();
      	//初始顺序(即加入list的顺序)
      	list.forEach(o -> System.out.print(o.getName() + " "));
      	System.out.println("
      =============================");
      	
      	//根据名称排序,使用lambda
      	Comparator<TestBean> sortByName = (o1,o2) -> o1.getName().compareTo(o2.getName());
      	list.sort(sortByName);
      	//或者直接 list.sort((o1,o2) -> o1.getName().compareTo(o2.getName()));
      	
      	//操作后顺序
      	list.forEach(o -> System.out.print(o.getName() + " "));
      }
      

    函数式接口

    原Java7的一些接口进化为函数式接口

    比如:

    • java.util.Comparator
    • java.lang.Runnable
    • java.util.concurrent.Callable
    • java.io.FileFilter
    • java.nio.file.PathMatcher
    • java.lang.reflect.InvocationHandler
    • java.beans.PropertyChangeListener
    • java.security.PrivilegedAction
    • ......

    lambda实现Runnable

    • 观察Runnable接口实现,无参数,比Consumer还简单
      new Runnable() {
      	@Override
      	public void run() {
      	}
      }; 
      
    • 简单代码
      @Test
      public void testLambdaAndAnonymousClass3() {
      	List<TestBean> list = TestBean.list();
      	Runnable runner = () -> list.forEach(System.out::println); //方法引用
      	new Thread(runner).start();
      }
      
    • lambda的基本语法和方法引用就不表了

    Java8四大内置通用行为函数式接口

    • Consumer 消费型, 接受一个T,不返回值
      • 源码
        @FunctionalInterface
        public interface Consumer<T> {
            void accept(T t);
            ...
        }
        
      • 实例 in jdk8:Iterable的forEach方法
        default void forEach(Consumer<? super T> action) {
            Objects.requireNonNull(action);
            for (T t : this) {
                action.accept(t);
            }
        }
        
    • Function<T, R> 函数型,接受一个T,返回一个R
      • 源码
        @FunctionalInterface
        public interface Function<T, R> {
            R apply(T t);
            ...
        }
        
      • 实例 in jdk8:Optional的map方法
        public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
            Objects.requireNonNull(mapper);
            if (!isPresent())
                return empty();
            else {
                return Optional.ofNullable(mapper.apply(value));
            }
        }
        
      • 实现
        @Test
        public void testLambdaAndFunctional() {
        	TestBean testBean = new TestBean(1, "hhh");
        	Optional<TestBean> opt = Optional.ofNullable(testBean);
        	Optional<String> mapName = opt.map(TestBean::getName); //t -> t.getName()
        	System.out.println(mapName); //Optional[hhh]
        }
        
    • Predicate 断言型,接受一个T,返回boolean
      • 源码
        @FunctionalInterface
        public interface Predicate<T> {
            boolean test(T t);
            ...
        }
        
      • 实例 in jdk8:Stream的filter方法
        Stream<T> filter(Predicate<? super T> predicate);
        
      • 实现
        @Test
        public void testLambdaAndPredicate() {
        	List<TestBean> testBean = TestBean.list();
        	testBean.stream().filter(o -> o.getId()>2)
        					 .forEach(System.out::println); //参数一致,方法引用简写
        }
        
    • Supplier 供给型,不接受参数,返回一个T
      • 源码
        @FunctionalInterface
        public interface Supplier<T> {
            T get();
        }
        
      • 实例 in jdk8:Optional的orElseGet方法
        public T orElseGet(Supplier<? extends T> other) {
            return value != null ? value : other.get();
        }
        
      • 实现
        @Test
        public void testLambdaAndSupplier() {
        	TestBean testBean = (int)Math.floor(Math.random()*10)>5? new TestBean(1,"111") : null;
        	System.out.println(Optional.ofNullable(testBean).orElseGet(TestBean::new));// () -> new TestBean()
        }
        
    • 以上各子接口 + 更细致灵活的接口
      • BiFunction<T, U, R>
      • DoubleConsumer
      • ......

    文章副本地址

    元湛

  • 相关阅读:
    idea配置tomcat运行按钮置灰,下拉没有自定义的tomcat选项
    配置多版本jdk,自由切换jdk版本
    五年经验程序员告诉你,如何确定自己是否适合做程序员
    你的编程能力从什么时候开始突飞猛进?
    10 个提升效率的Linux小技巧
    8 种经常被忽视的 SQL 错误用法,你有没有踩过坑?
    十大优秀编程项目,让你的简历金光闪闪
    一文掌握 Lambda 表达式
    一文详解微服务架构(一)
    Java的参数传递是「按值传递」还是「按引用传递」?
  • 原文地址:https://www.cnblogs.com/noodlerkun/p/11929676.html
Copyright © 2011-2022 走看看