Lambda

Wed, Sep 1, 2021 4-minute read

Lambda quick note

1. 无参,无返回值

Runnable r1 = () -> {System.out.println(“Hell0 Lambda!");};

2. 需要一个参数,但是没有返回值

Consumer con = (String str) -> {System.out.println(str);};

3. 数据类型可以省略,因为可由编译器推断得出,称为“类型推断”

Consumer con = (str) -> {System.out.println(str);};

4. Lambda 若只需要一个参数时,参数的小括号可以省略

Consumer con = str -> {System.out.println(str);};

5. Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值

Comparator com = (x, y) -> { System.out.println(str); return Integer.compare(x, y); };

6. 当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略

Comparator com = (x, y) -> Integer.compare(x, y); };


方法引用

对象::实例方法名

类::静态方法名

类::实例方法名

Consumer con = (x) -> System.out.println(x);

Consumer con = System.out::println;

Comparator com = (x, y) -> Integer.compare(x, y);

System.out.println(com.compare(12, 3));

Comparator com = Integer::compare;

System.out.println(com.compare(12, 3));

BiPredicate<String, String> bp = (x, y) -> x.equals(y);

BiPredicate<String, String> bp = String::equals; boolean flag = bp.test(“hello”, “hi”);

Function<Double, Long> func1 = d -> Math.round(d); func1.apply(12.3);

Function<Double, Long> func1 =Math::round; func1.apply(12.3);


构造器引用格式

类名::new

Supplier sup1 = () -> new Employee(); System.out.println(sup1.get());

Supplier sup1 = Employee:: new; System.out.println(sup1.get());


数组引用格式

数组类型[]::new

Function<Integer, Integer[]> func1 = (n) -> new Integer[n];

Function<Integer, Integer[]> func1 = Integer[]:: new


Function<Integer, String[]> func1 = length -> new String[length]; String[] arr1 = func1.apply(5); System.out.println(Arrays.toString(arr1));

Function<Integer, String[]> func1 = String[]:: new; String[] arr1 = func1.apply(10); System.out.println(Arrays.toString(arr1));


Stream API

创建 Stream 方式一:通过集合

Stream stream() : 返回一个顺序流

List employees = EmployeeData.getEmployees();

Stream stream = employees.stream();

Stream parallelStream() : 返回一个并行流

Stream stream = employees.parallelStream();

创建 Stream 方式二:通过数组

Arrays.stream() 的静态方法 可以获取数组流

int[] arr = new int[] {1, 2, 3, 4, 5};

IntStream stream = Arrays.stream(arr);

Employee e1 = new Employee(1001, “Tom”); Employee e2 = new Employee(1002, “Tom2”); Employee[] arr1 = new Employee[]{e1, e2}; Stream stream = Arrays.stream(arr1);

创建 Stream 方式三:通过 Stream 的 of()

Stream.of(1, 2, 3, 4, 5) 静态方法 通过显示值创建一个流。它可以接收任意数量的参数

Stream stream = Stream.of(1, 2, 3, 4, 5);

创建 Stream 方式四:创建无限流

可以使用静态方法 Stream.iterate() 和 Stream.generate(), 创建无限流。

Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);

Stream.generate(Math::random).limit(10).forEach(System.out::println);


Stream 的中间操作:筛选

List<Employee> list = new ArrayList<>();

list.add(new Employee(1001, "aa", 11, 10001));

Stream<Employee> stream = list.stream();

stream.filter(e -> e.getSalary() > 8000).forEach(System.out::println);

stream.limit(3).forEach(System.out::println); // 错误

list.stream().limit(3).forEach(System.out::println); //重新生成

list.stream().skip(3).forEach(System.out::println); //重新生成

list.stream().distinct().forEach(System.out::println); //筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素


Stream 的中间操作

映 射 map

接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。

List<String> list = Arrays.asList("aa","bb","cc","dd");

list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
获取员工姓名大于 3 的员工的姓名
List<Employee> e1 = EmployeeData.getEmployees();

String<String> namesStream = e1.stream().map(Employee::getName());

namesStream.filter(name -> name.length() > 3).forEach(System.out::println);


将字符串中多个字符构成的集合转换为对应的 Stream 的实例 flatmap
List<String> list = Arrays.asList("aa","bb","cc","dd");

String<Stream<Characte>> streamStream = list.stream().map(StreamAPITest1::fromStringToStream);

streamStream.forEach(s -> {
  s.forEach(System.out::println);
});
  
// a a b b c c 
public static Stream<Character> fromStringToStream(String str) {


ArrayList<Character> list = new ArrayList<>();

for (Character c : str.toCharArray()) {
  list.add(c);
}

return list.stream();
}

flatmap

List<String> list = Arrays.asList("aa","bb","cc","dd");

Stream<Characte> characterStream = list.stream().flatmap(StreamAPITest1::fromStringToStream);

characterStream.forEach(System.out::println);


// a a b b c c 
public static Stream<Character> fromStringToStream(String str) {


ArrayList<Character> list = new ArrayList<>();

for (Character c : str.toCharArray()) {
  list.add(c);
}

return list.stream();
}
自然排序 sort
List<Integer> list = Arrays.asList(12, 43, 65, 23, 89, 0, -98, 7);

list.stream().sorted().forEach(System.out::println);

定制排序 sorted(Comparator com)
List<Employee> e1 = EmployeeData.getEmployees();

e1.stream().sorted((e1, e2) -> {
  return Integer.compare(e1.getAge(), e2.getAge());
}).forEach(System.out::println);

List<Employee> e1 = EmployeeData.getEmployees();

e1.stream().sorted((e1, e2) ->  Integer.compare(e1.getAge(), e2.getAge()) )
  .forEach(System.out::println);

List<Employee> e1 = EmployeeData.getEmployees();

e1.stream().sorted((e1, e2) -> {

int ageValue = Integer.compare(e1.getAge(), e2.getAge());
if (ageValue != 0) {
  return ageValue;
} else {
  return Double.Compare(e1.getSalary(), e2.getSalary());
}
  
})..forEach(System.out::println);

终止操作

allMatch

List<Employee> e1 = EmployeeData.getEmployees();

boolean b = e1.stream().allMatch(e -> e.getAge() > 18);

System.out.println(b);

anyMatch 是否存在员工工资大于 8000

List<Employee> e1 = EmployeeData.getEmployees();

boolean b = e1.stream().anyMatch(e -> e.getSalary() >  8000);

System.out.println(b);

findFirst 第一个元素/任意/个数

List<Employee> e1 = EmployeeData.getEmployees();

long count = employees.stream().filter(e -> e.gertSalary() > 5000).count();

max(Comparator c)返回流中最大值/min

返回最高的工资

List<Employee> e1 = EmployeeData.getEmployees();

long count = employees.stream().filter(e -> e.gertSalary() > 5000).count();

String<Double> stream1 = employees.stream().map(e -> e.getSalary());
Optional<Double> max = steam1.max(Double::compare);

返回最低的工资的员工

List<Employee> e1 = EmployeeData.getEmployees();

Optional<Employee> min = employees.stream().min((e1, e2) -> Double.compare(e1.gertSalary(), e2.gertSalary());

归约 1-10 的自然数的和:可以将流中元素反复结合起来,得到一个值返回 T

List<Integer> list = Array.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Integer sum = lists.stream().reduce(0, Integer::sum); // 55

Integer sum = lists.stream().reduce(10, Integer::sum); // 65

计算公司所有员工工资的总和

List<Employee> e1 = EmployeeData.getEmployees();

Optional<Double> sum = employees.stream().map(Employee::getSalary).reduce(Double::sum); 


Collect(Collector c)

将流转换为其他形式。接收一个 Collector 接口的实现,用于给 Stream 中元素做汇总的方法

返回工资大于 6000 的员工,返回一个 list 或 set

List<Employee> e1 = EmployeeData.getEmployees();

List<Employee> collect = employees.stream().filter(e -> e.gertSalary() > 6000).collect(Collectors.toList()); 

Set<Employee> set = employees.stream().filter(e -> e.gertSalary() > 6000).collect(Collectors.toSet()); 

collect.forEach(System.out::println);


Optional

创建 Optional 类对象的方法

Optional.of(T t) : 创建一个 Optional 实例,t 必须非空

Optional.empty() : 创建一个空的 Optional 实例

Optional.ofNullable(T t):t 可以为 null

判断 Optional 容器中是否包含对象

boolean isPresent() : 判断是否包含对象

void ifPresent(Consumer<? super T> consumer) :如果有值,就执行 Consumer 接口的实现代码,并且该值会作为参数传给它

获取 Optional 容器的对象

T get(): 如果调用对象包含值,返回该值,否则抛异常

T orElse(T other) :如果有值则将其返回,否则返回指定的 other 对象

T orElseGet(Supplier<? extends T> other) :如果有值则将其返回,否则返回由 Supplier 接口实现提供的对象

T orElseThrow(Supplier<? extends X> exceptionSupplier) :如果有值则将其返回,否则抛出由 Supplier 接口实现提供的异常

public String getGirlName(Boy boy) {
  if (boy != null) {
    Girl girl = boy.getGirl();
    if (girl != null) {
      return girl.getName();
    }
  }
  return null;
}

Optional 类

public String getGirlName(Boy boy) {
  Optional<Boy> boyOptional = Optional.ofNullable(boy);
  // boy1一定非空
  Boy boy1 = boyOptional.orElse(new Boy(new Girl("aa")));

  Girl girl = boy1.getGirl();

  Optional<Girl> girlOptional = Optional.ofNullable(girl);
  // girl一定非空
  Girl girl = girlOptional.orElse(new Girl("BB"));
}