java8-Stream流

一、Stream是什么?

Stream 是 Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。
使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

二、Stream流的实际应用

基础类

@Data //该注解需要引用lombok包
class Employee {
    private int id;
    private String name;
    private int age;
    private double salary;
   }
    List<Employee> emps = Arrays.asList(
            new Employee(102, "李四", 59, 6666.66),
            new Employee(101, "张三", 18, 9999.99),
            new Employee(103, "王五", 28, 3333.33),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(105, "田七", 38, 5555.55)
    );

在这里插入图片描述

1、filter过滤操作

//返回年龄小于等于28的流,转成List
List<Employee> employeeList = emps.stream()
                .filter((e) -> e.getAge() <= 28).collect(Collectors.toList());
//打印当前List
employeeList.stream().forEach(System.out::println);

2、map操作

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

//提取emps集合中的name元素,并转成List
List<String> collect = emps.stream()
                .map(Employee::getName).collect(Collectors.toList());
//打印name
collect.stream().forEach(System.out::println);

//将该集合元素转成大写
List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
List<String> stringList = strList.stream()
          .map(String::toUpperCase).collect(Collectors.toList());

3、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
  • reduce(BinaryOperator b) ======== 可以将流中元素反复结合起来,得到一个值。 返回 Optional
  • collect(Collector c) ======== 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
//检查是否至少匹配一个元素,false
boolean bl1 = emps.stream()
                .anyMatch((e) -> "赵武".equals(e.getName()));
 //返回name是赵六的对象个数
long count = emps.stream().filter((e) -> "赵六".equals(e.getName())).count();

4、Optional 常用方法

Optional 是一个容器对象,可以存储对象、字符串等值,当然也可以存储 null 值。Optional 提供很多有用的方法,能帮助我们将 Java 中的对象等一些值存入其中,这样我们就不用显式进行空值检测,使我们能够用少量的代码完成复杂的流程。

of 方法通过工厂方法创建 Optional 实例,需要注意的是传入的参数不能为 null,否则抛出 NullPointerException

 // 传入正常值,正常返回一个 Optional 对象
  Optional<String> optional1 = Optional.of("mydlq");
  // 传入参数为 null,抛出 NullPointerException.
  //Optional optional2 = Optional.of(null);
  //get方法获得传入的值
  System.out.println(optional1.get());

ofNullable 方法是和 of 方式一样,都是用于创建 Optional 对象,只是传入的参数 null 时,会返回一个空的 Optional 对象,而不会抛出 NullPointerException 异常

// 传入正常值,正常返回一个 Optional 对象
Optional<String> optional1 = Optional.ofNullable("mydlq");
// 传入 null 参数,正常返回 Optional 对象。不会抛异常
Optional optional2 = Optional.ofNullable(null);

isPresent方法用于判断创建 Optional 时传入参数的值是否为空

// 传入正常值,正常返回一个 Optional 对象,并使用 isPresent 方法
Optional optional1 = Optional.ofNullable("mydlq");
System.out.println("传入正常值返回:" + optional1.isPresent());//false

// 传入参数为 null 生成一个 Optional 对象,并使用 isPresent 方法
Optional optional2 = Optional.ofNullable(null);
System.out.println("传入 null 值返回:" + optional2.isPresent()); //true

get 方法内部实现其实就是判断 Otpional 对象中的 value 属性是否为 null,如果是就抛出 NoSuchElementException 异常,否则返回这个 value 值

// 传入正常值,正常返回一个 Optional 对象,并使用 get 方法获取值
   Optional optional1 = Optional.ofNullable("mydlq");
   System.out.println(optional1.get());

   // 传入参数为 null 生成一个 Optional 对象,并使用 get 方法获取值,报空指针异常
   Optional optional2 = Optional.ofNullable(null);
   System.out.println(optional2.get());

orElse 方法实现很简单,就是使用三目表达式对传入的参数值进行 null 验证,即 value != null ? value : other; 如果为 null 则返回 true,否则返回 false

       // 传入正常参数,获取一个 Optional 对象,并使用 orElse 方法设置默认值
       Optional optional1 = Optional.ofNullable("mydlq");
       Object object1 = optional1.orElse("默认值");
       System.out.println("如果值不为空:" + object1);

       // 传入 null 参数,获取一个 Optional 对象,并使用 orElse 方法设置默认值
       Optional optional2 = Optional.ofNullable(null);
       Object object2 = optional2.orElse("默认值");
       System.out.println("如果值为空:" + object2);

orElseGet 方法和 orElse 方法类似,都是在 Optional 值为空时,返回一个默认操作,只不过 orElse 返回的是默认值,而 orElseGet 是执行 lambda 表达式,然后返回 lambda 表达式执行后的结果

// 传入正常参数,获取一个 Optional 对象,并使用 orElse 方法设置默认值
 Optional optional1 = Optional.ofNullable("mydlq");
 Object object1 = optional1.orElseGet(() -> {
     String defaultVal = "执行逻辑和生成的默认值";
     return defaultVal;
 });
 System.out.println("输出的值为:"+object1);

 // 传入 null 参数,获取一个 Optional 对象,并使用 orElse 方法设置默认值
 Optional optional2 = Optional.ofNullable(null);
 Object object2 = optional2.orElseGet(() -> {
     String defaultVal = "执行逻辑和生成的默认值";
     return defaultVal;
 });
 System.out.println("输出的值为:"+object2);

…还有Optional 的map、filter等用法,自行百度哈!!!

5、Stream.reduce()使用案例

/**
 * reduce计算数组的和
 */
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int sum = Arrays.stream(numbers).reduce(0, Integer::sum); // 55
//reduce求出数组最大值
int max = Arrays.stream(numbers).reduce(0, (a, b) -> a > b ? a : b);  // 10
//reduce求出数组最小值
int min = Arrays.stream(numbers).reduce(0, (a, b) -> a < b ? a : b);  // 0

6、Stream 的collect(Collector c) 方法用法

 //计算流中元素的个数
 long count = emps.stream().collect(Collectors.counting());
 //计算年龄总和
 int total=emps.stream().collect(Collectors.summingInt(Employee::getAge));
 //计算平均年龄
 Double avg = emps.stream().collect(Collectors.averagingInt(Employee::getAge));
 //计算最大年龄
 Optional<Employee> max= emps.stream().collect(Collectors.maxBy(comparingInt(Employee::getAge)));
 int maxAge = max.get().getAge();

7、java8排序

排序先了解下Comparable、Comparator两个排序类的使用,方便更好的理解排序类

sorted() 方法产生一个新流,其中按自然顺序排序

List<String> strList = Arrays.asList("张", "李", "啊", "亚", "不");
//排序操作--并打印
strList.stream().sorted().forEach(System.out::println);

sorted(Comparator comp) 方法产生一个新流,其中按比较器顺序排序

@Data
@ToString
public class Employee {
	private int id;
	private String name;
	private int age;
	private double salary;
	private Status status;

	public Employee() {
	}
}
    List<Employee> emps = Arrays.asList(
            new Employee(102, "李四", 59, 6666.66),
            new Employee(101, "张三", 18, 9999.99),
            new Employee(103, "王五", 28, 3333.33),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(104, "赵六", 8, 7777.77),
            new Employee(105, "田七", 38, 5555.55)
    );

//按照年龄大小排序,如果年龄相等,则按照姓名排序。
  emps.stream()
           .sorted((x, y) -> {
               if (x.getAge() == y.getAge()) {
                   return x.getName().compareTo(y.getName());
               } else {
                   return Integer.compare(x.getAge(), y.getAge());
               }
           }).forEach(System.out::println);

一些骚气的写法

//按照年龄排序
emps.stream().sorted(Comparator.comparingInt(Employee::getAge)).collect(Collectors.toList());

//按照年龄倒序
emps.stream().sorted(Comparator.comparingInt(Employee::getAge).reversed());

 //按照年龄、姓名排序
 emps.sort(Comparator.comparing(Employee::getAge)
         .thenComparing(Employee::getName)
 );
 
 //按照姓名升序,年龄降序
 emps.sort(Comparator.comparing(Employee::getName)
         .thenComparing(Employee::getAge,((o1, o2) -> o2-o1))
 );

8、java8多条件去重


/**
 * List<Map>多条件去重
*/
String s = "[{\"name\":\"张刚\",\"age\":\"3\"},{\"name\":\"张刚\",\"age\":\"3\"}]";
List<Map<String, Object>> list2 = JSONArray.parseObject(s, List.class);
List<Map<String, Object>> collect = list2.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.get("name") + ";" + o.get("age")))), ArrayList::new));
collect.stream().forEach(System.out::println);


/**
 * List<实体>多条件去重
*/
List<Student> list = JSON.parseArray(s, Student.class);
List<Student> collect2 = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getName() + ";" + o.getAge()))), ArrayList::new));
collect2.stream().forEach(System.out::println);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北漂IT民工_程序员_ZG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值