函数式编程
函数式编程-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
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对基本数据类型的优化
并行流
并行流就是将一个流的内容分成多个数据块,并用不同的线程分别处理每个不同数据块的流