函数式编程

函数式编程-Stream

Stream流

操作对象是集合和数组,可以更加方便的让我们对集合和数组进行操作。

package StreamTest;

import java.util.Arrays;
import java.util.Random;
import java.util.function.IntConsumer;
import java.util.function.IntPredicate;

public class StreamOne {
    public static void main(String[] args) {
        int[] nums=new int[100];
        int i=0;
        Random r=new Random();
        while(i<100){
            nums[i++]=r.nextInt(101);
        }
        Arrays.stream(nums)
                .distinct() //去重
                .filter( value->value<50) //过滤
                .forEach( value-> System.out.println(value));//终结操作 如果没有终结操作的话就不会执行中间操作 
    }
}

流的创建流程

创建流

  • 单例集合创建流 集合.stream()

    List<Integer> list = new ArrayList<>();
    Stream<Integer> stream = list.stream(); 
    
  • 数组:使用数组工具类Arrays.stream(数组实例对象)或者是Stream.of()

    IntStream stream1 = Arrays.stream(nums);
    Stream.of(nums);
    
  • 双列集合:首先转换成为单列集合之后再创建(Map)

    Set<Map.Entry<String, String>> entries = map.entrySet();
    entries.stream().forEach(System.out::println);
    

中间操作

  • filter过滤操作,将返回值为true的值将器保留下来,其他的全部的抛弃

  • map操作,可以对流中的数据进行计算和转换

      <R> Stream<R> map(Function<? super T, ? extends R> mapper); 
    //观察到map接收的参数是一个Function队列,Function是一个函数式接口,里面存在一个apply方法将T类型转换成为R类型,相当于是一个适配器
         list.stream()
                    .map(s -> Integer.valueOf(s)) //价格String类型转换成为Integer类型,
                    .forEach(System.out::println);
    
  • distinct去重操作 ,注意distinct的底层是使用的equals方法来比较的,如果我们重写了equals方法的话那么distinct就会使用重写之后的equals方法,如果是maven项目的话可以是用lombok@EqualsAndHashCode重写Equals方法和HashCode方法。不然就会使用Object方法(只有两个对象的地址相同的时候才相等)

  • sorted对流里面的数据进行排序 ,

    Stream.sorted()空参方法。
    //需要注意的是除了数据类型,其他类型需要实现Comparable,如果此流的元素不是Comparable,则在执行终端操作时可能会抛出 。java.lang.ClassCastException。
    Stream<T> sorted(Comparator<? super T> comparator);
    //需要自己实现比较器
    
  • limit 设置流的长度,超出的部分将会被抛弃掉

  • skip 跳过前面的数据,打印剩下的数据

  • flatMap

    map只能把一个对象转换成为另一个对象来作为流中的元素。而flatMap可以把一个对象转换成为多个对象作为流中的元素。

终结操作

  • count计算流中元素个数

  • min:求流中的最小值

  • max:求流中的最大值

  • collect:将流中的数据转换成为集合

    • 转换成list集合

      list.stream()
          .sorted(( o1, o2) -> Integer.valueOf(o2)-Integer.valueOf(o1))
          .collect(Collectors.toList()); //使用集合的工具类Collections.toList()转换成List集合
      
    • 转换成为Set集合

      list.stream()
          .sorted(( o1, o2) -> Integer.valueOf(o2)-Integer.valueOf(o1))
          .collect(Collectors.toSet());
      
    • 转换成为Map集合

      list.stream()
          .sorted(( o1, o2) -> Integer.valueOf(o2)-Integer.valueOf(o1))
          .collect(Collectors.toMap());
      
    • reduce方法

查找匹配

  • anyMatch 相当于判断是否存在
  • allMatch 判断是否流中的元素全部都满足条件
  • findAny :随机查找数据
  • findfirst:查找第一个数据

Optional

概述

Optional是在java.util包下的一个用于代替null的一个工具类

Optional的构造方法

JDK 提供三个静态方法来构造一个Optional:

2.1 Optional.of(T value),该方法通过一个非 null 的 value 来构造一个 Optional,返回的 Optional 包含了 value 这个值。对于该方法,传入的参数一定不能为 null,否则便会抛出 NullPointerException。

2.2 Optional.ofNullable(T value),该方法和 of 方法的区别在于,传入的参数可以为 null , 但是前面 javadoc 不是说 Optional 只能包含非 null 值吗?原来该方法会判断传入的参数是否为 null,如果为 null 的话,返回的就是 Optional.empty()。

2.3 Optional.empty(),该方法用来构造一个空的 Optional,即该 Optional 中不包含值,其实底层实现还是 如果 Optional 中的 value 为 null 则该 Optional 为不包含值的状态,然后在 API 层面将 Optional 表现的不能包含 null 值,使得 Optional 只存在 包含值 和 不包含值 两种状态。

String str="";
Optional<String> str1 = Optional.ofNullable(str);
str1.ifPresent(s -> System.out.println("Hello World")); .//如果S为null是则不会执行下面的语句

安全消费

使用ifPresent(),当只有参数存在,才会消费

public void ifPresent(Consumer<? super T> consumer) {
    if (value != null)
        consumer.accept(value);
}

安全的获取值

不安全的获取值使用get()方法,当Optianal里面的值为null就会抛出异常

  • orElseGet 有值就返回值,没有值就返回自己定义的值
public T orElseGet(Supplier<? extends T> other) {
    return value != null ? value : other.get();
}

  • orElseThrow()有值的时候返回值,值为null时候,就使用自己定义的异常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

str1.orElseThrow(()->new RuntimeException("元素值为NULL"));

Stream对基本数据类型的优化

image-20230919195232998

并行流

并行流就是将一个流的内容分成多个数据块,并用不同的线程分别处理每个不同数据块的流

并行流结构

posted @ 2023-12-17 23:57  zL66  阅读(1)  评论(0编辑  收藏  举报