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("\n=============================");
    	
    	//根据名称排序,匿名内部类方式
    	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("\n=============================");
    	
    	//根据名称排序,使用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
    • ......

文章副本地址

元湛

posted @ 2019-11-25 19:07  summaster  阅读(237)  评论(0编辑  收藏  举报