java stream学习

Stream学习

Stream流式操作方便我们对集合进行操作,使用过程中有几个点需要注意,本人踩过坑。首先理解中间操作和最终操作,中间操作是惰性加载的,只有到达最终操作时,才会执行中间操作的代码。

用实例来学习stream的用法,这里有一个Boy和一个Girl类,其中Boy类有girlFriends,nickname等属性,这些下面会用到。

public class Boy {
    private String name;
    private List<String> nickName;
    private int age;
    private List<Girl> girlFriends;

    public Boy(String name, List<String> nickName, int age, List<Girl> girlFriends) {
        this.name = name;
        this.nickName = nickName;
        this.age = age;
        this.girlFriends = girlFriends;
    }
}
public class Girl {
    private String name;
    private int age;

    public Girl(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class StreamTest {

    Boy jiabaoyu;
    Boy tangseng;
    List<Girl> jiabaoyuGirls;
    List<Girl> tangsengGirls;

    @Before
    public void init() {
        jiabaoyuGirls = new ArrayList<>();
        Girl daiyu = new Girl("林黛玉", 17);
        Girl baochai = new Girl("薛宝钗", 18);
        Girl xiangyun = new Girl("史湘云", 16);
        jiabaoyuGirls.add(daiyu);
        jiabaoyuGirls.add(baochai);
        jiabaoyuGirls.add(xiangyun);

        jiabaoyu = new Boy("贾宝玉", Arrays.asList("混世魔王","通灵宝玉"), 17, jiabaoyuGirls);

        tangsengGirls = new ArrayList<>();
        Girl zhizhjing = new Girl("蜘蛛精", 17);
        Girl laoshujing = new Girl("老鼠精", 18);
        Girl kongquejing = new Girl("孔雀精", 16);
        tangsengGirls.add(zhizhjing);
        tangsengGirls.add(laoshujing);
        tangsengGirls.add(kongquejing);

        tangseng = new Boy("唐僧", Arrays.asList("老和尚"), 17, tangsengGirls);
    }
}

为了理解所谓的惰性,我们用forEach和stream做对比。对集合属性修改的时候,forEach能够马上得到结果,但stream在中间操作时,是不会执行具体逻辑的,只有到最终操作时,才执行。

/**
 * 简单的遍历方式
 */
@Test
public void testForeach() {
    jiabaoyu.getGirlFriends().forEach(girl -> girl.setAge(100));
    System.out.println(jiabaoyu); // 修改成功
}
/**
 * Stream是惰性加载的,当Stream在中间操作时,不执行具体逻辑,只有处于最终操作时,才执行相关代码
 */
@Test
public void testStream() {
    Stream<Girl> peek = jiabaoyu.getGirlFriends().stream().peek(girl -> girl.setAge(100));
    System.out.println(jiabaoyu); // 没有修改成功
    Stream<Girl> distinct = peek.distinct();
    System.out.println(jiabaoyu); // 没有修改成功
    distinct.count();
    System.out.println(jiabaoyu); // 修改成功
}

map操作返回一个集合,注意它是有返回值的,要得到最终的集合,还需要执行collect方法收集。

/**
 * map操作有返回值
 * 使用collect可以返回一个新的list集合
 */
@Test
public void testMap() {
    jiabaoyu.setNickName(jiabaoyu.getNickName().stream().map(name -> name + "-贾宝玉").collect(Collectors.toList()));
    System.out.println(jiabaoyu); // 修改成功
}

flatMap可以将嵌套的list合并为一个list,如List[List[1,2,3],List[4,5,6]] -> 1,2,3,4,5,6

/**
 * 通过flatMap我们可以提取到一个list中
 */
@Test
public void testFlatMap() {
    List<Boy> boys = new ArrayList<>();
    boys.add(jiabaoyu);
    boys.add(tangseng);
    List<Girl> allGirlFriends = boys.stream().flatMap(boy -> boy.getGirlFriends().stream()).collect(Collectors.toList());
    System.out.println(allGirlFriends);
}

peek操作无返回值,常用来做日志输出

/**
 * peek操作无返回值
 * 主要用于debug,比如可以输出流式处理中间的执行结果
 */
@Test
public void testPeek() {
    jiabaoyu.setNickName(jiabaoyu.getNickName().stream().peek(name -> name = name + "-贾宝玉").collect(Collectors.toList()));
    System.out.println(jiabaoyu); // 没有修改,因为peek没有返回值
    jiabaoyu.getGirlFriends().stream()
            .filter(girl -> girl.getAge() > 17)
            .peek(girl -> System.out.println("处理后的结果" + girl))
            .collect(Collectors.toList());
}
  • reduce操作用于把元素组合起来得到结果
/**
 * reduce把集合元素组合起来
 */
@Test
public void testReduce() {
    System.out.println(Stream.of("A","B","C","D").reduce("拼接结果:", String::concat));
}

总结

介绍了几种常用的stream操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值