java基础之Stream流(二)

1 其他流的转换

distinct方法会返回一个流,它的流是从原有的流中产生的,即原来的元素按照同样的顺序剔除重复元素后产生的。这个流显然能记住它已经见过的元素。

Stream<String> stream = Stream.of("work","word","sister","word")
                              .distinct();

对于流的排序,有多种sorted方法变体可用。其中一种利用操做Comparable元素的流,而另一种可以接受一个Comparator。下面是对一个字符串进行排序,是最长的字符串排到最前面:

List<String> word = new ArrayList<>();
word.add("word");
word.add("student");

Stream<String> longestFirst = word.stream()
                                  .sorted(Comparator(String::length).reversed());

与所有的转换流一样,会产生一个新的流,它的元素还是原有流按照顺序排列的元素。

当然,我们对集合的排序可以不使用流。但是,当排序处理成为流管道的一部分时,sorted方法就显得有用了。

        最后peek会产生一个新的流,它的元素与原来的元素相同,但每次获取一个元素时都会调用一个函数。这对于调试非常方便。

Object[] power = Stream.iterate(2.0,p -> p*2)
                       .peek(e -> System.out.println("Fething"+e))
                       .limit(20)
                       .toArray();

当实际访问一个元素时,就会打印一条消息。通过这种方式你就可以验证iterate返回的无限流是被惰性处理的。对于调试,你也可以让peek调用一个你设置断点的地方。

2 简单约简

        约简是一种终结操作,它们会将流约简成可以在程序中使用的非流值。

        count方法就是一种简单约简,会返回流中元素的数量。其他的简单约简还有max和min,它们会返回最大值和最小值。这两个方法返回的是Optional<T>的值,它要么在其中包装的答案,要么表示没有任何值。在过去,碰见这种情况返回null很常见,但这样做会导致在未做完备测试的程序抛出空指针异常。Optional是一种表示缺少返回值的一种更好的方式。

        findFirst是查找非空集合中的第一个元素。它通常与filter配合使用才显得有用。例如,下面展示了如何找到第一个以Q开头的单词。前提是存在这样的单词:

Optional<String> startWithQ = words.filter(s -> s.startsWith("Q")).findFirst(); 

        如果不强调第一个匹配,而是使用任意匹配,那么使用findAny方法。这个方法在并行处理流方面很有效。

Optional<String> startWithQ = words.parallel()
                                   .filter(s -> s.startsWith("Q")).findFirst(); 

        如果只想知道,是否存在匹配,可以使用anyMatch.这个方法会接受一个断言引元,因此不需要使用filter。

Optional<String> startWithQ = words.parallel()
                                   .anyMatch(s -> s.startsWith("Q")); 

还有allMatch和noneMatch方法,他们分别在所有元素和没有任何元素匹配的情况下返回true。这些方法都可以在并行情况下获益。

3 Optional类型

        Optional<T>对象是一种包装器对象,要么包装了类型T的对象,要么没有包装任何对象。对于第一种情况,我们称为这种值是存在的。Optional<T>类型被当作一种更安全的方式,用来代替类型T的引用,这种引用要么引用某个对象,要么为null。但是,他只有正确使用的情况下才会更安全。

3.1 如何使用Optional值

        有效地使用optional的关键是要使用这样的方法:它的值不存在的情况下会产生一个可替代物,而只有在值存在的情况下才会使用这个值。

        通常,在没有任何匹配时,我们会希望使用某种默认值,可能是空字符串:

String result = OptionalString.orElse("");

可以调用代码来计算默认值

String result = optionalString.orElseGet(
                                () -> Locale.getDefault().displayName());

或者在没有任何值时抛出异常:

String result = optionString.orElseThrow(IllegalStateException::new);

上面是当optional中,不存在任何值时,就会产生一个替代物。另一条使用可选值的策略是只有其值存在的情况下才消费改值。

        ifPresent()方法会接受一个函数。如果该可选值存在,那么它会被传递给该函数。否则,不会发生任何事情。

optionalValue.ifPresent(v -> process V)

        例如,如果该值存在的情况下,想要将其添加到某个集中,那么就可以调用

optionalValue.ifPresent(v -> results.add(v));

         也可以这样调用:

optionalValue.ifPresent(results::add);

        当调用ifPresent时,从该函数不会返回任何值。如果想要处理函数的结果,应该使用map:

Optional<Boolean> added = optionalValue.map(results::add);

        现在added具有三种值之一:在optionalValue存在的情况下包装在Option中的true或false,以及optionvalue不存在的情况下的空Optional。

常用方法

  • T orElse(T other) 产生这个option的值,或者在optional为空的情况下,产生other。
  • T orElseGet(Suplier<? extends T > other) 产生这个Optional的值,或者在optional为空的情况下,产生other的结果。
  • <x extends Throwable>T orElseThrow(Suplier<? extends T > exceptionSuplier) 产生这个Optional的值,或者在optional为空的情况下,抛出调用exceptionSuplier的结果。
  • void ifPresent(Consumer<? super T> consumer)   如果optional的值不为空,就把值传递给consumer。
  • <U> Optional<U> map(Function<? super T, ? extends U> mapper) 产生将该Optional的值传递给mapper后的结果,只要这个optional不为空且结果不为null,否则会产生一个空的Optional对象。

3.2 不适合使用Optional值的方式

        如果没有正确的使用Optional值,那么相较以往的得到"某物或null"的方式,你并没有得到任何好处。

        get方法会在Optional值存在的情况下获得其中包装的元素,或在不存在的情况下抛出一个NoSuchElementException对象。因此,

Optional<T> optionalValue = ...;

optionalvalue.get().someMethod();

上面方法并不比下面的安全

T value = ....;

value.someMethod();

isPresent()方法会报告某个Optional<T> 对象是否具有一个值。但是

if(optionalValue.isPresent()){

    optionalValue.get().someMethod();
}

//并不比下面的方式更容易处理

if(value != null){
    value.someMethod();
}

常用方法

  • T get() 产生这个Optional的值,或者在该Optional为空时,抛出一个NoSuchElementException
  • boolean isPresent() 如果该Optional不为空,则返回true。

3.3 创建Optional值

        如果想要编写方法来创建Optional对象,那么有多个方法可以用于创建

public static Optional<Double> inverse(){

    return x == 0 ? Optional.empty() : Optional.of(1/x);

} 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值