Optional<T> max(Comparator<? super T> comparator)

这个方法看字面上的意思就是取流中最大的元素返回。但是这个最大不是通常意义上简单数据比较的那个最大,而是通过自定义的比较函数得到的计算结果。看例子:

void stream_max() {

        List<String> list = List.of("Mr.zhangsan","Mr.lisi","Mr.wanger","Mr.mazi");

        String str = list.stream().max((a,b) -> a.length()-b.length()).get();

        System.out.println(str);

    }

运行结果:

Mr.zhangsan

这个例子取的最大是指集合中字符串长度最长的那个元素。如果我们把比较方法简单修改一下,修改如下:

(a,b) -> b.length()-a.length()

运行结果就是:Mr.lisi

那这里的最大其实就是取字符串长度最小的元素,所以max方法不可以简单理解为取最大元素,主要还是看你怎么定义比较方法。

 

另外,需要指出如果流中存在好几个同时满足比较方法的元素那就取第一个。如上面例子,满足比较函数的元素有

"Mr.lisi"和"Mr.mazi"两个字符串,实际返回结果是“Mr.lisi”。需要再说明一下,并行流不能保证这个顺序返回元素。

 

这个方法还有两个不正式的用法,先看例子:

String str2 = list.stream().max((a,b) -> 1).get();

        System.out.println(str2);

        String str21 = list.stream().max((a,b) -> 0).get();

        System.out.println(str21);

        String str22 = list.stream().max((a,b) -> -1).get();

        System.out.println(str22);

运行结果:

Mr.zhangsan

Mr.zhangsan

Mr.mazi

 

如果我们要取流中第一个元素,那么就强制定义比较函数返回结果为1或0,如果要取最后一个元素那就定义返回值为-1。为什么会这样呢,因为比较过程是这样:

  1. 取第一个元素给a,第二个元素给b,然后传入比较函数进行比较
  2. 比较结果为1或0就把a作为中间计算结果保存起来,跳到第4步
  3. 比较结果为-1,那就把b作为中间计算结果保存起来,跳到第4步
  4. 把中间计算结果给a,然后取流中下个元素给b,再把这两参数传入比较函数进行比较,根据比较结果选择跳到第2步还是第3步。
  5. 遍历完流中全部元素,把最后的中间结果放到Optional中返回。

 

根据上面处理流程,如果强制定义比较结果为1或0,那么第一个元素会永远保留在中间结果中直至最后返回,所以其作用就像是取第一个元素,同样如果强制定义比较结果为-1,那一直会把b放入中间结果中,当循环到最后一个元素给b的时候,就把最后一个元素当作最终结果返回,作用就像是直接取流中最后一个元素返回一样。