Stream流

Stream流介绍

JDK1.8的新特性之一
它跟我们所学的 IO 流完全没有什么关系
Stream 它是Lambda的衍生物。

传统方式遍历的问题

需求:我们先找出性张的,再性张的中找出三个字的,然后遍历集合

public class Test {
    public static void main(String[] args) {

        ArrayList<String> list = new ArrayList();
        //给集合添加元素
        Collections.addAll(list,"张无忌","张三","王二","张三明","马六");

        //先找姓张的
        ArrayList<String> zhangList = new ArrayList<>();
        for (String s : list) {
            if(s.startsWith("张")){
                zhangList.add(s);
            }
        }

        //在找三个字的
        ArrayList<String> threeList = new ArrayList<>();
        for (String s : zhangList){
            if (s.length() == 3){
                threeList.add(s);
            }
        }

        //遍历集合
        for (String s : threeList){
            System.out.println(s);
        }
    }
}


结果:
	张无忌
	张三明

这样写显然我们要进行三次遍历,不但代码多,而且还很浪费功夫,还容易写错。

JDK1.8的新特性中就指明了流的思想,下面让我们看看使用Stream之后的代码吧。

		ArrayList<String> list = new ArrayList();
        //给集合添加元素
        Collections.addAll(list,"张无忌","张三","王二","张三明","马六");

		//使用Stream流
		list.stream().filter(s->s.startsWith("张"))
				.filter(s->s.length() == 3).forEach(s-> System.out.println(s));


结果:
	张无忌
	张三明

可以看到两个例子的结果完全一致,流的使用简化了很多的代码。
我相信正在读文章的你也很好奇,那么久让我们先看一下流是怎样做到这一点的吧。

使用Stream流解决

我们可以发现,stream流的方法中都有一个参数,而且该参数都是一个接口并且该接口中只有一个抽象方法,我相信看过我上篇Lambda表达式的小伙伴都应该知道,这是符合Lambda表达式的使用条件的,那么就让我们来简化一下吧。

		//流的原始方式写法
		list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("张");
            }
        }).filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.length() == 3;
            }
        }).forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });

		
		//流与Lambda表达式结合使用,简化后的代码如下:
		list.stream().filter(s->s.startsWith("张"))
				.filter(s->s.length() == 3).forEach(s-> System.out.println(s));

从这里可以看到,流的引入给我们带来了很大的便利,下面就让我们充分的认识一下它吧!

获取流的方式

java.util.stream.Stream 是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)
获取一个流非常简单,有以下几种常用的方式:

Collection 集合及其子类都可以通过 .stream() 获取流。
Stream接口的静态方法 .of 可以获取数组对应的流。

		//通过单列集合获取流
		ArrayList<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();

		//通过Stream接口的静态方法也可以获取流
		String[] arr = {"a","b","c"};
        Stream<String> Stream1 = Stream.of(arr);

		//map方式获取流	基本用不到
        HashMap<String, String> map = new HashMap<>();
        Stream<String> s1 = map.keySet().stream();
        Stream<String> s2 = map.values().stream();
        Stream<Map.Entry<String, String>> s3 = map.entrySet().stream();

常用方法

流模型的操作很丰富,这里介绍一些常用的API。这些方法可以被分成两种:

  • 终结方法:返回值类型不再是 Stream 接口自身类型的方法,因此不再支持类似 StringBuilder 那样链式调用。本次介绍的终结方法包括 count 和 forEach 方法。
  • 非终结方法:返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为非终结方法。)

方法介绍:
终结方法:不支持链式调用

  • count : 统计个数(终结方法,不支持链式调用)
  • forEach :逐一处理,遍历的意思(终结方法,不支持链式调用)

其他方法(非终结方法):除了终结方法,其他方法都支持链式调用

  • filter : 过滤
  • limit : 取前几个
  • skip : 跳过前几个
  • map : 映射
  • static concat : 组合,拼接(只能通过Stream接口调用)
  • static of : 获取数组对应的流(只能通过Stream接口调用)
  • collect(Collectors接口) : 把流转换成指定的集合
  • toArray : 转化成数组

filter与forEach使用

public class Work5 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        Collections.addAll(list,"王佳乐","张三丰","王思聪","张飞","刘晓敏","张靓颖","王敏");

		//获取流
        Stream<String> stream = list.stream();
        
         //注意:因为已经调用了终结方法,后面就不能使用这个流进行操作了,因为该流已经不存在了,要想操作还需要再次创建新的流
        stream.filter(s->s.startsWith("张")).forEach(s-> System.out.println(s));
        
        //流对象已经消失,该语句会报错的
        stream.filter(s -> s.startsWith("王")).forEach(s-> System.out.println(s));
     }
}

结果:
注意:因为已经调用了终结方法,后面就不能使用这个流进行操作了,因为该流已经不存在了,要想操作还需要再次创建新的流
在这里插入图片描述

count使用

public class Test1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张三");

        //count是终结方法,调用后此流就不能在使用,不然会报异常,要想使用需要新创建一个流
        long count = list.stream().count();

        System.out.println(count);

    }
}

结果:
	2

limit使用

public class Work5 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        //给集合添加元素
        Collections.addAll(list,"王佳乐","张三丰","王思聪","张飞","刘晓敏","张靓颖","王敏");

        //获取流
        Stream<String> stream = list.stream();

        //调用方法 使用limit获取集合前三个并打印
        stream.limit(3).forEach(s-> System.out.println(s));
    }
}


结果:
	王佳乐
	张三丰
	王思聪

skip使用

public class Work5 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        //给集合添加元素
        Collections.addAll(list,"王佳乐","张三丰","王思聪","张飞","刘晓敏","张靓颖","王敏");

        //获取流
        Stream<String> stream = list.stream();

        //调用方法 使用skip跳过集合中前三个元素并打印
        stream.skip(3).forEach(s-> System.out.println(s));
    }
}

结果:
	张飞
	刘晓敏
	张靓颖
	王敏

map使用

//Person类
public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

//测试类
public class Work6 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        Collections.addAll(list,"王佳乐","张三丰","王思聪","张飞");

        //把集合中的元素映射到Person对象中并打印
        list.stream().map(Person::new).forEach(s-> System.out.println(s));

    }
}

结果:
	Person{name='王佳乐'}
	Person{name='张三丰'}
	Person{name='王思聪'}
	Person{name='张飞'}

collect(Collectors接口)使用

Collectors接口下的方法:
toList 、 toSet 等等

//Person类
public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

//测试类
public class Work6 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        Collections.addAll(list,"王佳乐","张三丰","王思聪","张飞");

        //把集合元素映射到Person对象中,并且把流转换成list集合
        List<Person> collect = list.stream().map(Person::new).collect(Collectors.toList());

        //打印list集合
        System.out.println(collect);
    }
}

结果:
	[Person{name='王佳乐'}, Person{name='张三丰'}, Person{name='王思聪'}, Person{name='张飞'}]


toArray使用

public class Test1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张三");
        list.add("王二");
        list.add("马六");
        list.add("马腾飞");

        //获取流,找出姓张的,然后把流转换成数组
        Object[] arr = list.stream().filter(s -> s.startsWith("张")).toArray();

        System.out.println(Arrays.toString(arr));
    }
}

结果:
	[张无忌, 张三]

concat使用

注意:concat是静态方法,要使用Stream接口来调用

public class Test1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张三");
        
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("王二");
        list1.add("马六");
        list1.add("马腾飞");

        //获取两个集合的流对象
        Stream<String> stream = list.stream();
        Stream<String> stream1 = list1.stream();

        //调用 静态的concat方法
        Stream<String> concat = Stream.concat(stream, stream1);
        
        //打印 concat流
        concat.forEach(s-> System.out.println(s));
        
    }
}


结果:
	张无忌
	张三
	王二
	马六
	马腾飞

of使用

注意:of是静态方法,要使用Stream接口来调用

		//通过Stream接口的静态方法也可以获取流
		String[] arr = {"a","b","c"};
        Stream<String> stream = Stream.of(arr);

如果能够帮到你,就留下一个赞吧!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值