Java8 Stream流与Optional的使用指南

Stream简介

Stream流不存储数据,它的作用是检索和逻辑处理集合数据、包括筛选、排序、统计、计数等。可以想象成是 Sql 语句。

它的源数据可以是Collection、Array等。由于它的方法参数都是函数式接口类型,所以一般和 Lambda 配合使用。

Stream流类型

1.stream 串行流

2.parallelStream 并行流,可以多线程执行,基于 ForkJoin 框架实现

常用方法

接下来我们看java.util.stream.Stream常用方法

/**
* 返回一个串行流
*/
default Stream stream()

/**
* 返回一个并行流
*/
default Stream parallelStream()

/**
* 返回T的流
*/
public static Stream of(T t)

/**
* 返回其元素是指定值的顺序流。
*/
public static Stream of(T... values) {
    return Arrays.stream(values);
}


/**
* 过滤,返回由与给定predicate匹配的该流的元素组成的流
*/
Stream filter(Predicate predicate);

/**
* 此流的所有元素是否与提供的predicate匹配。
*/
boolean allMatch(Predicate predicate)

/**
* 此流任意元素是否有与提供的predicate匹配。
*/
boolean anyMatch(Predicate predicate);

/**
* 返回一个 Stream的构建器。
*/
public static Builder builder();

/**
* 使用 Collector对此流的元素进行归纳
*/
 R collect(Collector collector);

/**
 * 返回此流中的元素数。
*/
long count();

/**
* 返回由该流的不同元素(根据 Object.equals(Object) )组成的流。
*/
Stream distinct();

/**
 * 遍历
*/
void forEach(Consumer action);

/**
* 用于获取指定数量的流,截短长度不能超过 maxSize 。
*/
Stream limit(long maxSize);

/**
* 用于映射每个元素到对应的结果
*/
 Stream map(Function mapper);

/**
* 根据提供的 Comparator进行排序。
*/
Stream sorted(Comparator comparator);

/**
* 在丢弃流的第一个 n元素后,返回由该流的 n元素组成的流。
*/
Stream skip(long n);

/**
* 返回一个包含此流的元素的数组。
*/
Object[] toArray();

/**
* 使用提供的 generator函数返回一个包含此流的元素的数组,以分配返回的数组,以及分区执行或调整大小可能需要的任何其他数组。
*/
 A[] toArray(IntFunction generator);

/**
* 合并流
*/
public static  Stream concat(Stream a, Stream b)

具体使用示例

List strings = Arrays.asList("abc", "def", "gkh", "abc"); 
//返回符合条件的stream
Stream stringStream = strings.stream().filter(s -> "abc".equals(s));
//计算流符合条件的流的数量
long count = stringStream.count();

//forEach遍历->打印元素
strings.stream().forEach(System.out::println);

//limit 获取到1个元素的stream
Stream limit = strings.stream().limit(1);
//toArray 比如我们想看这个limitStream里面是什么,比如转换成String[],比如循环
String[] array = limit.toArray(String[]::new);

//map 对每个元素进行操作返回新流
Stream map = strings.stream().map(s -> s + "22");

//sorted 排序并打印
strings.stream().sorted().forEach(System.out::println);

//Collectors collect 把abc放入容器中
List collect = strings.stream().filter(string -> "abc".equals(string)).collect(Collectors.toList());
//把list转为string,各元素用,号隔开
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(","));

//对数组的统计,比如用
List number = Arrays.asList(1, 2, 5, 4);

IntSummaryStatistics statistics = number.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("列表中最大的数 : "+statistics.getMax());
System.out.println("列表中最小的数 : "+statistics.getMin());
System.out.println("平均数 : "+statistics.getAverage());
System.out.println("所有数之和 : "+statistics.getSum());

//concat 合并流
List strings2 = Arrays.asList("xyz", "jqx");
Stream.concat(strings2.stream(),strings.stream()).count();

//注意 一个Stream只能操作一次,不能断开,否则会报错。
Stream stream = strings.stream();
//第一次使用
stream.limit(2);
//第二次使用
stream.forEach(System.out::println);
//报错 java.lang.IllegalStateException: stream has already been operated upon or closed

//但是可以这样, 连续使用
stream.limit(2).forEach(System.out::println);

Optional简介

Optional 是 Java8 提供的为了解决 null 安全问题的一个 API。善用 Optional 可以使我们代码中很多繁琐、丑陋的设计变得十分优雅

Stream 中的 findAny、max/min、reduce 等方法等返回 Optional 值。还有例如 IntStream.average() 返回 OptionalDouble 等等

假设有一个 Zoo 类,里面有个属性 Dog,需求要获取 Dog 的 age

class Zoo {
   private Dog dog;
}

class Dog {
   private int age;
}

传统解决NPE的方法

Zoo zoo = getZoo();
if(zoo != null){
   Dog dog = zoo.getDog();
   if(dog != null){
      int age = dog.getAge();
      System.out.println(age);
   }
}

使用Optional后的代码

Optional.ofNullable(zoo).map(o -> o.getDog()).map(d -> d.getAge()).ifPresent(age ->
    System.out.println(age)
);

Optional类中的方法

上例中Optional.ofNullable是其中一种创建 Optional 的方式。我们先看一下它的含义和其他创建 Optional 的源码方法。

创建Optional

/**
* Common instance for {@code empty()}. 全局EMPTY对象
*/
private static final Optional EMPTY = new Optional<>();

/**
* Optional维护的值
*/
private final T value;

/**
* 如果value是null就返回EMPTY,否则就返回of(T)
*/
public static  Optional ofNullable(T value) {
   return value == null ? empty() : of(value);
}
/**
* 返回 EMPTY 对象
*/
public static Optional empty() {
   Optional t = (Optional) EMPTY;
   return t;
}
/**
* 返回Optional对象
*/
public static  Optional of(T value) {
    return new Optional<>(value);
}
/**
* 私有构造方法,给value赋值
*/
private Optional(T value) {
  this.value = Objects.requireNonNull(value);
}
/**
* 所以如果of(T value) 的value是null,会抛出NullPointerException异常,这样貌似就没处理NPE问题
*/
public static  T requireNonNull(T obj) {
  if (obj == null)
         throw new NullPointerException();
  return obj;
}

ofNullable方法和of方法唯一区别就是当 value 为 null 时,ofNullable 返回的是EMPTY,of 会抛出 NullPointerException 异常。如果需要把 NullPointerException 暴漏出来就用 of,否则就用 ofNullable。

map()相关方法

/**
* 如果value为null,返回EMPTY,否则返回Optional封装的参数值
*/
public Optional map(Function mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
}
/**
* 如果value为null,返回EMPTY,否则返回Optional封装的参数值,如果参数值返回null会抛 NullPointerException
*/
public Optional flatMap(Function> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
        }
}

两个方法区别:

flatMap()参数返回值如果是 null 会抛 NullPointerException,而 map()返回EMPTY

判断 value 是否为 null

/**
* value是否为null
*/
public boolean isPresent() {
    return value != null;
}
/**
* 如果value不为null执行consumer.accept
*/
public void ifPresent(Consumer consumer) {
   if (value != null)
    consumer.accept(value);
}

获取value

/**
* Return the value if present, otherwise invoke {@code other} and return
* the result of that invocation.
* 如果value != null 返回value,否则返回other的执行结果
*/
public T orElseGet(Supplier other) {
    return value != null ? value : other.get();
}

/**
* 如果value != null 返回value,否则返回T
*/
public T orElse(T other) {
    return value != null ? value : other;
}

/**
* 如果value != null 返回value,否则抛出参数返回的异常
*/
public  T orElseThrow(Supplier exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
}
/**
* value为null抛出NoSuchElementException,不为空返回value。
*/
public T get() {
  if (value == null) {
      throw new NoSuchElementException("No value present");
  }
  return value;
}

filter()

/**
* 1. 如果是empty返回empty
* 2. predicate.test(value)==true 返回this,否则返回empty
*/
public Optional filter(Predicate predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
}

Optional常见使用

Optional.ofNullable(zoo).map(o -> o.getDog()).map(d -> d.getAge()).filter(v->v==1).orElse(3);

你可能感兴趣的:(Java8 Stream流与Optional的使用指南)