java基础教程——Stream流

一、流的操作

  • 生成流的操作

通过数据源(集合、数组等)生成流

如,list.stream()

  • 中间操作

一个流后面可以跟随零个或多个中间操作,其目的主要是打开流,做出某种程度的数据过滤/映射,然后返回一个新的流,交给下一个操作使用

如,filter(),其操作完成之后还是一个stream流

  • 终结操作

一个流只能有一个终结操作,当这个操作执行后,流就被使用"光"了,无法再被操作。所以这必定是流的最后一个操作forEach()

forEach()

二、Stream流的生成方式

Stream流常见的生成方式有三种

  • Colletion体系的集合可以使用默认方法stream()生成流

default Stream <E> stream()

List<String> list = new ArrayList<>();
Stream<String> listStream = list.stream();

Set<String> set = new HashSet<>();
Stream<String> setStream = set.stream();

  • Map体系的集合间接的生成流

        Map<String,Integer> map = new HashMap<>();

//      这就是间接的获取键的stream流:map.keySet() 得到键的set集合,再通过键的set集合获取到流,
        Stream<String> keyStream = map.keySet().stream();

//      间接的获取值的stream流
        Stream<Integer> valueStream = map.values().stream();

//      键值对对象所对应的流
        Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();

  • 数组可以通过Stream接口的静态方法of(T...values)生成流

        String[] strArray = {"hello","world","java"};

        Stream<String> strArrayStream = Stream.of(strArray);

        Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");

        Stream<Integer> intStream = Stream.of(10, 20, 30);

三、Stream流常见中间操作方法

3.1 中间操作之filter(Predicate predicate)

  • Stream<T> filter(Predicate predicate):用于对流中的数据进行过滤

Predicate接口中的方法 boolean test(T t) : 对给定的参数进行判断,返回一个布尔值

需求:把list集合中以张开头的元素在控制台输出

        ArrayList<String> list = new ArrayList<>();
        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

//      需求:把list集合中以张开头的元素在控制台输出

//      filter()需要一个函数式接口,在这里我们可以写一个lambda表达式
        list.stream().filter( (String s) ->{
            return s.startsWith("张");
        } ).forEach(System.out::println);

其中我们的lambda表达式可以简写成下面的形式

list.stream().filter(s->s.startsWith("张")).forEach(System.out::println);

需求:把list集合中长度为3的元素在控制台输出

  list.stream().filter(s->s.length()==3).forEach(System.out::println);

需求: 把list集合中以张开头的,长度为3的元素在控制台输出

 list.stream()
     .filter(s->s.startsWith("张"))
     .filter(s->s.length()==3)
     .forEach(System.out::println);

3.2 中间操作之limit&skip

  • Stream<T> limit(long maxSize):返回流中的元素组成的流,截取前指定参数个数的数据

  • Stream<T> skip(long n): 跳过指定参数个数的数据,返回由该流的剩余元素组成的流

需求:取前3个数据在控制台输出

 list.stream()
     .limit(3)
     .forEach(System.out::println);

需求:跳过3个元素,把剩下的元素在控制台输出

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

需求:跳过2个元素,把剩下的元素中前两个在控制台输出

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

3.3 中间操作之concat&distinct()

  • static<T> Stream<T> concat(Stream a,Stream b):合并a和b两个流为一个流(静态方法)

  • Stream<T> distinct():返回由该流的不同元素(根据Object.equals(Object))组成的流

需求:取前四个数据组成一个流

 Stream<String> s1 = list.stream().limit(4);

需求:跳过2个数据组成一个流

Stream<String> s2 = list.stream().skip(2);

需求: 合并需求1和需求2得到的流,并把结果在控制台输出

Stream.concat(s1, s2).forEach(System.out::println);

需求: 合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复

 Stream.concat(s1,s2).distinct().forEach(System.out::println);

3.4 中间操作之sorted

  • Stream<T> sorted:返回由此流的元素组成的流,根据自然顺序排序

  • Stream<T> sorted(Compatator comparator):返回由该流的元素组成的流,根据提供的Comparator进行排序

需求:按照字母顺序把数据在控制台输出

        ArrayList<String> list = new ArrayList<>();
        list.add("linqingxia");
        list.add("zhangmanyu");
        list.add("wangzuxian");
        list.add("liuyan");
        list.add("zhangmin");
        list.add("zhangwuji");


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

需求:按照字符串长度把数据在控制台输出

       list.stream()
               .sorted((s1,s2)->{
                   int num = s1.length()-s2.length();
                   int num2 = num ==0 ? s1.compareTo(s2) : num;
                   return  num2;
               })
               .forEach(System.out::println);

3.5 中间操作之map&mapToInt

  • <R> Stream<R> map(Fucntion mapper):返回由给定函数应用于此流的元素的结果组成的流

Function接口中的方法 R apply(T t)

  • IntStream map ToInt(ToIntFuction mapper):返回一个IntStream其中包含将给定函数应用于此流的元素的结果

IntStream:表示原始int流

ToIntUFunction接口中的方法 int applyAsInt(T value)

需求: 将集合中的字符串数据转换为整数之后再控制台输出

        ArrayList<String> list = new ArrayList<>();

        list.add("10");
        list.add("20");
        list.add("30");
        list.add("40");
        list.add("50");
        list.stream().map(s->Integer.parseInt(s)).forEach(System.out::println);

或者

list.stream().map(Integer::parseInt).forEach(System.out::println);

或者 mapToInt也可以

 list.stream()
        .mapToInt(Integer::parseInt)
        .forEach(System.out::println);

结果:

IntStream也是一个接口,支持顺序和并行聚合操作的原始int值元素序列,其有个方法是 int sum() 返回流中元素的总和

注意:sum方法是IntStream接口中的,而Stream接口中是没有的

        int sum = list.stream().mapToInt(Integer::parseInt).sum();
        System.out.println(sum);

四、Stream流常见终结操作方法

  • void forEach(Consumer action):对此流的每个元素执行操作

Consumer接口中的方法 void accept(T t): 对给定的参数执行此操作

我们前面指定的就是再控制台输出我们的数据

  • long count():返回此流中元素数

需求:把集合中的元素在控制台输出

        ArrayList<String> list = new ArrayList<>();
        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

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

需求: 统计集合中有几个以张开头的元素,并把统计结果输出

        long count = list.stream().filter(s -> s.startsWith("张")).count();
        System.out.println(count);

五、Stream流的练习

public class Actor {
    private String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
        ArrayList<String> manList = new ArrayList<>();
        manList.add("周润发");
        manList.add("成龙");
        manList.add("刘德华");
        manList.add("吴京");
        manList.add("周星驰");
        manList.add("李连杰");


        ArrayList<String> womanList = new ArrayList<>();

        womanList.add("林心如");
        womanList.add("张曼玉");
        womanList.add("林青霞");
        womanList.add("柳岩");
        womanList.add("林志玲");
        womanList.add("王祖贤");

现在有两个ArrayList集合,分别存储6名男演员和6名女演员名称,要求完成如下的操作

  • 男演员只要名字为3个字的前三人

        Stream<String> manStream = manList.stream()
                                        .filter(s -> s.length() == 3)
                                        .limit(3);

  • 女演员只要姓林的,并且不要第一个

 Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);

  • 把过滤后的男演员姓名和女演员姓名合并到一起

Stream<String> stream = Stream.concat(manStream, womanStream);

  • 把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据

演员类Actor已经提供,里面有一个成员变量,一个带构造方法,以及成员变量对应的get/set方法

 stream.map(Actor::new).forEach(System.out::println);

我们没有重写toString方法

stream.map(Actor::new).forEach( p-> System.out.println(p.getName()));

六、Stream流的收集操作

对数据使用stream流的方式操作完毕后,想把流中的数据收集到集合中

Stream流的收集方法

  • R collect(Collector collector)

<R,A> R collect(Collector<? super T,A,R> collector)

其中Collector<? super T,A,R>是一个接口

Collectors是一个工具类,实现各种有用的还原操作的Collector,例如将元素累积到集合中,根据各种标准汇总元素等

工具类Collectors提供了具体的收集方式

  • public static <T> Collector toList(): 把元素收集到List集合中

        ArrayList<String> list = new ArrayList<>();
        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

//        需求1:得到名字为3个字的流
        Stream<String> listStream = list.stream().filter(s -> s.length() == 3);

//        需求2:把使用Stream流操作完毕的数据收集到List集合中并遍历
        List<String> names = listStream.collect(Collectors.toList());

        for(String name :names){
            System.out.println(name);
        }
    }

  • public static <T> Collector toSet(): 把元素收集到Set集合中

        Set<Integer> set = new HashSet<>();
        set.add(10);
        set.add(20);
        set.add(30);
        set.add(33);
        set.add(35);
//      需求: 大于25
        Stream<Integer> setStream = set.stream().filter(are -> are > 25);
//      需求:把使用Stream流操作完毕的数据收集到Set集合中并遍历
        Set<Integer> ages = setStream.collect(Collectors.toSet());
        for(Integer age :ages)
            System.out.println(age);

  • public static Collector toMap(Function keyMapper,Function valueMapper):把元素收集到Map集合中

       String[] strArray = {"林青霞,30","张曼玉,35","王祖贤,33","柳岩,25"};
//     需求:得到字符串中年龄数据大于28的流
        Stream<String> arrayStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);

//     需求:把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作为键,年龄作为值
        Map<String, Integer> map = arrayStream.collect(Collectors.toMap( s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1]) ) );

        Set<String> keySet = map.keySet();
        for(String key: keySet){
            System.out.println(key+","+map.get(key));
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我爱布朗熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值