内容简介:大概一年多之前,我对java8的理解还仅限一些只言片语的文章之上,后来出于对函数式编程的兴趣,买了本参考书看了一遍,然后放在了书架上,后来,当我接手大客户应用的开发工作之后,java8的一些工具,对我的效率有了不小的提升,因此想记录一下java'8的一些常用场景,我希望这会成为一个小字典,能让我免于频繁翻书,但是总能找到自己想找的知识。用于举例的model:这无疑是最常用的功能之一,其实lambda表达式的作用,应该就是简洁明了,实际上是用最短的字符,通过类型推导,语法糖等方式去对编译器描述清楚这段代码的功
大概一年多之前,我对 java 8的理解还仅限一些只言片语的文章之上,后来出于对函数式编程的兴趣,买了本参考书看了一遍,然后放在了书架上,后来,当我接手大客户应用的开发工作之后,java8的一些工具,对我的效率有了不小的提升,因此想记录一下java'8的一些常用场景,我希望这会成为一个小字典,能让我免于频繁翻书,但是总能找到自己想找的知识。
用于举例的model:
@Data
public class Apple {
private Long appleId;
private String appleName;
private Float appleWeight;
private Integer appleClassic;
}
一、Java 8 Lambda 表达式
这无疑是最常用的功能之一,其实lambda表达式的作用,应该就是简洁明了,实际上是用最短的字符,通过类型推导,语法糖等方式去对编译器描述清楚这段代码的功能,这和泛型有点相似,对于编程人员来说,一定程度上也提高了编程效率和代码可读性。
如常用的lambda表达式:
process(()->System.out.println("this is so cool!"))
例如对苹果重量排序:
List<Apple> apples = Lists.newArrayList();
for (int i = 1; i < 10; i++) {
Apple apple = new Apple();
apples.add(apple);
}
apples.sort(Comparator.comparing(Apple::getAppleWeight));
反序:
apples.sort(Comparator.comparing(Apple::getAppleWeight).reversed());
重量相同时:比较等级:
apples.sort(Comparator
.comparing(Apple::getAppleWeight)
.reversed()
谓词复合查询:
Predicate<Apple> a = apple -> apple.getAppleWeight() > 10;
weight10.or(apple -> apple.getAppleClassic() > 2)
.and(apple -> StringUtils.equalsIgnoreCase(apple.getAppleName(), "优质苹果"));
可以看做(a||b)&&c
函数复合:
Function<Apple, Float> f = a -> a.getAppleWeight() + 1;
Function<Float, Float> g = a -> a * 2;
Function<Apple, Float> h = f.andThen(g);
数学写作 h=g(f(x))
Function<Apple, Float> g = a -> a.getAppleWeight() + 1;
Function<Float, Float> f = a -> a * 2;
Function<Apple, Float> h = f.compose(g);
数学写作 h=f(g(x))
小结:java8实际上想传递函数,函数是什么?是一个映射,可以看做x->y,输入x然后映射到值y的过程,
java无法摆脱一切皆是对象的思想,因此函数式依附在对象上传递的,因此也有了下面的说法,方法引用,以及函数式接口,让函数随着对象传递,为了函数式编程,甚至专门写一个接口---对象来传递函数。然而,函数才是主角。
二、Java 8 方法引用
方法引用十分简单,其实也是将方法作为参数传递。使用::域作用符,将一段方法传递。
举例:Apple::getAppleId
String::subString System.out::println
三、Java 8 函数式接口 函数式编程
利用java进行函数式编程主要就是利用函数式接口,但是函数式接口在java8之前就有一些了,就例如多线程的runnable,但是8以前是没有lambda表达式的,所以只能使用匿名内部类,在用过lambda表达式的人看来,那是相当臃肿的,8更新了lambda表达式,这就使函数式编程更上一层楼.
java8的函数式接口为我们传递函数提供了工具,我们可以自己定义函数式接口,然后让其他人,或者是java API调用。
关于函数接口,需要记住的就是两件事:
函数接口是行为的抽象;
函数接口是数据转换器。
四、Java 8 Stream
在我接触到java8流式处理的时候,我的第一感觉是流式处理让集合操作变得简洁了许多,通常我们需要多行代码才能完成的操作,借助于流式处理可以在一行中实现。其本质是,将一些原本开发者需要做的处理如迭代等,放在了java库里,让我们只关心自己的业务逻辑,比如我们希望对一个包含整数的集合中筛选出所有的偶数,并将其封装成为一个新的List返回,那么在java8之前,我们需要通过如下代码实现:
过去:
List<Integer> evens = new ArrayList<>();
for (final Integer num : nums) {
if (num % 2 == 0) {
evens.add(num);
}
}
stream实现:
List<Integer> evens = nums.stream().filter(num -> num % 2 == 0).collect(Collectors.toList());
我们需要取出10个等级高于3的苹果,跳过其中两个,按重量排序,去重,然后取出苹果的Name,然后取出名字的每个字符:
List<String> appleName = apples.parallelStream()
.filter(a -> a.getAppleClassic() < 2)
.sorted(Comparator.comparing(Apple::getAppleWeight))
.map(Apple::getAppleName)
.map(s -> s.split(""))
.limit(10)
.skip(2)
.distinct()
.flatMap(Arrays::stream)
.collect(Collectors.toList());
构造AppleId ApppleName Map:
Map<Long, String> appleIdMap = apples.stream()
.collect(Collectors.toMap(Apple::getAppleId, Apple::getAppleName, (s, s2) -> s.length() > s2.length() ? s : s2));
谓词查找:
if (appleName.stream().anyMatch(a -> StringUtils.equalsIgnoreCase(a, "一级苹果")));
if (appleName.stream().allMatch(a -> StringUtils.equalsIgnoreCase(a, "一级苹果")));
if (appleName.stream().noneMatch(a -> StringUtils.equalsIgnoreCase(a, "一级苹果")));
短路查找:
appleName.stream()
.filter(a -> StringUtils.equalsIgnoreCase(a, "一级苹果"))
.findAny()
.ifPresent(System.out::println);
findfirst在并行时限制多一些,如果不在意返回的是哪个元素,使用findAny。
求和:
apples.stream()
.map(Apple::getAppleWeight)
.reduce(0F, (a, b) -> a + b);
计数:
apples.stream().count();
使用stream的好处:
1.更简洁,更易读
2.可复合,更灵活
3.可并行
五、Java 8 Optional 类
Optional着重为解决java的NPE问题是Java8提供的为了解决null安全问题的一个API。善用Optional可以使我们代码中很多繁琐、丑陋的设计变得十分优雅。
使用Optional,我们就可以把下面这样的代码进行改写:
public static String getName(User u) {
if (u == null)
return "Unknown";
return u.name;
}
不过,千万不要改写成这副样子。
public static String getName(User u) {
Optional<User> user = Optional.ofNullable(u);
if (!user.isPresent())
return "Unknown";
return user.get().name;
}
这样才是正确使用Optional的姿势。那么按照这种思路,我们可以安心的进行链式调用,而不是一层层判断了。
public static String getName(User u) {
return Optional.ofNullable(u)
.map(user->user.name)
.orElse("Unknown");
}
看一段代码:
public static String getChampionName(Competition comp) throws IllegalArgumentException {
if (comp != null) {
CompResult result = comp.getResult();
if (result != null) {
User champion = result.getChampion();
if (champion != null) {
return champion.getName();
}
}
}
throw new IllegalArgumentException("The value of param comp isn't available.");
}
让我们看看经过Optional加持过后,这些代码会变成什么样子。
public static String getChampionName(Competition comp) throws IllegalArgumentException {
return Optional.ofNullable(comp)
.map(c->c.getResult())
.map(r->r.getChampion())
.map(u->u.getName())
.orElseThrow(()->new IllegalArgumentException("The value of param comp isn't available."));
}
还有很多不错的使用姿势,比如为空则不打印可以这么写:
string.ifPresent(System.out::println);
参考资料:《Java 8 in Action: Lambdas, streams, and functional-style programming》 Raoul-gabriel Urma (作者), Mario Fusco (作者), Alan Mycroft (作者)
作者:文烁
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Writing Apache Modules with Perl and C
Lincoln Stein、Doug MacEachern / O'Reilly Media, Inc. / 1999-03 / USD 39.95
Apache is the most popular Web server on the Internet because it is free, reliable, and extensible. The availability of the source code and the modular design of Apache makes it possible to extend Web......一起来看看 《Writing Apache Modules with Perl and C》 这本书的介绍吧!