【Java8新特性】Stream API有哪些中间操作?看完你也可以吊打面试官!!

Stream filter(Predicate<? super T> predicate);

可以看到,在filter()方法中,需要传递Predicate接口的对象,Predicate接口又是个什么鬼呢?点进去看下源码。

@FunctionalInterface

public interface Predicate {

boolean test(T t);

default Predicate and(Predicate<? super T> other) {

Objects.requireNonNull(other);

return (t) -> test(t) && other.test(t);

}

default Predicate negate() {

return (t) -> !test(t);

}

default Predicate or(Predicate<? super T> other) {

Objects.requireNonNull(other);

return (t) -> test(t) || other.test(t);

}

static Predicate isEqual(Object targetRef) {

return (null == targetRef)

? Objects::isNull
object -> targetRef.equals(object);

}

}

可以看到,Predicate是一个函数式接口,其中接口中定义的主要方法为test()方法,test()方法会接收一个泛型对象t,返回一个boolean类型的数据。

看到这里,相信大家明白了:filter()方法是根据Predicate接口的test()方法的返回结果来过滤数据的,如果test()方法的返回结果为true,符合规则;如果test()方法的返回结果为false,则不符合规则。

这里,我们可以使用下面的示例来简单的说明filter()方法的使用方式。

//内部迭代:在此过程中没有进行过迭代,由Stream api进行迭代

//中间操作:不会执行任何操作

Stream stream = list.stream().filter((e) -> {

System.out.println(“Stream API 中间操作”);

return e.getAge() > 30;

});

我们,在执行终止语句之后,一边迭代,一边打印,而我们并没有去迭代上面集合,其实这是内部迭代,由Stream API 完成。

下面我们来看看外部迭代,也就是我们人为得迭代。

//外部迭代

Iterator it = list.iterator();

while (it.hasNext()) {

System.out.println(it.next());

}

2.limit()方法

主要作用为:截断流,使其元素不超过给定数量。

先来看limit方法的定义,如下所示。

Stream limit(long maxSize);

limit()方法在Stream接口中的定义比较简单,只需要传入一个long类型的数字即可。

我们可以按照如下所示的代码来使用limit()方法。

//过滤之后取2个值

list.stream().filter((e) -> e.getAge() >30 ).limit(2).forEach(System.out :: println);

在这里,我们可以配合其他得中间操作,并截断流,使我们可以取得相应个数得元素。而且在上面计算中,只要发现有2条符合条件得元素,则不会继续往下迭代数据,可以提高效率。

3.skip()方法

跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素 不足 n 个,则返回一个空流。与 limit(n) 互补。

源码定义如下所示。

Stream skip(long n);

源码定义比较简单,同样只需要传入一个long类型的数字即可。其含义是跳过n个元素。

简单示例如下所示。

//跳过前2个值

list.stream().skip(2).forEach(System.out :: println);

4.distinct()方法

筛选,通过流所生成元素的 hashCode() 和 equals() 去 除重复元素。

源码定义如下所示。

Stream distinct();

旨在对流中的元素进行去重。

我们可以如下面的方式来使用disinct()方法。

list.stream().distinct().forEach(System.out :: println);

这里有一个需要注意的地方:distinct 需要实体中重写hashCode()和 equals()方法才可以使用。

映射


关于映射相关的方法如下表所示。

| 方法 | 描述 |

| — | — |

| map(Function f) | 接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。 |

| mapToDouble(ToDoubleFunction f) | 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 DoubleStream。 |

| mapToInt(ToIntFunction f) | 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 IntStream。 |

| mapToLong(ToLongFunction f) | 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 LongStream |

| flatMap(Function f) | 接收一个函数作为参数,将流中的每个值都换成另 一个流,然后把所有流连接成一个流 |

1.map()方法

接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。

先来看Java8中Stream接口对于map()方法的声明,如下所示。

Stream map(Function<? super T, ? extends R> mapper);

我们可以按照如下方式使用map()方法。

//将流中每一个元素都映射到map的函数中,每个元素执行这个函数,再返回

List list = Arrays.asList(“aaa”, “bbb”, “ccc”, “ddd”);

list.stream().map((e) -> e.toUpperCase()).forEach(System.out::printf);

//获取Person中的每一个人得名字name,再返回一个集合

List names = this.list.stream().map(Person :: getName).collect(Collectors.toList());

2.flatMap()

接收一个函数作为参数,将流中的每个值都换成另 一个流,然后把所有流连接成一个流。

先来看Java8中Stream接口对于flatMap()方法的声明,如下所示。

Stream flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

我们可以使用如下方式使用flatMap()方法,为了便于大家理解,这里,我就贴出了测试flatMap()方法的所有代码。

/**

  • flatMap —— 接收一个函数作为参数,将流中的每个值都换成一个流,然后把所有流连接成一个流

*/

@Test

public void testFlatMap () {

StreamAPI_Test s = new StreamAPI_Test();

List list = Arrays.asList(“aaa”, “bbb”, “ccc”, “ddd”);

list.stream().flatMap((e) -> s.filterCharacter(e)).forEach(System.out::println);

//如果使用map则需要这样写

list.stream().map((e) -> s.filterCharacter(e)).forEach((e) -> {

e.forEach(System.out::println);

});

}

/**

  • 将一个字符串转换为流

*/

public Stream filterCharacter(String str){

List list = new ArrayList<>();

for (Character ch : str.toCharArray()) {

list.add(ch);

}

return list.stream();

}

其实map方法就相当于Collaction的add方法,如果add的是个集合得话就会变成二维数组,而flatMap 的话就相当于Collaction的addAll方法,参数如果是集合得话,只是将2个集合合并,而不是变成二维数组。

排序


关于排序相关的方法如下表所示。

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-LHlYl2LK-1715139753168)]

[外链图片转存中…(img-1Xp0IjGf-1715139753169)]

[外链图片转存中…(img-8wUE7yfC-1715139753169)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 30
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值