Java(十四)

一、Stream流

1.1流式思想概述

注意:请暂时忘记对传统IO流的固有印象! 整体来看,流式思想类似于工厂车间的“生产流水线”。
当需要对多个元素进行操作(特别是多步操作)的时候,考虑到性能及便利性,我们应该首先拼好一个“模型”步骤 方案,然后再按照方案去执行它。
Stream(流)是一个来自数据源的元素队列 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。 数据源 流的来源。 可以是集合,数组 等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者增强for的方式, 显式的在集合外部进行迭代, 这叫做外部迭 代。 Stream提供了内部迭代的方式,流可以直接调用遍历方法。

1.2 Stream方法

Filter过滤

具体实现代码如下:

import org.w3c.dom.ls.LSOutput;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/*
    使用Stream流的方式,遍历集合,对集合中的数据进行过滤
    Stream流是JDK1.8之后出现的
    关注的是做什么,而不是怎么做
 */
public class Demo01Stream {
    public static void main(String[] args) {
        //创建一个List集合,存储姓名
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");

        //对List集合中的元素进行过滤,只要以张开头的元素,存储到一个新的集合中
        //遍历集合
        Stream<String> stream= list.stream()
                .filter(name->name.startsWith("张"))
                .filter(name -> name.length() == 3);
        stream.forEach(name -> System.out.println(name));

        /*
            Stream流属于管道流,只能被消费(使用)一次
            第一个Stream流调用完毕,数据就会流转到下一个Stream上
            而这时第一个Stream流已经使用完毕,就会关闭了
            所以第一个Stream流就不能再调用方法了
            IllegalStateException: stream has already been operated upon or closed
         */
        //遍历stream流
        //stream.forEach(name-> System.out.println(name));
    }
}

Map映射

如果需要将流中的元素映射到另一个流中,可以使用 map 方法。
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
该接口需要一个 Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
Function中的抽象方法:
    R apply(T t);

具体代码实现如下:

import java.util.stream.Stream;

/*
    如果需要将流中的元素映射到另一个流中,可以使用 map 方法。
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);
    该接口需要一个 Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
    Function中的抽象方法:
        R apply(T t);
 */
public class Demo02StreamMap {
    public static void main(String[] args) {
        //获取一个String类型的Stream流
        Stream<String> stream = Stream.of("1", "2","3", "4");
        //使用map方法,把字符串类型的整数,转换(映射)为Integer类型的整数
        Stream<Integer> map =  stream.map((String s)->{
            return Integer.parseInt(s);
        });
        //遍历Stream流
        map.forEach(i-> System.out.println(i));
    }
}

Count统计

Stream流中的常用方法:用于同济Stream流中元素的个数
long count();
count方法是一个终结方法,返回值是一个龙类型的整数
所以不能在继续调用Stream流中的其他方法了

具体代码实现如下:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/*
    Stream流中的常用方法:用于同济Stream流中元素的个数
    long count();
    count方法是一个终结方法,返回值是一个龙类型的整数
    所以不能在继续调用Stream流中的其他方法了
*/
public class Demo03StreamCount {
    public static void main(String[] args) {
        //获取一个Stream流
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        list.add(7);
        list.add(8);
        list.add(9);
        Stream<Integer> stream = list.stream();
        long count = stream.count();
        System.out.println(count);
    }
}

Concat 组合

Stream流中的常用方法,concat:用于把流组合到一起
如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口的静态方法 concat :
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)

具体代码实现如下:

import java.util.stream.Stream;

/*
    Stream流中的常用方法,concat:用于把流组合到一起
    如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口的静态方法 concat :
    static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
 */
public class StreamConcat {
    public static void main(String[] args) {
        //获取一个Stream流
        Stream<String> stream1 = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
        //获取一个Stream流
        String[] arr = {"aaa", "bbb", "ccc","ddd","eee"};
        Stream<String> stream2 = Stream.of(arr);
        //把以上两个流转为一个流
        Stream<String> concat = Stream.concat(stream1, stream2);
        //遍历concat流
        concat.forEach(name-> System.out.println(name));
    }
}

Limit 限定长度

limit 方法可以对流进行截取,只取用前n个。方法签名:
Stream<T> limit(long maxSize);
参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作。
limit方法是一个延迟方法,只是对流中的元素进行截取,返回的是一个新的流,所以可以继续调用Stream流中的其他方法

具体代码实现如下:

/*
    limit 方法可以对流进行截取,只取用前n个。方法签名:
    Stream<T> limit(long maxSize);
    参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作。
    limit方法是一个延迟方法,只是对流中的元素进行截取,返回的是一个新的流,所以可以继续调用Stream流中的其他方法
 */

import java.util.stream.Stream;

public class StreamLimit {
    public static void main(String[] args) {
        //获取一个Stream流
        String[] arr = {"aaa", "bbb", "ccc"};
        Stream<String> stream = Stream.of(arr);
        //使用limit对Stream流中的元素进行截取,只要前三个元素
        Stream<String> stream2 = stream.limit(3);
        //遍历stream流
        stream2.forEach(name-> System.out.println(name));
    }
}

Skip跳过

Stream<T> skip(long n);
    如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。

具体实现代码如下:

import java.util.stream.Stream;

/*
    Stream<T> skip(long n);
        如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。
 */
public class StreamSkip {
    public static void main(String[] args) {
        //获取一个Stream流
        String[] arr = {"aaa", "bbb", "ccc","ddd","eee"};
        Stream<String> stream = Stream.of(arr);
        //使用skip方法跳过前三个元素
        Stream<String> stream1 = stream.skip(3);
        //遍历stream2流
        stream1.forEach(name -> System.out.println(name));
    }
}

1.3 Stream流的综合应用

先有一道题目:
现在有两个 ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以 下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
5. 将两个队伍合并为一个队伍;存储到一个新集合中。
6. 根据姓名创建 Person 对象;存储到一个新集合中。
7. 打印整个队伍的Person对象信息。

需要通过Stream流来实现:

具体代码实现如下:

1.定义Person类

public class Person {
    private String name;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

2.测试主体类具体实现

import java.util.ArrayList;
import java.util.stream.Stream;

/*
    现在有两个 ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以 下若干操作步骤:
    1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
    2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
    3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
    4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
    5. 将两个队伍合并为一个队伍;存储到一个新集合中。
    6. 根据姓名创建 Person 对象;存储到一个新集合中。
    7. 打印整个队伍的Person对象信息。
 */
public class Demo01StreamTest {
    public static void main(String[] args) {
        //第一支队伍
        ArrayList<String> one = new ArrayList<>();
        one.add("迪丽热巴");
        one.add("宋远桥");
        one.add("苏星河");
        one.add("石破天");
        one.add("石中玉");
        one.add("老子");
        one.add("庄子");
        one.add("洪七公");
        //1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
        //2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
        Stream<String> stream = one.stream().filter(name->name.length() == 3).limit(3);

        //第二支队伍
        ArrayList<String> two = new ArrayList<>();
        two.add("古力娜扎");
        two.add("张无忌");
        two.add("赵丽颖");
        two.add("张三丰");
        two.add("尼古拉斯赵四");
        two.add("张天爱");
        two.add("张二狗");

        //3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
        //4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
        Stream<String> stream1 = two.stream().filter(name->name.startsWith("张")).skip(2);
        //5. 将两个队伍合并为一个队伍;存储到一个新集合中。
        Stream<String> newStream = Stream.concat(stream, stream1);
        //6. 根据姓名创建 Person 对象;存储到一个新集合中。
        Stream<Person> personStream = newStream.map((String name)->{
            return new Person(name);
        });
        //7. 打印整个队伍的Person对象信息。
       personStream.forEach(person -> System.out.println(person));
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值