Java8函数式接口的基础学习教程

函数式接口

1.1 函数式接口概述

函数式接口:有且仅有一个抽象方法的接口

Java中的函数式编程体现就是Lambda表达式,所以函数式接口就是可以使用与Lambda使用的接口

只有确保接口只能够有且只有一个抽象方法,Lambda才能顺利的进行推导

检测接口是不是函数式接口:

  • @FunctionalInterface
  • 放在接口定义的上方:如果接口是函数式接口,编译通过,反之失败。

注意:

  • 我们自己定义函数式接口的时候,@FunctionalInterface是可选的,就算不写,只要爆炸慢煮函数式接口定义的要求,照样也是。但是建议加上注解。

1.2 函数式接口作为方法的参数

如果方法的参数是一个函数式接口,我们可以使用Lambda表达式作为参数传递

定义一个类(RunnableDemo).在类中提供俩个方法

一个方法是 startThread(Runnable r) 方法参数Runnable是一个函数式接口

一个方法是主方法.在主方法中凋用startThread方法

public class RunnableDemo {
	public static void main(String[] args) {
		//在主方法中凋用startThread方法

		//匿名内部类
		startThread(new Runnable() {

			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName() + " 线程启动");
			}
		});

		//Lambda
		startThread(() -> System.out.println(Thread.currentThread().getName() + " 线程启动"));

	}

	private static void startThread(Runnable r) {//方法参数Runnable是一个凾数式接口
//		Thread t = new Thread(r);
//		t.start();
		new Thread(r).start();
	}
}

结果:

Thread-0 线程启动
Thread-1 线程启动

1.3 函数式接口作为方法的返回值

如果方法的返回值是一个函数式接口,我们可以使用Lambda表达式来作为结果返回

练习:
定义一个类(ComparatorDemo).在类中提供俩个方法
 一个方法是 Comparotorestring getComparator() 方法返回値Comparator是一个凾数式接口
 一个方法是主方法.在主方法中调用getComparator方法

public class ComparatorDemo {

	public static void main(String[] args) {
		//构造使用场景 根据字符串长度
		//定义集合,存储字符串元素
		ArrayList<String> array = new ArrayList<String>();
		array.add("Collin");
		array.add("Leon");
		array.add("Pi");
		array.add("123");
		array.add("878");

		System.out.println("排序前: " + array);

		Collections.sort(array);
		System.out.println("排序后: " + array);
		Collections.sort(array, getComparator());
		System.out.println("排序后: " + array);
	}

        private static Comparator<String> getComparator(){
                //匿名内部类的方式实现
                //根据长度去排序
//		Comparator<String > comp = new Comparator<String>() {
//
//			@Override
//			public int compare(String o1, String o2) {
//				return o1.length() - o2.length();
//			}
//		};
//		return comp;

                //改进
//		return new Comparator<String>() {
//
//		@Override
//		public int compare(String o1, String o2) {
//			return o1.length() - o2.length();
//			}
//		};

                //改进为Lambda表达式
//		return ((String s1, String s2) -> {
//			return s1.length()-s2.length();
//		});

                //优化
                return (s1,s2) -> s1.length()-s2.length();
        }
}

结果:

排序前: [Collin, Leon, Pi, 123, 878]
排序后: [123, 878, Collin, Leon, Pi]
排序后: [Pi, 123, 878, Leon, Collin]

1.4常见的函数式接口

Java8在java.util.function包下预定义了大量的函数式接口

  • 功能性接口 java.Util.Function<T,R>{public R apply(T t);} :接口一个参数,返回一个参数
  • 消费性接口 Consumer{public void accept(T t);} :不需要返回
  • 供给性接口 Supplier{public T get();}
  • 断言性接口 Predicate{public boolean test(T t);}: 判断使用

1.5 Supplier接口

主要用来生产数据

Supplier< T >: 包含一个无参的方法

  • T get():获取结果
  • 该方法不需要参数,会按照某种实现逻辑(由Lambda表达式实现)返回一个数据
  • Supplier< T > 接口也被称为生产型接口,如果我们制定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用
public class SupplierDemo {
	public static void main(String[] args) {
//		String s = getstring(() -> {
//			return "你好Java";
//		});
		//优化
		String s = getstring(() -> "略略略");
		System.out.println(s);

		Integer i = getInteger(() -> 9920);
		System.out.println(i);

	}
	//定义一个方法,返回一个int数据
	private static Integer getInteger(Supplier<Integer> sup) {
		return sup.get();
	}
	//定义一个方法,返回一个String数据
	private static String getstring(Supplier<String> sup) {
		return sup.get();
	}
}

结果:

略略略
9920

1.6 Customer接口

Consumer< T > :包含俩个方法

  • void accept( T t ):对指定的参数执行此操作
  • default Consumer< T >and Then( Consumer after ):返回一个组合的Consumer,依次执行操作,然后执行after操作
  • 该接口也被称为消费型接口,它消费的数据的类型由泛型指定
	public static void main(String[] args) {
		operatorString("Leo1", (String s) ->{
			System.out.println(s);
		});
		//优化
		operatorString("Leo2", s -> System.out.println(s));
		//方法引用
		operatorString("Leo3", System.out::println);

		operatorString("Leo4", s -> System.out.println(new StringBuilder(s).reverse()));
		System.out.println("--------------");

		operatorString("Leon5", s -> System.out.println(s),s -> System.out.println(new StringBuilder(s).reverse()));

	}
	//定一个方法,用不同的方式消费同一个一个字符串数据俩次
	private static void operatorString(String name, Consumer<String> con1,Consumer<String> con2) {
//		con1.accept(name);
//		con2.accept(name);
		con1.andThen(con2).accept(name);
		//先消费name,再con2
	}

	//定一个方法,消费一个字符串数据
	private static void operatorString(String name, Consumer<String> con) {
		con.accept(name);
	}

}

结果:

Leo1
Leo2
Leo3
4oeL
--------------
Leon5
5noeL

练习

String[] strArray= {"林青霞30",”张曼玉,35", "王祖贤,33");

字符串数组中有多条信息, 请按照格式:“姓名: XX年龄: XX"的格式将信息打印出来

要求:

把打印姓名的动作作为第一个Consumer接口的L ambda实例

把打印年龄的动作作为第二个Consumer接[ ]的ambda实例

将两个Consumer接口按照顺序组合到一起使用

public class ConsumerTest {
	public static void main(String[] args) {
		String[] strArray= {"林青霞,30","张曼玉,35","王祖贤,33"};

		printInfo(strArray, (String str) ->{
			String name = str.split(",")[0];
			System.out.print("Name: " + name);
		},(String str) -> {
			int age =Integer.parseInt(str.split(",")[1]);
			System.out.println(" ,Age: " + age);
		});
		System.out.println("-------------------");
		//改进
		printInfo(strArray,
				str -> System.out.print("Name: "+ str.split(",")[0]),
				str -> System.out.println(" ,Age: " + Integer.parseInt(str.split(",")[1]))
				);
	}

	private static void printInfo(String[] strArray, Consumer<String> con1, Consumer<String> con2) {
		for(String str : strArray) {
			con1.andThen(con2).accept(str);
		}
	}
}

结果:

Name: 林青霞 ,Age: 30
Name: 张曼玉 ,Age: 35
Name: 王祖贤 ,Age: 33
-------------------
Name: 林青霞 ,Age: 30
Name: 张曼玉 ,Age: 35
Name: 王祖贤 ,Age: 33

1.7Predicate接口

Predicate< T >:常用的四个方法

  • boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值
  • default Predicate  negate():返回一个逻辑的否定,对应逻辑非
  • default Predicate and(Predicate other):返回一个组合判断,对应短路与
  • default Predicate  or(Predicate other):返回一个组合判断,对应短路或
  • Predicate< T >接口通常用于判断参数是否满足指定的条件

  练习

String[] strArray= {"林青霞,30","柳岩,34", "张曼玉,35","貂蝉,31","王祖贤,33"};

字符串数组中有多条信息,请通过Predicate接口的拼装将符合要求的字符串筛选到集合ArrayList中,井遍历ArrayList集合

同时满足如下要求:

姓名长度大于2;

年龄大于33

 分析

有两个判断条件,所以需要使用两个Predicate接[ ],对条件进行判断

必须同时满足两个条件,所以可以使用and方法连接两个判断条件

public class PredicateTest {
	public static void main(String[] args) {
		String[] strArray= {"林青霞,30","柳岩,34", "张曼玉,35","貂蝉,31","王祖贤,33"};

		ArrayList<String> array = myFilter(strArray,
				s -> s.split(",")[0].length() > 2,
				s -> Integer.parseInt(s.split(",")[1]) > 33);
		for (String str : array) {
			System.out.println(str);
		}
	}
	//通过Predicate接口的拼装将符合要求的字符串筛选到集合ArrayList中
	private static ArrayList<String> myFilter(String[] strArray, Predicate<String> pre1, Predicate<String> pre2){
		//定义一个集合
		ArrayList<String> array = new ArrayList<String>();

		//遍历数组
		for (String str : strArray) {
			if(pre1.and(pre2).test(str)) {
				array.add(str);
			}
		}
		return array;
	}
}

结果:

张曼玉,35

1.8 Function接口

Function<T,R>:常用的兩个方法

  • R apply(T t): 将此函数应用于给定的参数
  • default < V > Function andThen (Function after):返回一个组合函数,首先将该函数应用输入,然后将after函数作用于結果
  • Function<T,R> 接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的値

练习

String s =“林青霞30";

请按照我指定的要求进行操作:

1:将字符串截取得到数字年龄部分

2:将上一步的年龄字符串转换成为int类型的数据

3:将上-步的int数据加70, 得到一个int结果,在控制台输出

请通过Function接口来实现函数拼接

public class FunctionTest {

	public static void main(String[] args) {
		String s ="林青霞,30";

		convert(s, ss -> s.split(",")[1], ss -> Integer.parseInt(ss), i -> i + 70);
	}

	private static void convert(String s, Function<String, String> fun1, Function<String, Integer> fun2, Function<Integer, Integer> fun3) {
		int i = fun1.andThen(fun2).andThen(fun3).apply(s);
		System.out.println(i);

	}

}

结果:

100

总结

到此这篇关于Java8函数式接口基础学习教程的文章就介绍到这了,更多相关Java8函数式接口内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅析Java8新特性Lambda表达式和函数式接口

    什么是Lambda表达式,java8为什么使用Lambda表达式? "Lambda 表达式"(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数.我们可以把 Lambda表达式理解为是 一段可以传递的代码.最直观的是使用Lambda表达式之后不用再写大量的匿名内部类,简化代码,提高了代码的可读性. // 启动一个线程,不使用Lambda

  • 基于Java8 函数式接口理解及测试

    1. 函数式接口的理解 根据重构的思想,需要把容易变化的模块进行抽象并封装起来,从这个点来看,Java8新引入的函数式接口就是基于这个思想进行设计的. 2. 函数式接口定义 2.1 自定义如下 需要FunctionalInterface关键字显示声明: @FunctionalInterface public interface AppleInterface { public void test(); } 2.2 系统预定义 java.util.function.Consumer; java.ut

  • Java8简单了解Lambda表达式与函数式接口

    Java8被称作Java史上变化最大的一个版本.其中包含很多重要的新特性,最核心的就是增加了Lambda表达式和StreamAPI.这两者也可以结合在一起使用.首先来看下什么是Lambda表达式. 使用Lambda表达式不仅让代码变的简单.而且可读.最重要的是代码量也随之减少很多.然而,在某种程度上,这些功能在Scala等这些JVM语言里已经被广泛使用. 并不奇怪,Scala社区是难以置信的,因为许多Java 8里的内容看起来就像是从Scala里搬过来的.在某种程度上,Java 8的语法要比Sc

  • JAVA8之函数式编程Function接口用法

    从这章开始,会介绍几个常用的函数式接口工具,首先先来看下这个大家族: 首先从Function接口开始介绍 一. 概述 该接口顾名思义,函数的意思,就像是数学,是给定一个参数然后返回结果.该类方法如下: package java.util.function; import java.util.Objects; @FunctionalInterface public interface Function<T, R> { R apply(T t); default <V> Functio

  • 详解JAVA8 函数式接口

    写在前面 Java8中内置了一些在开发中常用的函数式接口,极大的提高了我们的开发效率.那么,问题来了,你知道都有哪些函数式接口吗? 函数式接口总览 这里,我使用表格的形式来简单说明下Java8中提供的函数式接口. 四大核心函数式接口 首先,我们来看四大核心函数式接口,如下所示. 函数式接口 参数类型 返回类型 使用场景 Consumer消费型接口 T void 对类型为T的对象应用操作,接口定义的方法:void accept(T t) Supplier供给型接口 无 T 返回类型为T的对象,接口

  • 实例详解Java8函数式接口

    以下我们继续深入Java8函数式编程模型 public class Test1 { public static void main(String[] args) { List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); list.forEach(new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.prin

  • Java8函数式接口的基础学习教程

    函数式接口 1.1 函数式接口概述 函数式接口:有且仅有一个抽象方法的接口 Java中的函数式编程体现就是Lambda表达式,所以函数式接口就是可以使用与Lambda使用的接口 只有确保接口只能够有且只有一个抽象方法,Lambda才能顺利的进行推导 检测接口是不是函数式接口: @FunctionalInterface 放在接口定义的上方:如果接口是函数式接口,编译通过,反之失败. 注意: 我们自己定义函数式接口的时候,@FunctionalInterface是可选的,就算不写,只要爆炸慢煮函数式

  • Java8函数式接口java.util.function速查大全

    前言 Java 8中有很多新实用的特性,其中就有函数式接口.相信很多小伙伴都是第一次听到这个名词,下面进行函数式接口相关知识的学习. 函数式接口概念 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口. 函数式接口可以被隐式转换为 lambda 表达式. Java 8函数式接口可以对现有的函数友好地支持 lambda. 函数式接口组成 包含三部分: 1.一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数 2.一个箭头符号

  • Java线程编程中Thread类的基础学习教程

    一.线程的状态 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解. 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程包括以下这几个状态:创建(new).就绪(runnable).运行(running).阻塞(blocked).time waiting.waiting.消亡(dead). 当需要新起一个线程来执行某个子任务时,就创建了一个线程.但是线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如内

  • Ruby on Rails中Rack中间件的基础学习教程

    rack是ruby服务器和rack应用程序之间的一个框架,rails,sinatra都是基于rack构建的,都属于rack应用程序. rack提供了一个标准的接口,用于与服务器进行交互.标准的rack程序是一个可以响应call的对象,可以是对象.Proc.lambda甚至是method,它接收env参数(环境对象),返回一个数组,数组包括: 状态(status),http响应状态码 可以是hash,为http的header信息 拥有each方法的对象,each返回字符串 rack通过中间件来进行

  • 简明 Python 基础学习教程

    版本:1.20 A Byte of Python Copyright © 2003-2005 Swaroop C H 简明 Python 教程 <简明 Python 教程>为 "A Byte of Python" 的唯一指定简体中文译本,版权 © 2005 沈洁元 本书依照 创作公用约定(署名-非派生作品-非商业用途) 发布. 概要 无论您刚接触电脑还是一个有经验的程序员,本书都将有助您学习使用Python语言. 前言 本书的读者 本书的由来 本书目前的状况 官方网站 约定

  • Go语言基础学习教程

    本文实例讲述了Go语言基础知识.分享给大家供大家参考,具体如下: GO文件目录结构 该图是go-windows的目录结构 如图,go的程序应该是在gopath文件夹下的,分为bin, pkg, 和src三个子文件夹 src文件夹:每个次级文件夹(如demo)就是代表一个go项目,里面存放源程序 bin文件夹:go的每个项目生成的二进制可执行程序.windows下会生成.exe文件,linux下会生成可执行文件.Go的最大特色之一就是可移植性,就是说,当生成一个demo.exe之后,将这个exe文

  • Three.js基础学习教程

    一.Three.js官网及使用Three.js必备的三个条件 1.Three.js 官网 https://threejs.org/ 2.使用Three.js必备的三个条件 (To actually be able to display anything with Three.js, we need three things: A scene, a camera, and a renderer so we can render the scene with the camera.) 大致意思是使用

随机推荐