java8常用函数式接口
import java.util.function.Supplier;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
- Supplier
@FunctionalInterface
public interface Supplier<T> {
T get(); // 无参,有返
}
- Consumer
@FunctionalInterface
public interface Consumer<T> {
void accept(T t); // 有参,无返
// 默认方法
}
- Function
@FunctionalInterface
public interface Function<T, R> {
R apply(T t); // 有参,有返
// 默认方法、static方法
}
- BiConsumer
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
// 默认方法
}
- BiFunction
@FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T t, U u);
// 默认方法
}
- Predicate
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
// 默认方法
}
// Bi开头的,BiConsumer和 BiFunction,都至少接受两个参数。而Consumer和 Function都是一个参数。
java8常用stream API
- filter
stream().filter(Predicate p); 要求传入 Predicate,有参数,且返回布尔值,并生成原类型的stream流。
- map
stream().map(Function mapper); 要求传入Function, 有参数,有返回值。 map会对每一个元素映射为另一个返回值,并生成新类型的stream流。
- peek
stream().peek(Consumer action); 要求传入Consumer,有参数,无返回值。 peek会操作每一个元素,但返回原来的流。
- forEach
stream().forEach(Consumer action);要求传入Consumer,有参数,无返回值。但forEach不再返回流了,是一个流结束函数。
- collect
stream().collect(); 有两个重载方法参数列表,都不再返回流,而是返回某种集合类型。
<R> R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner);
<R, A> R collect(Collector collector);
// Collector接口中,也规范了supplier(),accumulator(),combiner()方法,本质和上面差不多
- toMap
stream().collect(Collectors.toMap());
Collectors.toMap(), 有三个重载方法参数列表
// 两个Function类型参数 key,value, 实际上是去调用另一个重载方法,throwingMerger():当key相同时,会抛出异常;
Collector toMap(Function keyMapper, Function valueMapper) {
return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
// 两个Function类型参数 key,value + 一个父类为BiFunction的mergeFunction,BiFunction接收两个参数,聚合后一个返回值:当key相同时,如何合并。
Collector toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction) {
return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}
// 实际上他们都是调用四个参数的重载方法,对传入的mergeFunction,也是使用java.util.Map中的merge方法来合并
Collector toMap(Function keyMapper,Function valueMapper,BinaryOperator mergeFunction,Supplier<M> mapSupplier) {
BiConsumer accumulator = (map, element) -> map.merge(keyMapper.apply(element), valueMapper.apply(element), mergeFunction);
return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}
- 其他stream流常用API
stream().distinct()
stream().count()
stream().sorted()
stream().findFirst()
stream().findAny()
stream().anyMatch()
stream().allMatch()
stream().noneMatch()
stream().max()
stream().min()
.stream().toArray(IntFunction<A[]> generator) // 返回指定类型的数组 A[] toArray(IntFunction<A[]> generator)
Optional中filter、map、ifPresent
- map
Optional.ofNullable(customer).map(Function mapper)
在Optional中,map也是要求传入Function,有参数,有返回值,map返回一个新类型的Optional,
- filter
Optional.ofNullable(customer).filter(Predicate p)
filter也是要求传入 Predicate,有参数,且返回布尔值,返回原类型的Optional,
- ifPresent
Optional.ofNullable(customer).ifPresent(Consumer action);
而ifPresent与forEach类似,要求传入Consumer,有参数,无返回值,且结束后不再返回Optional,结束这个Optional。
Runnable、Closeable 也是函数式接口
(无参数,无返回值)
- Runnable
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
- Closeable
public interface Closeable extends AutoCloseable {
public void close() throws IOException;
}
匿名内部类
在不熟悉Runnable、Function、Consumer、BiFunction、BiConsumer区别时,可以new Runnable()并按提示生成匿名内部类
例如:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello word!");
}
});
再按提示转成lambda,但明确这几项函数式接口的参数和返回值后,可以直接写lambda
直接写lambda表达式
- Runnable: 无参数,无返回值。直接写出lambda:
()->{System.out.println("hello word!");}
方法体只有一行省略掉大括号:()->System.out.println(“hello word!”)
- Predicate:有参数,需要返回值(布尔)。直接写出lambda:
(e)->{return e.getId() > 0;}
参数只有一个可以省略括号,方法体加返回只有一行又可以省略大括号和return关键字:e-> e.getId() > 0
- Function:有参数,有返回值。直接写出lambda:
(e)->{return e.getId();}
参数只有一个可以省略括号,方法体加返回只有一行又可以省略大括号和return关键字:e->e.getId()
e是上一步函数的返回值作为当前函数参数,又可省略到参数声明,方法引用:Customer::getId
- Consumer:有参数,无返回值。直接写出lambda:
(e)->{system.out.println(e);}
参数只有一个可以省略括号,但方法体只有一行又可以省略大括号:e->System.out.println(e)
e是上一步函数的返回值作为当前函数参数并又作为参数传入sout,又可省略到参数声明,方法引用:System.out::println
- BiConsumer:有两个参数,无返回值。直接写出lambda:
(k1, k2)->{System.out.println(k1 + k2);}
参数大于1不能省略小括号,但方法体只有一行又可以省略大括号:(k1, k2)->System.out.println(k1 + k2)
- BiFunction:有两个参数,有返回值。直接写出lambda:
(k1, k2)->{return k1 + k2;}
参数大于1不能省略小括号,但方法体加返回只有一行又可以省略大括号和return关键字:(k1, k2)->k1 + k2