java8的 lambda表达式到stream API总结备忘

文章目录

  • 1. Lambda 表达式
    • 为什么使用 Lambda 表达式
    • 从匿名类到 Lambda 的转换
    • Lambda 表达式语法
      • 语法格式一:无参,无返回值,Lambda 体只需一条语句
      • 语法格式二:Lambda 需要一个参数
      • 语法格式三:Lambda 只需要一个参数时,参数的小括号可以省略
      • 语法格式四:Lambda 需要两个参数,并且有返回值
      • 语法格式五:当 Lambda 体只有一条语句时,return 与大括号可以省略
      • 语法格式六:多条语句
  • 2. 函数式接口
    • 什么是函数式接口
    • 自定义函数式接口
    • 常用的函数式接口
      • 1. 消费式Consumer<T>
      • 2. 功能式Function<T, R>
      • 3.预测Predicate<T>
      • 4.供给/提供Supplier<T>
  • 3. 方法引用与构造器引用
    • 方法引用
    • 构造器引用
    • 数组引用
  • 4. Stream API
    • 什么是 Stream
    • Stream 的操作三个步骤
      • - 创建 Stream
      • - 中间操作
      • - 终止操作(终端操作)
    • 创建 Stream
      • 由数组创建流
      • 由值创建流
      • 由函数创建流:创建无限流
    • Stream 的中间操作
      • 筛选与切片
        • filter(Predicate p)
        • distinct()
        • limit(long maxSize)
        • skip(long n)
      • 映射
        • map(Function f)
        • mapToDouble(ToDoubleFunction f)
        • mapToInt(ToIntFunction f)
        • mapToLong(ToLongFunction f)
        • flatMap(Function f)
      • 排序
    • Stream 的终止操作
      • 查找与匹配
        • allMatch(Predicate p) 检查是否匹配所有元素
        • anyMatch(Predicate p) 检查是否至少匹配一个元素
        • noneMatch(Predicate p) 检查是否没有匹配所有元素
        • findFirst() 返回第一个元素终端操作会从流的流水线生成结果。
        • findAny() 返回当前流中的任意元素
      • 归约
        • count() |返回流中元素总数
        • max(Comparator c) 返回流中最大值
        • min(Comparator c)返回流中最小值
        • forEach(Consumer c) 内部迭代
        • reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 T
      • 收集
        • 1、toList
        • 2、toMap
        • 3、toSet
        • 4、counting
        • 5、summingInt
        • 6、minBy
        • 7、joining
        • 8、groupingBy
        • 1.orElse(null)
        • 2.orElseGet(null)
        • orElse(null)和orElseGet(null)区别:
    • 并行流和串行流
  • 5. 新时间日期 API
    • 使用 LocalDate、LocalTime、LocalDateTime

1. Lambda 表达式

为什么使用 Lambda 表达式

Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更 灵活的代码。作为一种更紧凑的代码风格,使 Java的语言表达能力得到了提升。

从匿名类到 Lambda 的转换

	//原来的匿名内部类@Testpublic void test1(){Comparator<String> com = new Comparator<String>(){@Overridepublic int compare(String o1, String o2) {return Integer.compare(o1.length(), o2.length());}};TreeSet<String> ts = new TreeSet<>(com);TreeSet<String> ts2 = new TreeSet<>(new Comparator<String>(){@Overridepublic int compare(String o1, String o2) {return Integer.compare(o1.length(), o2.length());}});}//现在的 Lambda 表达式@Testpublic void test2(){Comparator<String> com = (x, y) -> Integer.compare(x.length(), y.length());TreeSet<String> ts = new TreeSet<>(com);}List<Employee> emps = Arrays.asList(new Employee(101, "张三", 18, 9999.99),new Employee(102, "李四", 59, 6666.66),new Employee(103, "王五", 28, 3333.33),new Employee(104, "赵六", 8, 7777.77),new Employee(105, "田七", 38, 5555.55));

Lambda 表达式语法

Lambda 表达式在Java 语言中引入了一个新的语法元
素和操作符。这个操作符为 “->” , 该操作符被称
为 Lambda 操作符或剪头操作符。它将 Lambda 分为
两个部分:
左侧:指定了 Lambda 表达式需要的所有参数
右侧:指定了 Lambda 体,即 Lambda 表达式要执行
的功能。

语法格式一:无参,无返回值,Lambda 体只需一条语句

 // 语法格式一:无参数,无返回值@Testpublic void test1(){int num = 0; Runnable r = new Runnable() {@Overridepublic void run() {System.out.println("Hello World!" + num);}};r.run();System.out.println("-------------------------------");Runnable r1 = () -> System.out.println("Hello Lambda!");r1.run();}

语法格式二:Lambda 需要一个参数

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

语法格式三:Lambda 只需要一个参数时,参数的小括号可以省略

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

语法格式四:Lambda 需要两个参数,并且有返回值

Comparator<Integer> com = (x, y) -> {System.out.println("函数式接口");return Integer.compare(x, y);
}

语法格式五:当 Lambda 体只有一条语句时,return 与大括号可以省略

Consumer<String> con = (x,y) -> x + y;

语法格式六:多条语句

Comparator<Integer> com = (x, y) -> {System.out.println("函数式接口");return Integer.compare(x, y);
}

2. 函数式接口

什么是函数式接口

  • 只包含一个抽象方法的接口,称为函数式接口。
  • 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda
    表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方
    法上进行声明)。
  • 我们可以在任意函数式接口上使用 @FunctionalInterface 注解,
    这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包
    含一条声明,说明这个接口是一个函数式接口。

自定义函数式接口

@FunctionalInterface
public interface MyNumberf{public double getValue();
}
//函数式接口中使用泛型:
public interface MyFunc<T>{public T getValue(T t);
}@FunctionalInterface
public interface MyFunction {int apply(int x, int y);
}MyFunction add = (x, y) -> x + y;
int result = add.apply(5, 3);
System.out.println(result); // 输出8MyFunction multiply = (x, y) -> x * y;
result = multiply.apply(5, 3);
System.out.println(result); // 输出15

常用的函数式接口

1. 消费式Consumer

  • 源码解析
@FunctionalInterface
public interface Consumer<T> {/*** Performs this operation on the given argument.*/void accept(T t);/*** andThen()方法用于将两个Consumer对象串联起来,实现多个操作的* 连续执行。该方法的语法格式为consumer1.andThen(consumer2),* 其中consumer1和consumer2分别为两个Consumer对象。* */default Consumer<T> andThen(Consumer<? super T> after) {Objects.requireNonNull(after);return (T t) -> { accept(t); after.accept(t); };}
}
  • 使用实例
Consumer<String> consumer1 = s -> System.out.println("consumer1: " + s);
Consumer<String> consumer2 = s -> System.out.println("consumer2: " + s);
Consumer<String> consumer3 = consumer1.andThen(consumer2);consumer3.accept("hello world");

输出:

consumer1: hello world
consumer2: hello world

2. 功能式Function<T, R>

  • 源码解析
@FunctionalInterface
public interface Function<T, R> {/*** Applies this function to the given argument.*/R apply(T t);/*** compose()方法用于将两个Function对象串联起来,实现多个操作* 的连续执行,并返回一个新的Function对象。该方法的语法格式为* function1.compose(function2),其中function1和function2分别* 为两个Function对象。*/default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {Objects.requireNonNull(before);return (V v) -> apply(before.apply(v));}/*** andThen()方法与compose()方法类似,但它先执行当前Function对象* 的操作,再执行参数Function对象的操作,并返回一个新的* Function对象。该方法的语法格式为function1.andThen(function2)* ,其中function1和function2分别为两个Function对象。*/default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {Objects.requireNonNull(after);return (T t) -> after.apply(apply(t));}/*** identity()方法是一个静态方法,返回一个恒等函数,即输入参数和* 输出结果都相同的函数。该方法的语法格式为Function.identity()*/static <T> Function<T, T> identity() {return t -> t;}
}
  • 使用实例
Function<Integer, Integer> function1 = x -> x + 1;
Function<Integer, Integer> function2 = x -> x * 2;
Function<Integer, Integer> function3 = function1.compose(function2);int result3 = function3.apply(5);
System.out.println(result3); // 输出11Function<Integer, Integer> function4 = function1.andThen(function2);int result4 = function4.apply(5);
System.out.println(result4); // 输出12Function<String, String> function = Function.identity();
String str = function.apply("hello");
System.out.println(str); // 输出hello

输出:

11
12
hello

3.预测Predicate

  • 源码解析
@FunctionalInterface
public interface Predicate<T> {/*** Evaluates this predicate on the given argument.*/boolean test(T t);/*** and()方法用于将两个Predicate对象组合起来,并返回一个新的Predicate对象,* 实现多个条件的同时满足。该方法的语法格式为predicate1.and(predicate2),* 其中predicate1和predicate2分别为两个Predicate对象。*/default Predicate<T> and(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) && other.test(t);}/*** negate()方法用于对Predicate对象进行取反操作,并返回一个新的Predicate对象。* 该方法的语法格式为predicate.negate(),其中predicate为原始的Predicate对象*/default Predicate<T> negate() {return (t) -> !test(t);}/*** or()方法与and()方法类似,但它实现多个条件的任意一个满足即可。该方法的语法格式为predicate1.or(predicate2),* 其中predicate1和predicate2分别为两个Predicate对象。*/default Predicate<T> or(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) || other.test(t);}/*** */static <T> Predicate<T> isEqual(Object targetRef) {return (null == targetRef)? Objects::isNull: object -> targetRef.equals(object);}
}
  • 使用实例
Predicate<String> predicate1 = s -> s.startsWith("hello");
Predicate<String> predicate2 = s -> s.endsWith("world");
Predicate<String> predicate3 = predicate1.and(predicate2);
boolean result3 = predicate3.test("hello world");
System.out.println(result3); // 输出true
Predicate<String> predicate4 = predicate1.or(predicate2);
boolean result4 = predicate4.test("hello world");
System.out.println(result4); // 输出false
Predicate<String> negatedPredicate = predicate1.negate();
boolean result = negatedPredicate.test("hello world");
System.out.println(result); // 输出false
Predicate<String> predicate = Predicate.isEqual("hello world");
boolean result1 = predicate.test("hello world");
boolean result2 = predicate.test("hello java");
System.out.println(result1); // 输出true
System.out.println(result2); // 输出false

4.供给/提供Supplier

  • 源码解析
@FunctionalInterface
public interface Supplier<T> {/*** Gets a result.* @return a result*/T get();
}
  • 使用实例
Supplier<Double> supplier = Math::random;
double value = supplier.get();

3. 方法引用与构造器引用

方法引用

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!(实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!)方法引用:使用操作符“::”
将方法名和对象或类的名字分隔开来。 如下三种主要使用情况:

  • 对象::实例方法
  • 类::静态方法
  • 类::实例方法
(x) -> System.out.println(x);
//等同于
System::println;

构造器引用

格式: ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。
可以把构造器引用赋值给定义的方法,与构造器参数
列表要与接口中抽象方法的参数列表一致!

Function<Integer,MyClass> func = (n) -> new MyClass(n);
//等同于
Function<Integer,MyClass> func1 = MyClass::new;

数组引用

格式: type[] :: new

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

4. Stream API

Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一
个则是 Stream API(java.util.stream.*)。
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对
集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。
使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数
据库查询。也可以使用 Stream API 来并行执行操作。简而言之,
Stream API 提供了一种高效且易于使用的处理数据的方式。

什么是 Stream

流(Stream) 到底是什么呢?
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。

“集合讲的是数据,流讲的是计算

注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

Stream 的操作三个步骤

- 创建 Stream

一个数据源(如:集合、数组),获取一个流

- 中间操作

一个中间操作链,对数据源的数据进行处理

- 终止操作(终端操作)

一个终止操作,执行中间操作链,并产生结果

在这里插入图片描述

创建 Stream

  • default Stream stream() : 返回一个顺序流
  • default Stream parallelStream() : 返回一个并行流

由数组创建流

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

static Stream stream(T[] array): 返回一个流
重载形式,能够处理对应基本类型的数组:
 public static IntStream stream(int[] array)
 public static LongStream stream(long[] array)
 public static DoubleStream stream(double[] array)

由值创建流

可以使用静态方法 Stream.of(), 通过显示值创建一个流。它可以接收任意数量的参数。
public static<T> Stream<T> of(T... values) //: 返回一个流

由函数创建流:创建无限流

可以使用静态方法 Stream.iterate() 和Stream.generate(), 创建无限流。
  • 迭代
    public static Stream iterate(final T seed, final
    UnaryOperator f)
  • 生成
    public static Stream generate(Supplier s) :

Stream 的中间操作

多个中间操作可以连接起来形成一个流水线,除非流水 线上触发终止操作,否则中间操作不会执行任何的处理!
而在终止操作时一次性全部处理,称为“惰性求值”。

筛选与切片

方法描述
filter(Predicate p)接收 Lambda , 从流中排除某些元素。
distinct()筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
limit(long maxSize)截断流,使其元素不超过给定数量。
skip(long n)跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n)互补
filter(Predicate p)
distinct()
limit(long maxSize)
skip(long n)
package com.lyzdfintech.loongeasy.testengine;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Setter;import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;public class TestFort {public static void main(String[] args) {List<User> userList = getUserList();System.out.println(userList);System.out.println("=======================filter=========================");//1、filter:输出ID大于6的user对象List<User> filetrUserList = userList.stream().filter(user -> user.getId() > 6).collect(Collectors.toList());filetrUserList.forEach(System.out::println);System.out.println("=======================distinct=========================");//2、distinct:去重List<String> distinctUsers =  userList.stream().map(User::getCity).distinct().collect(Collectors.toList());distinctUsers.forEach(System.out::println);System.out.println("=======================limit=========================");//3、limit:取前5条数据userList.stream().limit(5).collect(Collectors.toList()).forEach(System.out::println);System.out.println("=======================skip=========================");//4、skip:跳过第几条取后几条userList.stream().skip(7).collect(Collectors.toList()).forEach(System.out::println);}private static List<User> getUserList() {List<User> userList = new ArrayList<>();userList.add(new User(1, "张三", 18, "上海"));userList.add(new User(2, "王五", 16, "上海"));userList.add(new User(3, "李四", 20, "上海"));userList.add(new User(4, "张雷", 22, "北京"));userList.add(new User(5, "张超", 15, "深圳"));userList.add(new User(6, "李雷", 24, "北京"));userList.add(new User(7, "王爷", 21, "上海"));userList.add(new User(8, "张三丰", 18, "广州"));userList.add(new User(9, "赵六", 16, "广州"));userList.add(new User(10, "赵无极", 26, "深圳"));return userList;}}@Data
@AllArgsConstructor
class User {int id;String name;int age;String city;}

映射

方 法描 述
map(Function f)接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
mapToDouble(ToDoubleFunction f)接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream。
mapToInt(ToIntFunction f)接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream。
mapToLong(ToLongFunction f)接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream。
flatMap(Function f)接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
map(Function f)
mapToDouble(ToDoubleFunction f)
mapToInt(ToIntFunction f)
mapToLong(ToLongFunction f)
flatMap(Function f)
package com.lyzdfintech.loongeasy.testengine;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Setter;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;public class TestFort {public static void main(String[] args) {List<User> userList = getUserList();System.out.println(userList);System.out.println("=======================map=========================");//1、mapList<String> mapUserList = userList.stream().map(user -> user.getName() + "用户").collect(Collectors.toList());mapUserList.forEach(System.out::println);System.out.println("=======================mapToDouble=========================");//2、mapToDoubleDoubleStream mapToDoubleList = userList.stream().map(user -> user.getAge()).mapToDouble(x ->x.doubleValue());mapToDoubleList.forEach(System.out::println);/*3、flatMap:数据拆分一对多映射*使用flatMap方法的效果是,各个数组并不是分别映射成一个流,而是映射成流的内容。所有使用map(Arrays::stream)时生成的单个流都被合并起来,即扁平化为一个流*/userList.stream().flatMap(user -> Arrays.stream(user.getCity().split(","))).forEach(System.out::println);}private static List<User> getUserList() {List<User> userList = new ArrayList<>();userList.add(new User(1, "张三", 18, "上海"));userList.add(new User(2, "王五", 16, "上海"));userList.add(new User(3, "李四", 20, "上海"));userList.add(new User(4, "张雷", 22, "北京"));userList.add(new User(5, "张超", 15, "深圳"));userList.add(new User(6, "李雷", 24, "北京"));userList.add(new User(7, "王爷", 21, "上海"));userList.add(new User(8, "张三丰", 18, "广州"));userList.add(new User(9, "赵六", 16, "广州"));userList.add(new User(10, "赵无极", 26, "深圳"));return userList;}}@Data
@AllArgsConstructor
class User {int id;String name;int age;String city;}

排序

方 法描 述
sorted()产生一个新流,其中按自然顺序排序
sorted(Comparator comp)产生一个新流,其中按比较器顺序排序
package com.lyzdfintech.loongeasy.testengine;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Setter;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;public class TestFort {public static void main(String[] args) {List<User> userList = getUserList();System.out.println(userList);System.out.println("=======================sorted-com=========================");//1、sorted:排序,根据id倒序userList.stream().sorted(Comparator.comparing(User::getId).reversed()).collect(Collectors.toList()).forEach(System.out::println);System.out.println("=======================sorted=========================");userList.stream().sorted().collect(Collectors.toList()).forEach(System.out::println);}private static List<User> getUserList() {List<User> userList = new ArrayList<>();userList.add(new User(1, "张三", 18, "上海"));userList.add(new User(2, "王五", 16, "上海"));userList.add(new User(3, "李四", 20, "上海"));userList.add(new User(4, "张雷", 22, "北京"));userList.add(new User(5, "张超", 15, "深圳"));userList.add(new User(6, "李雷", 24, "北京"));userList.add(new User(7, "王爷", 21, "上海"));userList.add(new User(8, "张三丰", 18, "广州"));userList.add(new User(9, "赵六", 16, "广州"));userList.add(new User(10, "赵无极", 26, "深圳"));return userList;}}@Data
@AllArgsConstructor
class User {int id;String name;int age;String city;}

Stream 的终止操作

查找与匹配

方 法描 述
allMatch(Predicate p)检查是否匹配所有元素
anyMatch(Predicate p)检查是否至少匹配一个元素
noneMatch(Predicate p)检查是否没有匹配所有元素
findFirst()返回第一个元素终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是 void 。
findAny()返回当前流中的任意元素
allMatch(Predicate p) 检查是否匹配所有元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicate p) 检查是否没有匹配所有元素
findFirst() 返回第一个元素终端操作会从流的流水线生成结果。
findAny() 返回当前流中的任意元素
package com.lyzdfintech.loongeasy.testengine;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Setter;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;public class TestFort {public static void main(String[] args) {List<User> userList = getUserList();System.out.println(userList);System.out.println("=======================matchAll + anyMatch + noneMatch=========================");//1、allMatch:检查是否匹配所有元素boolean matchAll = userList.stream().allMatch(user -> "北京".equals(user.getCity()));System.out.println("matchAll :" + matchAll);//2、anyMatch:检查是否至少匹配一个元素boolean matchAny = userList.stream().anyMatch(user -> "北京".equals(user.getCity()));System.out.println("anyMatch :" + matchAny);//3、noneMatch:检查是否没有匹配所有元素,返回booleanboolean nonaMatch = userList.stream().noneMatch(user -> "云南".equals(user.getCity()));System.out.println("noneMatch :" + nonaMatch);//4、findFirst:返回第一个元素User firstUser = userList.stream().findFirst().get();User firstUser1 = userList.stream().filter(user -> "上海".equals(user.getCity())).findFirst().get();System.out.println("firstUser :" + firstUser + ";" + "firstUser1 :" + firstUser1);//5、findAny:将返回当前流中的任意元素User findUser = userList.stream().findAny().get();User findUser1 = userList.stream().filter(user -> "上海".equals(user.getCity())).findAny().get();System.out.println("findUser :" + findUser + ";" + "findUser1 :" + findUser1);}private static List<User> getUserList() {List<User> userList = new ArrayList<>();userList.add(new User(1, "张三", 18, "上海"));userList.add(new User(2, "王五", 16, "上海"));userList.add(new User(3, "李四", 20, "上海"));userList.add(new User(4, "张雷", 22, "北京"));userList.add(new User(5, "张超", 15, "深圳"));userList.add(new User(6, "李雷", 24, "北京"));userList.add(new User(7, "王爷", 21, "上海"));userList.add(new User(8, "张三丰", 18, "广州"));userList.add(new User(9, "赵六", 16, "广州"));userList.add(new User(10, "赵无极", 26, "深圳"));return userList;}}@Data
@AllArgsConstructor
class User {int id;String name;int age;String city;}

归约

方 法描 述
count()返回流中元素总数
max(Comparator c)返回流中最大值
min(Comparator c)返回流中最小值
forEach(Consumer c)内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了)
reduce(T iden, BinaryOperator b)可以将流中元素反复结合起来,得到一个值。返回 T
reduce(BinaryOperator b)可以将流中元素反复结合起来,得到一个值。返回 Optional
count() |返回流中元素总数
max(Comparator c) 返回流中最大值
min(Comparator c)返回流中最小值
forEach(Consumer c) 内部迭代
reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 T
package com.lyzdfintech.loongeasy.testengine;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Setter;import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;public class TestFort {public static void main(String[] args) {List<User> userList = getUserList();System.out.println(userList);System.out.println("=======================归约=========================");//1、count:返回流中元素总数long count = userList.stream().filter(user -> user.getAge() > 20).count();System.out.println("count : " + count);//2、max:最大值int max = userList.stream().max(Comparator.comparingInt(User::getId)).get().getId();System.out.println("max id : " + max);//3、min:最小值int min = userList.stream().min(Comparator.comparingInt(User::getId)).get().getId();System.out.println("min id : " + min);//4、forEach:遍历流userList.stream().forEach(user -> System.out.println(user));userList.stream().filter(user -> "上海".equals(user.getCity())).forEach(System.out::println);System.out.println("reduce:");//5、reduce:将流中元素反复结合起来,得到一个值Optional reduce = userList.stream().reduce((user, user2) -> {user.name = user.name + user2.name;return user;});if(reduce.isPresent()) System.out.println(reduce.get());}private static List<User> getUserList() {List<User> userList = new ArrayList<>();userList.add(new User(1, "张三", 18, "上海"));userList.add(new User(2, "王五", 16, "上海"));userList.add(new User(3, "李四", 20, "上海"));userList.add(new User(4, "张雷", 22, "北京"));userList.add(new User(5, "张超", 15, "深圳"));userList.add(new User(6, "李雷", 24, "北京"));userList.add(new User(7, "王爷", 21, "上海"));userList.add(new User(8, "张三丰", 18, "广州"));userList.add(new User(9, "赵六", 16, "广州"));userList.add(new User(10, "赵无极", 26, "深圳"));return userList;}}@Data
@AllArgsConstructor
class User {int id;String name;int age;String city;}

收集

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

Collector 接口中方法的实现决定了如何对流执行收集操作(如收 集到 List、Set、Map)。但是 Collectors实用类提供了很多静态 方法,可以方便地创建常见收集器实例,具体方法与实例如下表:

方法返回类型作用
toListList把流中元素收集到List
List emps= list.stream().collect(Collectors.toList());
toSetSet把流中元素收集到Set
Set emps= list.stream().collect(Collectors.toSet());
toCollectionCollection把流中元素收集到创建的集合
Collectionemps=list.stream().collect(Collectors.toCollection(ArrayList::new));
countingLong计算流中元素的个数
long count = list.stream().collect(Collectors.counting());
summingIntInteger对流中元素的整数属性求和
inttotal=list.stream().collect(Collectors.summingInt(Employee::getSalary));
averagingIntDouble计算流中元素Integer属性的平均值
doubleavg= list.stream().collect(Collectors.averagingInt(Employee::getSalary));
summarizingIntIntSummaryStatistics收集流中Integer属性的统计值。如:平均值
IntSummaryStatisticsiss= list.stream().collect(Collectors.summarizingInt(Employee::getSalary));
joiningString连接流中每个字符串
String str= list.stream().map(Employee::getName).collect(Collectors.joining());
maxByOptional根据比较器选择最大值
Optionalmax= list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary)));
minByOptional根据比较器选择最小值
Optional min = list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary)));
reducing归约产生的类型从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值
inttotal=list.stream().collect(Collectors.reducing(0, Employee::getSalar, Integer::sum));
collectingAndThen转换函数返回的类型包裹另一个收集器,对其结果转换函数
inthow= list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
groupingByMap<K, List>根据某属性值对流分组,属性为K,结果为V
Map<Emp.Status, List> map= list.stream().collect(Collectors.groupingBy(Employee::getStatus));
partitioningByMap<Boolean, List>根据true或false进行分区
Map<Boolean,List>vd= list.stream().collect(Collectors.partitioningBy(Employee::getManage));

Collector:结果收集策略的核心接口,具备将指定元素累加存放到结果容器中的能力;并在Collectors工具中提供了Collector接口的实现类

1、toList

将用户ID存放到List集合中

        //1.toListList<Integer> idList = userList.stream().map(User::getId).collect(Collectors.toList());System.out.println(idList);
2、toMap
        //2.toMap  id name 以key value形式保存Map<Integer,String> userMap = userList.stream().collect(Collectors.toMap(User::getId,User::getName));System.out.println(userMap);
3、toSet
        //3.toSetSet<String> userCitySet = userList.stream().map(user -> user.getCity()).collect(Collectors.toSet());System.out.println(userCitySet);
4、counting

符合条件的用户总数

long count = userList.stream().filter(user -> user.getId()>1).collect(Collectors.counting());
5、summingInt

对结果元素即用户ID求和

Integer sumInt = userList.stream().filter(user -> user.getId()>2).collect(Collectors.summingInt(User::getId)) ;
6、minBy

筛选元素中ID最小的用户

User maxId = userList.stream().collect(Collectors.minBy(Comparator.comparingInt(User::getId))).get() ;
7、joining

将用户所在城市,以指定分隔符链接成字符串;

String joinCity = userList.stream().map(User::getCity).collect(Collectors.joining("||"));
8、groupingBy

按条件分组,以城市对用户进行分组;

Map<String,List<User>> groupCity = userList.stream().collect(Collectors.groupingBy(User::getCity));
1.orElse(null)

表示如果一个都没找到返回null(orElse()中可以塞默认值。如果找不到就会返回orElse中设置的默认值)

 /*** Return the value if present, otherwise return {@code other}.** @param other the value to be returned if there is no value present, may* be null* @return the value, if present, otherwise {@code other}* 返回值,如果存在,否则返回其他*/public T orElse(T other) {return value != null ? value : other;}
2.orElseGet(null)

表示如果一个都没找到返回null(orElseGet()中可以塞默认值。如果找不到就会返回orElseGet中设置的默认值)
orElse() 接受类型T的 任何参数,而orElseGet()接受类型为Supplier的函数接口,该接口返回类型为T的对象

 /*** Return the value if present, otherwise invoke {@code other} and return* the result of that invocation.** @param other a {@code Supplier} whose result is returned if no value* is present* @return the value if present otherwise the result of {@code other.get()}* @throws NullPointerException if value is not present and {@code other} is* null* 返回值如果存在,否则调用其他值并返回该调用的结果*/public T orElseGet(Supplier<? extends T> other) {return value != null ? value : other.get();}
orElse(null)和orElseGet(null)区别:

1、当返回Optional的值是空值null时,无论orElse还是orElseGet都会执行

2、而当返回的Optional有值时,orElse会执行,而orElseGet不会执行

package com.lyzdfintech.loongeasy.testengine;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Setter;import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;public class TestStream {public static void main(String[] args) {List<UserP> list = new ArrayList<>();//定义三个用户对象UserP UserP1 = new UserP();UserP1.setUserName("admin");UserP1.setAge(16);UserP1.setSex("男");UserP UserP2 = new UserP();UserP2.setUserName("root");UserP2.setAge(20);UserP2.setSex("女");UserP UserP3 = new UserP();UserP3.setUserName("admin");UserP3.setAge(18);UserP3.setSex("男");UserP UserP4 = new UserP();UserP4.setUserName("admin11");UserP4.setAge(22);UserP4.setSex("女");//添加用户到集合中list.add(UserP1);list.add(UserP2);list.add(UserP3);list.add(UserP4);/*在集合中查询用户名包含admin的集合*/List<UserP> UserPList = list.stream().filter(UserP -> UserP.getUserName().contains("admin")&& UserP.getAge() <= 20).collect(Collectors.toList());System.out.println(UserPList);/*在集合中查询出第一个用户名为admin的用户*/Optional<UserP> UserP = list.stream().filter(UserPTemp -> "admin".equals(UserPTemp.getUserName())).findFirst();System.out.println(UserP);/*orElse(null)表示如果一个都没找到返回null(orElse()中可以塞默认值。如果找不到就会返回orElse中设置的默认值)orElseGet(null)表示如果一个都没找到返回null(orElseGet()中可以塞默认值。如果找不到就会返回orElseGet中设置的默认值)orElse()和orElseGet()区别:在使用方法时,即使没有值 也会执行 orElse 内的方法, 而 orElseGet则不会*///没值UserP a =  list.stream().filter(UserPT-> UserPT.getAge() == 12).findFirst().orElse(getMethod("a"));UserP b =  list.stream().filter(UserPT11-> UserPT11.getAge() == 12).findFirst().orElseGet(()->getMethod("b"));//有值UserP c =  list.stream().filter(UserPT2-> UserPT2.getAge() == 16).findFirst().orElse(getMethod("c"));UserP d =  list.stream().filter(UserPT22-> UserPT22.getAge() == 16).findFirst().orElseGet(()->getMethod("d"));System.out.println("a:"+a);System.out.println("b:"+b);System.out.println("c:"+c);System.out.println("d:"+d);}public static UserP getMethod(String name){System.out.println(name + "执行了方法");return null;}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Setter
class UserP{String userName;int age;String sex;
}

[UserP(userName=admin, age=16, sex=男), UserP(userName=admin, age=18, sex=男)]
Optional[UserP(userName=admin, age=16, sex=男)]
a执行了方法
b执行了方法
c执行了方法
a:null
b:null
c:UserP(userName=admin, age=16, sex=男)
d:UserP(userName=admin, age=16, sex=男)
Process finished with exit code 0

并行流和串行流

并行流就是把一个内容分成多个数据块,并用不同的线程分
别处理每个数据块的流。
Java 8 中将并行进行了优化,我们可以很容易的对数据进行并
行操作。Stream API 可以声明性地通过 parallel() 与
sequential() 在并行流与顺序流之间进行切换。

5. 新时间日期 API

使用 LocalDate、LocalTime、LocalDateTime

LocalDate、LocalTime、LocalDateTime 类的实 例是不可变的对象,分别表示使用 ISO-8601日
历系统的日期、时间、日期和时间。它们提供 了简单的日期或时间,并不包含当前的时间信 息。也不包含与时区相关的信息。

方法描述示例
now()静态方法,根据当前时间创建对象LocalDate localDate = LocalDate.now();LocalTime localTime = LocalTime.now();LocalDateTime localDateTime = LocalDateTime.now();
of()静态方法,根据指定日期/时间创建对象LocalDate localDate = LocalDate.of(2016, 10, 26);LocalTime localTime = LocalTime.of(02, 22, 56);LocalDateTime localDateTime = LocalDateTime.of(2016, 10, 26, 12, 10, 55);
plusDays, plusWeeks,plusMonths, plusYears向当前 LocalDate 对象添加几天、几周、几个月、几年
minusDays, minusWeeks,minusMonths, minusYears从当前 LocalDate 对象减去几天、几周、几个月、几年
plus, minus添加或减少一个 Duration 或 Period
withDayOfMonth,withDayOfYear,withMonth,withYear将月份天数、年份天数、月份、年份 修 改 为 指 定 的 值 并 返 回 新 的LocalDate 对象
getDayOfMonth获得月份天数(1-31),getDayOfYear 获得年份天数(1-366),getDayOfWeek 获得星期几(返回一个DayOfWeek枚举值)
getMonth获得月份, 返回一个 Month 枚举值
getMonthValue获得月份(1-12)
getYear获得年份
until获得两个日期之间的 Period 对象,或者指定 ChronoUnits 的数字
isBefore, isAfter比较两个 LocalDate
isLeapYear判断是否是闰年

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/479791.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows 使设置更改立即生效——并行发送广播消息

目录 前言 1 遍历窗口句柄列表 2 使用 SendMessageTimeout 发送延时消息 3 并行发送消息实现模拟广播消息 4 修改 UIPI 消息过滤器设置 5 托盘图标刷新的处理 6 完整代码和测试 本文属于原创文章&#xff0c;转载请注明出处&#xff1a; https://blog.csdn.net/qq_5907…

单片机stm32智能鱼缸

随着我国经济的快速发展而给人们带来了富足的生活&#xff0c;也有越来越多的人们开始养鱼&#xff0c;通过养各种鱼类来美化居住环境和缓解压力。但是在鱼类饲养过程中&#xff0c;常常由于鱼类对水质、水位及光照强度有着很高的要求&#xff0c;而人们也由于工作的方面而无法…

【STM32】硬件SPI读写W25Q64芯片

目录 基础知识回顾&#xff1a; SPI外设简介 SPI框图 主模式全双工连续传输 非连续传输 初始化SPI外设 核心代码 - 交换一个字节 硬件接线图 Code 程序配置过程 MySPI.c MySPI.h W25Q64.c W25Q64.h W25Q64_Ins.h main.c 基础知识回顾&#xff1a; 【STM32】SP…

opencv安装介绍以及基本图像处理详解

文章目录 一、什么是OpenCV &#xff1f;二. OpenCV 安装1. 下载地址2.安装命令&#xff1a;pip install opencv-python 三、图像基础1. 基本概念2. 坐标系3. 基本操作&#xff08;彩色图片&#xff09;&#xff08;1&#xff09;读取图片&#xff1a;cv2.imread( )&#xff08…

java中实体pojo对于布尔类型属性命名尽量别以is开头,否则 fastjson可能会导致属性读取不到

假如我们有一个场景&#xff0c;就是需要将一个对象以字符串的形式&#xff0c;也就是jsonString存到一个地方&#xff0c;比如mysql&#xff0c;或者redis的String结构。现在有一个实体&#xff0c;我们自己创建的&#xff0c;叫做CusPojo.java 有两个属性是布尔类型的&#x…

获取 Windows 系统托盘图标信息的最新方案(一)

目录 前言 1 获取系统托盘图标的一般方法 1.1 使用 TB_ 类消息的注意事项 1.2 代码编写和测试 1.3 技术的适用范围 2 深度分析系统托盘图标信息 2.1 分析 Shell_NotifyIcon 函数参数 2.2 分析 Shell_NotifyIcon 函数的内部细节 2.3 分析 WM_COPYDATA 消息 2.4 调用方…

Milvus数据库介绍

参考&#xff1a;https://www.xjx100.cn/news/1726910.html?actiononClick Milvus 基于FAISS、Annoy、HNSW 等向量搜索库构建&#xff0c;核心是解决稠密向量相似度检索的问题。在向量检索库的基础上&#xff0c;Milvus 支持数据分区分片、数据持久化、增量数据摄取、标量向量…

前端简单知识复习

1.symbol类型 Symbol 是 ECMAScript 6 中引入的一种新的基本数据类型&#xff0c;它表示独一无二的值。Symbol 值是通过 Symbol() 函数创建的。 Symbol 值具有以下特点&#xff1a; 独一无二性&#xff08;唯一性&#xff09;&#xff1a;每个通过 Symbol() 函数创建的 Symb…

【硬核】Log4j2 与 Logback 当初的选型以及在当前云原生环境下的反思与展望

个人创作公约&#xff1a;本人声明创作的所有文章皆为自己原创&#xff0c;如果有参考任何文章的地方&#xff0c;会标注出来&#xff0c;如果有疏漏&#xff0c;欢迎大家批判。如果大家发现网上有抄袭本文章的&#xff0c;欢迎举报&#xff0c;并且积极向这个 github 仓库 提交…

【动态规划专栏】专题二:路径问题--------6.地下城游戏

本专栏内容为&#xff1a;算法学习专栏&#xff0c;分为优选算法专栏&#xff0c;贪心算法专栏&#xff0c;动态规划专栏以及递归&#xff0c;搜索与回溯算法专栏四部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握算法。 &#x1f493;博主csdn个人主页&#xff1a;小…

详解FreeRTOS:系统内核控制函数(拓展篇—8)

FreeRTOS 中系统内核控制函数只供系统内核使用&#xff0c;用户应用程序一般不允许使用&#xff0c;本篇博文讲解这些函数仅供大家了解和参考。 在 FreeRTOS 官网可以找到这些函数&#xff0c;如下图所示&#xff1a; 链接&#xff1a;https://www.freertos.org/zh-cn-cmn-s/a0…

Spin Image特征描述子简介

一、向量点积 二、狄拉克δ函数公式 三、Spin Image特征描述子原理 Spin Image自旋图像描述符可视化以及ICP配准-CSDN博客