
Lambda: 本质是函数式接口的实例(区别:在Python中lambda本质是函数)
函数式接口: 只有一个抽象方法的接口。 可用@functionalInterface来注解。
代码-内置函数接口Predicate(lambda来作为函数接口的实例)
Predicate<String> pre = x -> x.contains("京")
package com.xj.java;import org.junit.Test;import java.util.LinkedList;import java.util.List;import java.util.function.Predicate;/*** @author jia* @create 2021-12-22 5:31 下午*/public class LambdaTest {@Testpublic void Test(){String[] src = {"北京","成都","天津","南京"};List<String> res = filter(src,x -> x.contains("京"));System.out.println(res); // [北京, 南京]}public static List<String> filter(String[] src, Predicate<String> pre){// 内置函数接口-PredicateLinkedList<String> stringFilter = new LinkedList<>();for (String s : src){if (pre.test(s))stringFilter.add(s);}return stringFilter;}}
方法引用(MethodRef)

是特殊的lambda表达式。引用已有的实现来替代“函数式接口的实现”,而不用重复实现。 比如下方,Array.sort()中需要传入Comparable接口的实现对象,除了可以传入匿名实现类、和lambda表达式,还可以直接传入已有的接口实现的引用。
String[] stringsArray = {"Hello","World"};//使用lambda表达式和类型对象的实例方法Arrays.sort(stringsArray,(s1,s2)->s1.compareToIgnoreCase(s2));//使用方法引用//引用的是类型对象的实例方法Arrays.sort(stringsArray, String::compareToIgnoreCase);
引用自定义的接口实现。
class ComparisonProvider{public int compareByName(Person a,Person b){return a.getName().compareTo(b.getName());}public int compareByAge(Person a,Person b){return a.getBirthday().compareTo(b.getBirthday());}}ComparisonProvider provider = new ComparisonProvider();//使用lambda表达式//对象的实例方法Arrays.sort(persons,(a,b)->provider.compareByAge(a,b));//使用方法引用//引用的是对象的实例方法Arrays.sort(persons, provider::compareByAge);
甚至可以引用构造方法
public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>>DEST transferElements(SOURCE sourceColletions, Supplier<DEST> colltionFactory) {DEST result = colltionFactory.get();for (T t : sourceColletions) {result.add(t);}return result;}...final List<Person> personList = Arrays.asList(persons);//使用lambda表达式Set<Person> personSet = transferElements(personList,()-> new HashSet<>());//使用方法引用//引用的是构造方法Set<Person> personSet2 = transferElements(personList, HashSet::new);
Stream API: 函数式编程风格、用于操作容器、




Stream代码: 分为3部分介绍,对应了Stream的3个过程,Stream实例化,Stream中间操作,Stream终止操作
package com.xj.java;import org.junit.Test;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.Set;import java.util.stream.Collectors;import java.util.stream.Stream;/*** @author jia* @create 2021-12-23 3:55 下午*/public class StreamTest {/*** Stream分为如下3步。* */public static Stream<Integer> step1(){/*** 0. Stream分为串行流和并行流。* */Stream<Integer> stream = Arrays.asList(1, 2, 3).stream(); // 串行流Stream<Integer> integerStream = Arrays.asList(1, 2, 3).parallelStream(); // 并行流/*** 1. Stream实例化 - 4种方式* */// 方式1-集合Stream<Integer> stream1 = Arrays.asList(1, 2, 3,4,5,6,6,6,6).stream();// 方式2-数组Stream<Integer> stream2 = Arrays.stream(new Integer[]{1, 2, 3,4,5,6,6,6,6});// 方式3-Stream.of静态方法Stream<Integer> Stream3 = Stream.of(1, 2, 3,4,5,6,6,6,6);// 方式4-迭代器、生成器Stream<Integer> stream4 = Stream.iterate(0, t -> t + 1).limit(9);return stream1;}public static Stream<Integer> step2(){/*** 2. Stream中间操作* */// 1. filter(predict函数式接口实例)Stream<Integer> filter = step1().filter(x -> x.compareTo(2) > 0);// 2. limit(int)Stream<Integer> limit = step1().limit(8);// 3. skip(int)Stream<Integer> skip = step1().skip(1);// 4. distinct() 通过hashCode()和equals()来去重。Stream<Integer> distinct = step1().distinct();// 5. map(函数式接口实例) 将流中元素照指定函数映射。Stream<Integer> map = step1().map(x -> x * 10);// 6. flatMap(函数式接口实例) 将流中元素照指定函数映射。map和flatmap区别见test_map_flatmap测试。// 7. 排序Stream<Integer> sorted = step1().sorted((x, y) -> -1 * Integer.compare(x, y));// 无参数则自然排序return filter;}@Testpublic void step3(){/*** 3.1 Stream终止操作 -- 查找、遍历* */boolean bool;// 1.allMatch --是否全部匹配条件bool = step2().allMatch(e -> e > 4);System.out.println(bool);// 2. noneMatch-- 是否没有匹配的元素bool = step2().noneMatch(e -> e == 2);System.out.println(bool);// 3.findFirst -- 返回首个元素System.out.println(step2().findFirst());// 4. findAny -- 返回任意元素System.out.println(step2().findAny());// 5. count -- 总数。类型为longSystem.out.println(step2().count());// 6. 比较System.out.println(step2().max(Integer::compare)); // 或者(x,y) -> Integer.compare(x,y)和(x,y) -> x-y)等System.out.println(step2().min(Integer::compare));// 7.foreach 内部迭代step2().forEach(e -> System.out.print(e + " "));System.out.println();// 8. 对比7 外部迭代-使用集合的迭代Arrays.asList(1,2,3).forEach(e -> System.out.print(e + " "));System.out.println();/*** 3.2 Stream终止操作 -- 归约 reduce 将流中元素反复以xx方式结合起来,得到一个值。* */// 3.2.1 计算数字之和Integer reduce = Arrays.asList(1,2,3).stream().reduce(0, (a,b) -> a + b);// 或者 Integer::sumSystem.out.println(reduce);// 3.2.2 计算数字之积Integer reduce1 = Arrays.asList(1, 2, 3).stream().reduce(1, (a, b) -> a * b);System.out.println(reduce);/*** 3.3 Stream终止操作 -- 收集 collect 将流中元素以xx方式收集,比如收集到List,Set,Map。* */// 3.3.1 - 转为ListList<Integer> collect = Arrays.asList(1, 2, 3).stream().collect(Collectors.toList());collect.forEach(e -> System.out.print(e + " "));System.out.println();// 3.3.2 - 转为SetSet<Integer> collect1 = Arrays.asList(1, 2, 3).stream().collect(Collectors.toSet());collect1.forEach(e -> System.out.print(e + " "));System.out.println();}@Testpublic void test_map_flatmap(){/*比较map和flatmap的区别。采用同一个映射方法,将容器中的字符串拆分为字符。flatmap: 流{"good","man"} -> 流{'g','o','o','d','m','a','n'}map: 流{"good","man"} -> 流{流{'g','o','o','d'},流{'m','a','n'}}*/Stream<String> stream = null;// flatmapstream = Arrays.asList("good", "man").stream();Stream<Character> flatmap_characterStream = stream.flatMap(StreamTest::fromString2Stream);flatmap_characterStream.forEach(x -> System.out.print(x + " "));System.out.println();// mapstream = Arrays.asList("good", "man").stream();Stream<Stream<Character>> map_streamStream = stream.map(StreamTest::fromString2Stream);map_streamStream.forEach(x -> x.forEach(s -> System.out.print(s + " "))); // 注意区别}public static Stream<Character> fromString2Stream(String str){ArrayList<Character> characters = new ArrayList<>();for (char c : str.toCharArray()){characters.add(c);}return characters.stream();}}
测试step3()
false true Optional[3] Optional[3] 7 Optional[6] Optional[3] 3 4 5 6 6 6 6 1 2 3 6 6 1 2 3 1 2 3
Optional: 避免空指针问题
使用指南
Optional可以避免显式的空值检查,一般使用方式为
T obj = Optional.ofNullable(T t).orElse(T other)或T obj = Optional.of(T t).get()。第一种传入参数t允许为空,以备选对象的方式避免空指针的问题,第二种传入参数t不可为空,以抛异常的方式来避免空指针。 第一种方式类似于python的语法:obj = t or other

代码-有无Optional的情况下避免空指针的做法
下面是核心代码
package com.xj.java;import org.junit.Test;import java.util.Optional;/*** @author jia* @create 2021-12-23 10:44 下午*/public class OptionalTest {@Testpublic void PersonTest(){// 一个人只有左手。没有Optional时,通过提前判断来避免空指针Person person = new Person();person.setLeftHand(new Hand("左"));if (person.getLeftHand() != null){person.getLeftHand().holdOut();person.getLeftHand().drawBack();} elseSystem.out.println("没有左手");if (person.getRightHand() != null){person.getRightHand().holdOut();person.getRightHand().drawBack();}elseSystem.out.println(" !! 没有右手");}@Testpublic void OptionalPersonTest(){// 一个人只有左手。有Optional时,无需使用判断就能避免空指针OptionalPerson person = new OptionalPerson();person.setLeftHand(new Hand("左"));person.getLeftHand().holdOut();person.getLeftHand().drawBack();person.getRightHand().holdOut();person.getRightHand().drawBack();}}class OptionalPerson{// 一般人有两个手,但也有人没有手。private Hand leftHand = null;private Hand rightHand = null;public OptionalPerson() {}public Hand getLeftHand() {Optional<Hand> handOptional = Optional.ofNullable(this.rightHand);Hand hand = handOptional.orElse(new Hand("!!Optional-(没有右手)"));return hand;}public void setLeftHand(Hand leftHand) {this.leftHand = leftHand;}public Hand getRightHand() {Optional<Hand> handOptional = Optional.ofNullable(this.rightHand);Hand hand = handOptional.orElse(new Hand("!!Optional-(没有左手)"));return hand;}public void setRightHand(Hand rightHand) {this.rightHand = rightHand;}}class Person{// 一般人有两个手,但也有人没有手。private Hand leftHand = null;private Hand rightHand = null;public Hand getLeftHand() {return leftHand;}public void setLeftHand(Hand leftHand) {this.leftHand = leftHand;}public Hand getRightHand() {return rightHand;}public void setRightHand(Hand rightHand) {this.rightHand = rightHand;}}class Hand{// 这是一个手的3个动作。public String hand = null;public Hand(String hand) {this.hand = hand; // 左或右}public void drawBack(){System.out.println(this.hand + "手收回");}public void holdOut() {System.out.println(this.hand + "手伸出");}}


