Java8中四种基础函数式接口
目录
Java8中四种基础函数式接口
函数式接口 |
参数类型 |
返回类型 |
用途 |
举例 |
Function<T, R>{R apply(T t);} |
T,R |
R |
给定指定类型T的参数,返回R类型的结果,将函数限定。 |
对内容进行处理。比如给一张白纸,返回一张好看的画 |
Predicate{boolean test(T t);} |
T |
boolean |
给定指定类型T的参数,计算出断言式的boolean型结果 |
对内容进行过滤。比如公司招人,选适合的人 |
Consumer{void accept(T t);} |
T |
void |
给定类型为T的参数,执行操作 |
对内容进行输出。比如在超市买东西,打印的小票,这样就可以看到明细了 |
Supplier{T get();} |
void |
T |
获得给定类型T的结果,不传参数 |
提供相似的内容。比如:用的铅笔没了,提供其他铅笔用 |
Lambda表达式是函数式接口的基础,可以将 lambda 表达式视为一个对象,将其作为参数传递
1,函数式接口 Function:apply
接口: Function<T, R>
public interface Function<T, R> {
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));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
apply: 应用,这个方法是最常见的
compose: 构成之前,在apply之前,先进行XX操作
andThen:构成之后,在apply之后,进行YY操作
identity: 唯一,在Collectors.toMap中使用,保证key对应的值的唯一性;
基础:
/**
* Function是一个函数式接口,其中有四个方法 apply, compose, andThen, testIndetify()
* // 先执行输入的Function,其结果作为参数再作为调用者的Function的参数
* default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
* Objects.requireNonNull(before);
* return (V v) -> apply(before.apply(v));
* }
*
* // 先执行调用者的Function,其结果作为参数再作为输入的Function的参数
* default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
* Objects.requireNonNull(after);
* return (T t) -> after.apply(apply(t));
* }
*
*/
public static void main(String[] args) {
Function<String, String> applyFunc = s -> s.concat(" function ");
Function<String, String> composeFunc = s -> s.concat(" compose ");
Function<String, String> andThenFunc = s -> s.concat(" andThen ");
System.out.println(applyFunc.apply("yan"));
System.out.println(applyFunc.compose(composeFunc).apply(" yan "));
System.out.println(applyFunc.andThen(andThenFunc).apply(" yan "));
testComposeAndThen();
}
public static void testComposeAndThen(){
int res1 = compute1(1, e -> e + 1); // 结果:2
int res2 = compute2(2, e -> e + 3, e -> e * 3); // 结果:9
int res21 = compute21(2, e -> e + 3, e -> e * 3); // 结果:15
int res3 = compute3(3, e -> e + 4, e -> e * 3); // 结果:13
int res31 = compute4(3, e -> e + 4, e -> e * 3); // 结果:14
System.out.println(res1 + ", " + res2 + ", " + res21 + ", " + res3 + ", " + res31);
}
public static int compute1(int x, Function<Integer, Integer> function) {
return function.apply(x);
}
public static int compute2(int x, Function<Integer, Integer> after, Function<Integer, Integer> before) {
// x作为before的参数,其结果再作为after的参数
return after.compose(before).apply(x);
}
public static int compute21(int x, Function<Integer, Integer> after, Function<Integer, Integer> before) {
// x作为before的参数,其结果再作为after的参数
return before.compose(after).apply(x);
}
public static int compute3(int x, Function<Integer, Integer> after, Function<Integer, Integer> before) {
// x作为after的参数先执行after的计算,其结果再作为before的参数
return before.andThen(after).apply(x);
}
public static int compute4(int x, Function<Integer, Integer> after, Function<Integer, Integer> before) {
// x作为after的参数先执行after的计算,其结果再作为before的参数
return after.andThen(before).apply(x);
}
public static void testIndetify(){
List<Map<String, Object>> neIdList = new ArrayList<>();
Map<String, Object> paas = new HashMap<>(8);
paas.put("FILE_FIELD", "times");
paas.put("AGG_TYPE", "sum");
neIdList.add(paas);
Map<String, Object> paas2 = new HashMap<>(8);
paas2.put("FILE_FIELD", "times");
paas2.put("AGG_TYPE", "sum2");
neIdList.add(paas2);
Map<String, Map<String, Object>> identifyMap =
ListUtils.emptyIfNull(neIdList).stream()
.collect(Collectors.toMap(e -> MapUtils.getString(e, "FILE_FIELD"), Function.identity(), (x, y) -> x));
System.out.println(identifyMap.toString());
}
apply的使用
public static void main(String[] args) {
List<String> strList = Arrays.asList("orderType", "virtualOrderId", "cityCode");
List<Integer> strSizeList = map(strList, String::length);
strSizeList.forEach(System.out::println);
List<Integer> numAddList = map(strSizeList, (Integer s) -> s + 100);
numAddList.forEach(System.out::println);
List<String> concatOne = map(strList, (String s) -> s.concat(" one"));
concatOne.forEach(System.out::println);
}
public static <T, R> List<R> map(List<T> list, Function<T, R> func) {
return ListUtils.emptyIfNull(list).stream().map(func).collect(Collectors.toList());
}
2,断言式接口 Predicate:test
Predicate:断言,使基于,我倾向于后者的理解,基于什么去判断
基础:
// Stream<T> filter(Predicate<? super T> predicate);
public static <T> List<T> filter(List<T> list, Predicate<T> p) {
List<T> results = new ArrayList<>();
for (T s : list) {
if (p.test(s)) { // 判断是否符合条件
results.add(s);
}
}
return results;
}
public static void main(String[] args) {
testEmpty();
testFilterSize();
testFilterValue();
}
public static void testEmpty() {
Predicate<String> nonEmptyStrPre = (String s) -> !s.isEmpty();
List<String> aa = Arrays.asList("Hello", "", "Predict", "123", "ok");
List<String> nonEmpty = filter(aa, nonEmptyStrPre);
nonEmpty.forEach(System.out::println);
List<String> nonEmpty2 = filter(aa, s -> s.length() > 2);
nonEmpty2.forEach(System.out::println);
}
public static void testFilterSize() {
List<String> list = Arrays.asList("Hello", "Java8", "Lambda", "www", "ok");
ListUtils.emptyIfNull(list).stream().filter(s -> s.length() > 3).collect(Collectors.toList());
List<String> strList = filter(list, (s) -> s.length() > 3);
strList.forEach(System.out::println);
}
public static void testFilterValue() {
List<Integer> list = Arrays.asList(88, 44, 99, 980, 121212);
List<Integer> strList = filter(list, (s) -> s > 300);
strList.forEach(System.out::println);
}
使用
// 在接口:Collection<E>
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
3,消费式接口 Consumer:accept
Consumer 消费:主要是输出内容
public static void main(String[] args) {
forEach(Arrays.asList(1, 2, 3, 4, 5), (Integer i) -> System.out.println(i));
forEach(Arrays.asList("yan", "I", "wonder"), (String i) -> System.out.println(i));
}
public static <T> void forEach(List<T> list, Consumer<T> c) {
for (T s : list) {
c.accept(s);
}
}
// 在接口:Iterable<T> 中
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
4,供给式接口 Supplier: get
Supplier 提供同类型的数据内容,可以是单个或是多个,
public static void main(String[] args) {
Random random = new Random();
List<Integer> list = supplierSum(10, () -> random.nextInt(10));
list.forEach(System.out::println);
}
public static List<Integer> supplierSum(int total, Supplier<Integer> sup) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < total; i++) {
list.add(sup.get());
}
return list;
}
总结
四个基础函数式编程接口中,Function 和 Predicate 会用得比较多,在steam中的 方法map (<R> Stream<R> map(Function<? super T, ? extends R> mapper); ) 和 filter方法 (Stream<T> filter(Predicate<? super T> predicate)),用到的频率就很高。
在函数编程的理解中,主要是理解基础lambda可以作为一个参数进行传递。
本文地址:https://blog.csdn.net/qq_35461948/article/details/110234767
上一篇: Java学习笔记-CSV文件的读写操作
下一篇: 如何在java中精确到指定位数