JDK8函数式编程快速入门干货.docx

上传人:b****8 文档编号:10388659 上传时间:2023-02-10 格式:DOCX 页数:14 大小:21.60KB
下载 相关 举报
JDK8函数式编程快速入门干货.docx_第1页
第1页 / 共14页
JDK8函数式编程快速入门干货.docx_第2页
第2页 / 共14页
JDK8函数式编程快速入门干货.docx_第3页
第3页 / 共14页
JDK8函数式编程快速入门干货.docx_第4页
第4页 / 共14页
JDK8函数式编程快速入门干货.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

JDK8函数式编程快速入门干货.docx

《JDK8函数式编程快速入门干货.docx》由会员分享,可在线阅读,更多相关《JDK8函数式编程快速入门干货.docx(14页珍藏版)》请在冰豆网上搜索。

JDK8函数式编程快速入门干货.docx

JDK8函数式编程快速入门干货

Java8引入函数式编程,极大地提高了编码效率,对于习惯了原有Java代码风格的coder,确实需要好好熟悉一番才能熟练地coding。

本文每一条讲解都配置了最简短的代码,适合快速入门或者字典使用,但阅读之后还是需要多看函数原型多看源码,灵活使用为好。

函数式编程语法

以Consumer作为示例,它是一个函数式接口,包含一个抽象方法accept。

现在要定义一个Consumer对象,传统方式是这样的:

Consumerc=newConsumer(){

@Override

publicvoidaccept(Objecto){

System.out.println(o);

}

};

而使用函数式编程,可以这样定义:

Consumerc=(o)->{

System.out.println(o);

};

亦或者:

Consumerc=(o)->System.out.println(o);

简单理解函数式对象本质上还是一个对象,可以看做是其他方法的参数或者返回值,所以上面代码实际上可以这样:

Consumerc=System.out:

:

println;

常见的Java函数式接口

Consumer

顾名思义,Consumer的意思就是消费,即针对某个东西我们来使用它,因此它包含一个有形参无返回值的accept接口方法。

除了accept方法,还包含andThen这个方法,可以连续调用多个Consumer

publicstaticvoidconsumerTest(){

Consumerf1=System.out:

:

println;

Consumerf2=n->System.out.println(n+"-F2");

//执行f2之后,连续执行两次f2的Accept方法

f2.andThen(f1).andThen(f1).accept("test1");}

Supplier

Supplier代表的含义是“提供者”,因此它含有一个get方法,没有入参只能输出

Suppliersupplier=()->"Testsupplier";

supplier.get();

Function

Function也是一个函数式编程接口;它代表的含义是“函数”,而函数经常是有输入输出的,因此它含有一个apply方法,包含一个入参与一个返回值,可以用作装箱或者拆箱某个对象

/**

*Function测试

*/

publicstaticvoidfunctionTest(){

Functionf=s->s++;

Functiong=s->s*2;

/**

*下面表示在执行F时,先执行G,并且执行F时使用G的输出当作输入。

*相当于以下代码:

*Integera=g.apply

(1);

*System.out.println(f.apply(a));

*/

System.out.println(pose(g).apply

(1));

/**

*表示执行F的Apply后使用其返回的值当作输入再执行G的Apply;

*相当于以下代码

*Integera=f.apply

(1);

*System.out.println(g.apply(a));

*/

System.out.println(f.andThen(g).apply

(1));

/**

*identity方法会返回一个不进行任何处理的Function,即输出与输入值相等;

*/

System.out.println(Function.identity().apply("a"));}

Predicate

Predicate为函数式接口,predicate的中文意思是“断定”,意为判断某个东西是否满足某种条件;因此它包含test方法,根据输入值来做逻辑判断,其结果为True或者False,可以用作过滤对象

/**

*Predicate测试

*/privatestaticvoidpredicateTest(){

Predicatep=o->o.equals("test");

Predicateg=o->o.startsWith("t");

/**

*negate:

用于对原来的Predicate做取反处理;

*如当调用p.test("test")为True时,调用p.negate().test("test")就会是False;

*/

Assert.assertFalse(p.negate().test("test"));

/**

*and:

针对同一输入值,多个Predicate均返回True时返回True,否则返回False;

*/

Assert.assertTrue(p.and(g).test("test"));

/**

*or:

针对同一输入值,多个Predicate只要有一个返回True则返回True,否则返回False

*/

Assert.assertTrue(p.or(g).test("ta"));}

BinaryOperator

BinaryOperator接口用于执行lambda表达式,接受两个T类型的参数并返回一个T类型的返回值。

BinaryOperator中有两个静态方法,是用于比较两个数字或字符串的大小

minBy()获取更小的值,maxBy()获取更大的值。

示例如下:

BinaryOperatoradd=(n1,n2)->n1+n2;

System.out.println(add.apply(1,2));//3

System.out.println(BinaryOperator.maxBy(Integer:

:

compareTo).apply(1,2));//2

UnaryOperator

UnaryOperator继承于java.util.function.Function。

UnaryOperator接收一个T类型参数,并返回T类型的参数

UnaryOperatorddb=x->x+1;

System.out.println(ddb.apply("abc"));//abc1

函数式编程接口的使用

Stream类

Java8中,引入了流(Stream)的概念,这个流和以前我们使用的IO中的流并不太相同。

所有继承自Collection的接口都可以转换为Stream。

Stream的方法分为两类。

一类叫惰性求值,一类叫及早求值。

判断一个操作是惰性求值还是及早求值很简单:

只需看它的返回值。

如果返回值是Stream,那么是惰性求值。

其实可以这么理解,如果调用惰性求值方法,Stream只是记录下了这个惰性求值方法的过程,并没有去计算,等到调用及早求值方法后,就连同前面的一系列惰性求值方法顺序进行计算,返回结果。

Stream.惰性求值.惰性求值.....惰性求值.及早求值

Stream对象的创建

创建空的Stream对象

Streamstream=Stream.empty();

通过集合类中的stream或者parallelStream方法创建

Listlist=Arrays.asList("a","b","c","d");

StreamlistStream=list.stream();//获取串行的Stream对象

StreamparallelListStream=list.parallelStream();//获取并行的Stream对象

Stream具有平行处理能力,处理的过程会分而治之,也就是将一个大任务切分成多个小任务,这表示每个任务都是一个操作。

所以parallelListStream.forEach(out:

:

println)的输出结果不一定是abcd。

如果想要按照原本的stream顺序,可以使用parallelListStream.forEachOrdered(out:

:

println)

通过Stream中的of方法创建

Streams=Stream.of("a","b","c","d");

通过Stream中的iterate方法创建

Stream.iterate(1,item->item+1).limit(10).forEach(System.out:

:

println);

这段代码就是先获取一个无限长度的正整数集合的Stream,然后取出前10个打印。

千万记住使用limit方法,不然会无限打印下去。

通过Stream中的generate方法创建

Stream.generate(()->{

System.out.println("test");

returnMath.random();

}).limit(5).forEach(System.out:

:

println);

通过Stream中的concat方法连接两个Stream对象生成新的Stream对象

concat方法将两个Stream连接在一起,合成一个Stream。

若两个输入的Stream都是串行的,则新Stream也是串行的;若输入的Stream中任何一个是并行的,则新的Stream也是并行的

Stream.concat(Stream.of(1,2,3),Stream.of(4,5))

.forEach(integer->System.out.print(integer+""));//12345

Stream对象的函数列表

Stream对象提供多个非常有用的方法,这些方法可以分成两类:

中间操作:

将原始的Stream转换成另外一个Stream;如filter返回的是过滤后的Stream。

终止操作:

产生的是一个结果或者其它的复合操作;如count或者forEach操作。

方法都列举出来,但不是要求倒背如流,只是希望不重复造轮子

中间操作列表:

方法名

说明

sequential

返回一个相等的串行的Stream对象,如果原Stream对象已经是串行就可能会返回原对象

parallel

返回一个相等的并行的Stream对象,如果原Stream对象已经是并行的就会返回原对象

unordered

返回一个不关心顺序的Stream对象,如果原对象已经是这类型的对象就会返回原对象

onClose

返回一个相等的Steam对象,同时新的Stream对象在执行Close方法时会调用传入的Runnable对象

close

关闭Stream对象

mapToInt

元素一对一转换:

将原Stream中的使用传入的IntFunction加工后返回一个IntStream对象

distinct

去重:

返回一个去重后的Stream对象

sorted

排序:

返回排序后的Stream对象

peek

使用传入的Consumer对象对所有元素进行消费后,返回一个新的包含所有原来元素的Stream对象

limit

获取有限个元素组成新的Stream对象返回

skip

抛弃前指定个元素后使用剩下的元素组成新的Stream返回

takeWhile

如果Stream是有序的(Ordered),那么返回最长命中序列(符合传入的Predicate的最长命中序列)组成的Stream;如果是无序的,那么返回的是所有符合传入的Predicate的元素序列组成的Stream

dropWhile

与takeWhile相反,如果是有序的,返回除最长命中序列外的所有元素组成的Stream;如果是无序的,返回所有未命中的元素组成的Stream

终止操作列表:

方法名

说明

iterator

返回Stream中所有对象的迭代器

spliterator

返回对所有对象进行的spliterator对象

forEach

对所有元素进行迭代处理,无返回值

forEachOrdered

按Stream的Encounter所决定的序列进行迭代处理,无返回值

toArray

返回所有元素的数组

min

返回所有元素中最小值的Optional对象;如果Stream中无任何元素,那么返回的Optional对象为Empty

max

与min相反

count

所有元素个数

anyMatch

只要其中有一个元素满足传入的Predicate时返回True,否则返回False

allMatch

所有元素均满足传入的Predicate时返回True,否则False

noneMatch

所有元素均不满足传入的Predicate时返回True,否则False

findFirst

返回第一个元素的Optioanl对象;如果无元素返回的是空的Optional;如果Stream是无序的,那么任何元素都可能被返回

findAny

返回任意一个元素的Optional对象,如果无元素返回的是空的Optioanl

isParallel

判断是否当前Stream对象是并行的

常用函数示例

map

接收一个Funcation参数,用其对Stream中的所有元素进行处理,返回的Stream对象中的元素为Function对原元素处理后的结。

示例如下:

Streams=Stream.of("t1","t2");

s.map(n->n.concat(".txt")).forEach(System.out:

:

println);//ti.txtt2.txt

flatMap

元素一对多转换:

对原Stream中的所有元素使用传入的Function进行处理,每个元素经过处理后生成一个多个元素的Stream对象,然后将返回的所有Stream对象中的所有元素组合成一个统一的Stream并返回;

Streams=Stream.of("1t1","2t2");

s.flatMap(n->Stream.of(n.split("t"))).forEach(System.out:

:

println);//1122

filter

用于对Stream中的元素进行过滤,返回一个过滤后的Stream

Streams=Stream.of("t1","t2","aaa");

s.filter(n->n.contains("t")).forEach(System.out:

:

println);//t1t2

reduce

map用来归类,结果一般是一组数据,比如可以将list中的学生分数映射到一个新的stream中;reduce用来计算值,结果是一个值,比如计算最高分

ListpersonList=Arrays.asList(

newPerson(1,18,"小明"),

newPerson(1,19,"小强"),

newPerson(1,20,"小刚"),

newPerson(1,19,"小王"))

.stream()

.collect(Collectors.toList());

personList.stream()

.reduce((person1,person2)->person1.getAge()>person2.getAge()?

person1:

person2

.ifPresent((person)->System.out.println(JSON.toJSON(person)));

collect

可以将stream元素转换为不同类型的结果(List,Set,Map)。

转list用Collectors.toList();转set使用Collectors.toSet()。

示例(转List):

ListpersonList=Arrays.asList(

newPerson(1,18,"小明"),

newPerson(1,19,"小强"),

newPerson(1,19,"小王"))

.stream()

.filter(person->{

returnperson.getAge()==19;

})

.collect(Collectors.toList());

personList.forEach(person->System.out.println(person.getName()));

示例(转map):

Map>personMap=Arrays.asList(

newPerson(1,18,"小明"),

newPerson(1,19,"小强"),

newPerson(1,19,"小王"))

.stream()

.collect(Collectors.groupingBy(p->p.getAge()));

personMap.forEach((age,person)->System.out.println(age+":

"+JSON.toJSON(person)));

Optional类

这个类主要用来简化对空值的判断处理。

Optional实际上是对一个变量进行封装,它包含有一个属性value,实际上就是这个变量的值。

Optioanl对象的创建

它的默认构造函数是private类型的,因此要初始化一个Optional的对象无法通过其构造函数进行创建。

它提供了一系列的静态方法用于构建Optional对象:

empty

用于穿见一个空的Optional对象,其value属性为null。

例如:

Optionalo=Optional.empty();

of

根据传入的值构建一个Optional对象。

传入的值必须是非空值,否则如果传入的值为空值,则会抛出空指针异常。

例如:

o=Optional.of("test");

ofNullable

根据传入值构建一个Optional对象。

传入的值可以是空值,如果传入的值是空值,则与empty返回的结果是一样的。

Optional的使用

常用函数列表

方法名

说明

get

获取Value的值,如果Value值是空值,则会抛出NoSuchElementException异常;因此返回的Value值无需再做空值判断,只要没有抛出异常,都会是非空值

isPresent

Value是否为空值的判断

ifPresent

当Value不为空时,执行传入的Consumer

ifPresentOrElse

Value不为空时,执行传入的Consumer;否则执行传入的Runnable对象;

filter

当Value为空或者传入的Predicate对象调用test(value)返回False时,返回Empty对象;否则返回当前的Optional对象

map

一对一转换:

当Value为空时返回Empty对象,否则返回传入的Function执行apply(value)后的结果组装的Optional对象;

flatMap

一对多转换:

当Value为空时返回Empty对象,否则传入的Function执行apply(value)后返回的结果(其返回结果直接是Optional对象)

or

如果Value不为空,则返回当前的Optional对象;否则,返回传入的Supplier生成的Optional对象;

stream

如果Value为空,返回Stream对象的Empty值;否则返回Stream.of(value)的Stream对象;

orElse

Value不为空则返回Value,否则返回传入的值;

orElseGet

Value不为空则返回Value,否则返回传入的Supplier生成的值;

orElseThrow

Value不为空则返回Value,否则抛出Supplier中生成的异常对象;

简单示例

变量为空,则提供默认值

Mapmap=newHashMap<>();

map.put(1,"大米");

map.put(2,"小米");

map.put(3,"黑米");

Stringname=Optional.ofNullable(map.get(4)).orElse("none");

System.out.println(name);//none

如果用原本的代码写,就是这样的:

if(map.get(4)==null){

return"none";

}else{

returnmap.get(4);

}

如果变量为空时,抛异常的话

Optional.ofNullable(map.get(4)).orElseThrow(()->newException("test"));

如果变量为不为空则可以使用

如果按照原来的写法,如果不判断变量是否为空,并调用变量的成员方法的话,函数会抛空指针异常

Optional.ofNullable(map.get(4)).ifPresent(System.out:

:

println);

如果变量不为空则返回一定规则的返回值

returnuser.map(u->u.getUsername())

.map(name->name.toUpperCase())

.orElse(null);

如果上面这段转换成平时的Java代码,则变成这样:

Useruser=newUser....

if(user!

=null){

Stringname=user.getUsername();

if(name!

=null){

returnname.toUpperCase();

}else{

returnnull;

}

}else{

returnnull;

}

(哇,4000字的博客你都看得完。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 人力资源管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1