Java SE Function接口&Lambda
目录
1、Lambda表达式
Lambda表达式是一个匿名函数, 我们可以把Lambda表 达式理解为是一段可以传递的代码(将代码像数据一样 进行传递) 。
1、语法 ( 形参列表 )->{ 操作集合 } ;
2、演变过程 , Lambda本质 -> 就是一个接口中的唯一的那个方法的实现
左侧:Lambda表达式的参数列表。对应接口中抽象方法的参数列表。
右侧:Lambda表达式中所需要执行的功能,即Lambda体。对应接口中抽象方法的实现。
注意:Lambda表达式需要函数式接口的支持
public class Demo002 {
public static void main(String[] args) {
Fly something = ()->{System.out.println("飞行");};
}
}
interface Fly{
void fly();
}
2、函数式接口
- 接口中有且仅有一个抽象方法的接口,称为函数式接口。
- 可以使用注解@FunctionalInterface 修饰,可以检查是否是函数式接口。
- Lambda表达式需要函数式接口的支持
//函数式接口
interface NoParamNoResult{
void test();
}
2.1 四大内置函数接口
- 消费型接口 Consumer void accept(T t) 只进不出
- 供给型接口 Supplier T get() 白手起家,空手套白狼
- 函数型接口 Function<T,R> R apply(T t) 礼尚往来
- 断定型接口 Predicate boolean test(T t) 鉴定评审
2.2、Consumer (1参无回值)
带一个参数,在方法体中使用完了就完了,例如在Collection中的 forEach 方法则需要一个Consumer接口的实现类对象。
Collection<String> list = new ArrayList<>();
list.add("AAAAAA");
list.add("BBBBBB");
list.add("CCCCCC");
list.forEach(t-> System.out.println(t));
//消费型接口定义
public static void getComsumer(Integer i1, Consumer<Integer> cn){
cn.accept(i1);
}
//消费费型的
getComsumer(23,(i1)->System.out.println(i1) );
2.3、Supplier T get() 无参有回值
// 需求:产生指定个数的整数,并放入集合中
@Test
public void test2() {
List<Integer> numList = getNumList(10, ()-> (int)(Math.random() * 100));
for (Integer integer : numList) {
System.out.println(integer);
}
}
//供给型
public static Integer getSupplier(Supplier<Integer> sup){
return sup.get();
}
//供给型
System.out.println(getSupplier(()->12));
2.4、Function<T,R> R apply(T t)
- 礼尚往来
/* * Function<T, R> 函数型接口 * R apply(T t); */
// 需求:用于处理字符串
@Test
public void test3() {
String newStr = strHandler(" shsxt ", (str) -> {return str.trim();});
System.out.println(newStr);
newStr = strHandler("shsxt", (str) ->str.substring(2, 5));
System.out.println(newStr);
}
public String strHandler(String str, Function<String, String> fun) {
return fun.apply(str);
}
//函数型
public static Double getFunction(Double d1, Function<Double,Double> fun){
return fun.apply(d1);
}
//函数型
System.out.println(getFunction( 4.0,(d3)->{return Math.sqrt(d3);} ));
2.5 Predicate boolean test(T t)
- 鉴定评审
/* * Predicate<T> 断言型接口 * boolean test(T t); */
// 需求:将满足条件的字符串,放入集合中2
public void test(){
Predicate<Integer> pre = (i) -> i>1; System.out.println(pre.test(5));
}
public void test4() {
List<String> list = Arrays.asList("hello", "orange", "Lambda", "www", "ok");
List<String> strList = filterStr(list, (s)-> s.length() > 3);
for (String string : strList) {
System.out.println(string);
}
}
public List<String> filterStr(List<String> list, Predicate<String> pre) {
List<String> strList = new ArrayList<>();
for (String string : list) {
if(pre.test(string)) {
strList.add(string);
}
}
return strList;
}
//断定型
public static boolean getPredicate(Predicate<List<Integer>> pr){
List<Integer> list=List.of(1,2,3,4,5,6,7,8,9,10);
return pr.test(list);
}
//断定型
System.out.println(getPredicate((lst)->{
boolean b=false;
for (Integer s: lst) {
if (s>9){
return false;
}
}
return true;
}));
3、方法引用 ::
- 为了简化Lambda表达式
- 可以认为方法引用是lambda表达式的另一种表现形式
- lmabda接口: ()->{}
- 使用要求:
当lambda体的实现就是通过调用其他方法实现的时候,lambda的结构就可以使用方法引用简化,直接引用那个方法就可以。
3.1、方法引用使用
Comparator<Integer> com = (x, y)->x-y; //不能使用方法引用简化
com = (x,y)->LambdaCode3.test(x,y); //可以使用方法引用简化
com = LambdaCode3::test;
static int test(int x,int y){
return x-y;
}
3.1.1、对象 : : 成员方法 :
- 1)lambda体是否通过引用另外一个方法实现的
- 2)并且抽象方法的参数列表作为方法内部所引用的方法的参数列表的时候,并且所引用方法的返回值与抽象方法的返回值保持一致保持一致
//消费型接口定义
public static void getComsumer(Integer i1, Consumer<Integer> cn){
cn.accept(i1);
}
/对象::成员方法
//lmabda {} 中的行为是不是通过调用另外一个方法实现的 : 是通过调用println()方法实现的打印
test1();
//把集合中的每一个数据拿出来当做Consumer中accept的参数传递,写的方法 体就是把每一个参数打印输出
List.of(1,3,2,5,6,4).forEach(System.out::print);
List.of(1,3,2,5,6,4).forEach( s -> System.out.println(s));
3.1.2、类名::静态方法
- 1)lambda体是否通过引用另外一个方法实现的
- 2)lambda的参数列表与返回值是否匹配引用方法的参数列表与返回值
- 3)是静态方法->类名::静态方法
//类名::静态方法
//考虑是否能够使用方法引用简化:
// 1)lambda体是否通过引用另外一个方法实现的->是
// 2)lambda的参数列表与返回值是否匹配引用方法的参数列表与返回值->是
// 3)是静态方法->类名::静态方法
BiFunction<Double,Double,Double> fun = (a,b)->Math.max(a,b);
System.out.println(fun.apply(12.0,13.0));
3.1.3、类名::成员方法 :
-
1)lambda体是否是通过引用另外一个方法实现的
-
2)抽象的参数列表的第一个参数是否作为调用内部所引用方法的对象存在
-
3)抽象方法参数列表的第二参数及以后是否与所引用方法的参数列表保持一致,返回值保持一致
-
4)引用的方法时成员方法
//类名::成员方法
//方法引用简化
//判断是否可以使用类名::成员方法简化:
// 1)lambda体是否是通过引用另外一个方法实现的
// 2)抽象的参数列表的第一个参数是否作为调用内部所引用方法的对象存在
// 3) 抽象方法参数列表的第二参数及以后是否与所引用方法的参数列表保持一致,返回值保持一致
// 4) 引用的方法时成员方法
BiPredicate<String,String> pre = String::equals;
System.out.println(pre.test("zhangsan","zhangsan"));
//放法引用简化
System.out.println(getFunction(4,Math::sqrt));
//函数型
public static Double getFunction(Integer i1, Function<Integer,Double> fun){
return fun.apply(i1);
}
3.1.4、构造器引用:
- (s)-> new String(s)
- 数据类型::new
//构造器引用 : lambda体是通过new关键字实现的,并且创建的对象就作为抽象方法的返回值存在
//Supplier<String> sup = ()->new String();
Supplier<String> sup = String::new; //因为接口中的抽象方法没有参数列表,匹配的构造器就没有参数列表
System.out.println(sup.get().length());
//Function<String,String> fun = (s)-> new String(s);
Function<String,String> fun = String::new; //因为抽象方法存在一个参数,匹配的构造器就是一个带参构造
3.1.5、数组引用:
- (i)->new String[i]
- 素组类型[]::new
//数组引用
//Function<Integer,String[]> sup2 = (i)->new String[i];
Function<Integer,String[]> sup2 = String[]::new;
System.out.println(sup2.apply(10).length);
System.out.println(Arrays.toString(sup2.apply(10)));