java8函数式编程
一 、什么是函数式编程
1、每个人对函数式编程的理解不尽相同。
但其核心是:在思考问题时,使用不可变值和函数,函数对一个值进行处理,映射成另一个值。
Lambda 表达式是一个匿名方法,将行为像数据一样进行传递。
2、编写不同形式的Lambda表达式:
Runnable noArguments = () -> System.out.println("Hello World");
所示的 Lambda 表达式不包含参数,使用空括号 () 表示没有参数。该 Lambda 表达式 实现了 Runnable 接口,该接口也只有一个 run 方法,没有参数,且返回类型为 void。
ActionListener oneArgument = event -> System.out.println("button clicked");
所示的 Lambda 表达式包含且只包含一个参数,可省略参数的括号,这和例 2-2 中的 形式一样
Runnable multiStatement = () -> {
System.out.print("Hello");
System.out.println(" World");
};
Lambda 表达式的主体不仅可以是一个表达式,而且也可以是一段代码块,使用大括号 ({})将代码块括起来,如上图所示。该代码块和普通方法遵循的规则别无二致,可以用返 回或抛出异常来退出。只有一行代码的 Lambda 表达式也可使用大括号,用以明确 Lambda
表达式从何处开始、到哪里结束
BinaryOperator<Long> add = (x, y) -> x + y;
ambda 表达式也可以表示包含多个参数的方法,如上所示。这时就有必要思考怎样去阅 读该 Lambda 表达式。这行代码并不是将两个数字相加,而是创建了一个函数,用来计算 两个数字相加的结果。变量 add 的类型是 BinaryOperator<Long>,它不是两个数字的和, 而是将两个数字相加的那行代码。
BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;
所有 Lambda 表达式中的参数类型都是由编译器推断得出的。这当然不错,但有时最好也可以显式声明参数类型,此时就需要使用小括号将参数括起来,多个参数的情况也是如此.
final String[] array = { "hello", "world" };
等号右边的代码并没有声明类型,系统根据上下文推断出类型信息
artist -> artist.getName()
简化成(方法引用)
Artist::getName
创建一个 Artist 对象
(name, nationality) -> new Artist(name, nationality)
简化成
Artist::new (这种方式创建数组String[]::new)
直接调用foo方法
x -> foo(x)
3、 引用值,而不是变量
String name = getUserName();
button.addActionListener(event -> System.out.println("hi " + name));
Lambda 表达式中引用的局部变量必须是 final 或既成事实上的 final 变量,,即该变量不能被多次赋值!
4、函数接口
函数接口指仅具有单个抽象方法的接口,用来表示Lambda表达式的类型。
Predicate 接口的源码,接受一个对象,返回一个布尔值
public interface Predicate<T> {
boolean test(T t);
}
Predicate<Integer> atLeast5 = x -> x > 5;
二、类库
1、在代码中使用Lambda表达式
使用 isDebugEnabled 方法降低日志性能开销
Logger logger = new Logger(); if (logger.isDebugEnabled()) {
logger.debug("Look at this: " + expensiveOperation()); }
使用 Lambda 表达式简化日志代码 Logger logger = new Logger();
logger.debug(() -> "Look at this: " + expensiveOperation());
2、其他方法
package com.dy.spring.boot.domian;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Person {
private Integer id;
private String name;
public Person(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
List<Person> list = new ArrayList();
list.add(new Person(1, "name1"));
list.add(new Person(2, "name2"));
list.add(new Person(3, "name3"));
//collect(toList())----------由 Stream 里的值生成一个列表,是一个及早求值操作----------start
List<String> collected = Stream.of("a", "b", "c").collect(Collectors.toList());
//collect(toList())----------由 Stream 里的值生成一个列表,是一个及早求值操作----------end
//map +++++++++++++++++++++++++++++++++start
//如果有一个函数可以将一种类型的值转换成另外一种类型,map 操作就可以 使用该函数,将一个流中的值转换成一个新的流
List<String> names = list.stream().map(Person::getName).collect(Collectors.toList());
//map +++++++++++++++++++++++++++++++++end
//filter----------------------start-----------------
//过滤集合中的元素,去除元素中的集合。
List<Person> p2_list = list.stream().filter(o -> o.getId() > 1).collect(Collectors.toList());
p2_list.stream().forEach(p -> {
System.out.println(p.name);
});
//统计集合元素满足条件的数量
long count = list.stream()
.filter(p -> p.id > 1)
.count();
System.out.println("count = " + count);
//filter 时进行其他操作
count = list.stream()
.filter(p -> {
System.out.println(p.name);
return p.id > 1;
})
.count();
//filter----------------------end------------------
//flatMap 方法可用 Stream 替换值,然后将多个 Stream 连接成一个 Stream~~~~~~~~~~~~~~~~~~~~~~~~start
//map 生成的是个 1:1 映射,每个输入元素,都按照规则转换成为另外一个元素。还有一些场景,是一对多映射关系的,这时需要 flatMap
Stream<List<Integer>> inputStream = Stream.of(
Arrays.asList(1),
Arrays.asList(2, 3),
Arrays.asList(4, 5, 6)
);
List<Integer> outList = inputStream.flatMap((childList) -> childList.stream()).collect(Collectors.toList());
System.out.println("flatMap-> " + outList);
list.stream().peek(o -> System.out.println(o.getId()));
//flatMap 方法可用 Stream 替换值,然后将多个 Stream 连接成一个 Stream~~~~~~~~~~~~~~~~~~~~~~~~end
//max和min、reduce*******************start
// Stream 中的 findAny等方法等返回 Optional 值。还有例如 IntStream.average() 返回 OptionalDouble 等等。
// 可以将集合中的元素组合起来,例如:字符串拼接,数值的sum,min,max,average都是特殊的reduce。
System.out.println("findFirst:" + list.stream().findFirst().get().getName());
System.out.println("max : " + list.stream().max(Comparator.comparing(p->p.id)).get().name);
System.out.println("min : " + list.stream().min(Comparator.comparing(p->p.id)).get().name);
//reduce 操作可以实现从一组值中生成一个值
int sum = Stream.of(1, 2, 3).reduce(0, (acc, element) -> acc + element);
//结果是0+1+2+3=6
System.out.println("reduce : " +sum);
//max和min *******************end
//imit返回Stream的前n个元素,skip则是舍弃前n个元素
//[3,2,1]
System.out.println(Arrays.asList(5, 4, 3, 2, 1).stream().skip(2).collect(Collectors.toList()));
//[5,4]
System.out.println(Arrays.asList(5, 4, 3, 2, 1).stream().limit(2).collect(Collectors.toList()));
//对元素进行排序,强大之处在于可以对Stream类进行map,filter,limit,skip,distinct之后在进行排序,提高效率。
//返回1、2、3
System.out.println(Arrays.asList(5, 4, 3, 2, 1).stream().skip(2).sorted(Integer::compare).collect(Collectors.toList()));
}
}
以上是 java8函数式编程 的全部内容, 来源链接: utcz.com/z/517700.html