@FunctionalInterface
- @FunctionalInterface 不是强制性的,
- 优点1:使接口的含义更加明确
- 优点2:编译器进行代码检查,保证没有预发错误。
- 特点: 有且仅有一个默认的待实现方法(默认的方法 并不是使用default关键字修饰的方法)。
- 注意点:默认方法 VS 默认实现的方法
JAVA为什么引入函数式编程
- 减少了可变量(immutable variable)的声明
- 可以更好的利用并行(parallelism)
- 同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程
- 代码更加简洁 可读性更高
Stream 与 MapReduce 思想上有什么关系
reduce 与 reduce() 有什么区别
@FunctionalInterface的默认函数 与 default关键字的含义有什么区别?
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
// 默认方法
R apply(T t);
// 默认实现的方法
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
}
常用的函数式编程有哪些?
接口 | 默认方法 | 符号描述 | 含义 | 特化 |
---|---|---|---|---|
Predicate< T > | boolean test(T t) | T -> boolean | 谓词性接口,一般用于判断 | IntPredicate ; LongPredicate ; DoublePredicate |
Function<T, R> | R apply(T t); | T->R | 功能型接口,它的一个作用就是转换作用 | … |
Consumer< T > | void accept(T t); | T->void | 传入一个类型值,没有返回值,端子函数使用较多 | IntConsumer,LongConsumer DoubleConsumer |
Supplier | T get(); | ()->T | 当一个容器或者变量,可以存储值 | BooleanSupplier,IntSupplier LongSupplier |
- Function
- Predicate
- Consumer
- Supplier
- Runnable
- Callable
- Comparable
lambda表达式
lambda表达式 其实是一个匿名函数,他是一段没有函数名的函数体
lambda的基本写法是 (params) -> {body}
特点:
- lambda 可以有0个 或 多个参数
- lambda的参数类型可以明确声明,也可以通过上下文推断出参数类型
eg: (int a) 与 (a) 含义是一致的 - 全部参数都包含在 “()” 圆括号内,多个参数使用逗号分隔,仅有一个参数时"()" 圆括号可以省略
- “() -> {sout(“1231”)}” 说明参数为空
- 若body仅有一条语句时,“{}” 大括号可以省略
(param1,param2) -> {dody}
(type1 param1, type2 param2) -> {dody}
eg:
// 有返回值 函数
(int a, int b) -> {return a + b }
() -> {sout("12567890")}
// 无返回函数
(String s) -> {sout(s)};
// 无参函数,
()-> 42
为什么Lambda表达式的函数体内 必须使用final关键字或实际上是final的变量
Stream 流的常见生产方式
- Collection 体系的集合可以使用 xx.stream()的方式生成Stream对象
- 数组可以可以使用 Stream.of(T … values) 生成Stream对象
- Arrays.stream(T[] array)
-
eg: Arrays.stream(values()).filter...
** 抽象类与接口的区别 **
- 抽象类单继承 接口多实现
- 抽象类 有构造函数、有实例属性 、有实例方法、 可以保存状态(state) ; 接口均没有
- lambda 抽象类不能在lambda中使用
- 思想上不同 is-a has-a like-a --忘记了类图的线的含义
- is-a 继承关系, 小孩子都是人 类图表示为 实线 空心三角形
- has-a 标识聚合关系 汽车由发送机 电机 底牌 聚合而成。
- like-a 表示组合关系 虚线 空心三角形
/**
* 学习使用java8 function
*/
@Slf4j
public class TestFunction {
public static void main(String[] args) {
// testConsumer();
testSupplier();
}
/**
* 学习使用Supplier , 返回一个字符串
* <p>
* public void ifPresent(Consumer<? super T> consumer)
* </p>
*/
public static void testSupplier(){
// 方式1 lambda方式
Supplier<String> stringSupplier = () -> UUID.randomUUID().toString().replaceAll("-", "");
log.info("学习使用Supplier lambda result:[{}]",stringSupplier.get());
// 方式1 如果仅一步可以生成supplier 可以通过方法应用的方式创建 supplier
Supplier<UUID> randomUUID = UUID::randomUUID;
log.info("学习使用Supplier lambda result:[{}]",randomUUID.get().toString().replaceAll("-", ""));
//方式2 接口实现的方式实现
Supplier<String> supplier2 = new Supplier<String>() {
@Override
public String get() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
};
log.info("学习使用Supplier lambda result:[{}]",supplier2.get());
}
/**
* 学习使用consumer , 遍历输出学员的名称
* <p>
* public void ifPresent(Consumer<? super T> consumer)
* </p>
*/
public static void testConsumer(){
Result<List<String>> result = new Result<>();
List<String> names = new ArrayList<>(10);
names.add("a");names.add("b");names.add("c");names.add("d");names.add("e");
Optional<List<String>> optional = Optional.of(names);
// public void ifPresent(Consumer<? super T> consumer)
optional.ifPresent(result::setData);
log.debug("testConsumer result1:[{}]", JSONObject.toJSONString(result));
// 方式1 使用lambda实现
Stream<String> streamStr = Stream.of("a", "b", "c", "d", "e", "f", "g", "h");
//lambda表达式返回的就是一个Consumer接口
Consumer<String> consumer1 = (s) -> log.debug("testConsumer lambda name:[{}]",s);;
streamStr.forEach(consumer1);
Consumer consumer3 = System.out::println;
Stream.of("a", "b", "c", "d", "e", "f", "g", "h").forEach(consumer3);
Stream.of("a", "b", "c", "d", "e", "f", "g", "h").forEach(item ->{
log.debug("testConsumer lambda2 name:[{}]",item);
});
// 方式2 使用普通 接口实现的方式
Consumer<String> consumer2 = new Consumer<String>() {
@Override
public void accept(String s) {
log.debug("testConsumer 接口实现的方式 name:[{}]",s);
}
};
Stream.of("a", "b", "c", "d", "e", "f", "g", "h").forEach(consumer2);
}