Java中的Stream流

一、案例引入

案例需求:

  • 创建一个集合,存储多个姓名字符串元素;
  • 把集合中所有以“张”开头的元素存储到一个新的集合;
  • 把上述集合中长度为3的元素存储到一个新的集合;
  • 遍历后打印上一步得到的集合

传统方法:

public class StreamDemo {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

        //把集合中所有以"张"开头的元素存储到一个新的集合
        ArrayList<String> zhangList = new ArrayList<String>();

        for(String s : list) {
            if(s.startsWith("张")) {
                zhangList.add(s);
            }
        }

//        System.out.println(zhangList);

        //把"张"开头的集合中的长度为3的元素存储到一个新的集合
        ArrayList<String> threeList = new ArrayList<String>();

        for(String s : zhangList) {
            if(s.length() == 3) {
                threeList.add(s);
            }
        }

//        System.out.println(threeList);

        //遍历上一步得到的集合
        for(String s : threeList) {
            System.out.println(s);
        }
    }
}

Stream改进后:

public class StreamDemo {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

        //Stream流来改进
        list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
    }
}

二、Stream流概述

(一)Stream流思想

(二)Stream流的三类方法

1、获取Stream流

创建一条流水线,把数据放到流水线上准备对其进行操作

2、中间方法

流水线上对数据进行操作,一次操作完后还可以继续对其进行操作

3、终结方法

一系列中间方法操作完成后的最后一个操作,一个Stream流只能有一个终结方法

三、Stream流的生成

1、Collection体系集合

使用默认方法stream()生成流:default Stream<E> stream()

2、Map体系集合

把Map转成Set集合,间接生成流

3、数组

通过Arrays中的静态方法stream生成流

4、同种数据类型的多个数据

通过Stream接口的静态方法of(T…values)

示例:

public class StreamDemo {
    public static void main(String[] args) {
        //Collection体系的集合可以使用默认方法stream()生成流
        List<String> list = new ArrayList<String>();
        Stream<String> listStream = list.stream();

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

        //Map体系的集合间接的生成流
        Map<String,Integer> map = new HashMap<String, Integer>();
        Stream<String> keyStream = map.keySet().stream();
        Stream<Integer> valueStream = map.values().stream();
        Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();

        //数组可以通过Arrays中的静态方法stream生成流
        String[] strArray = {"hello","world","java"};
        Stream<String> strArrayStream = Arrays.stream(strArray);
      
      	//同种数据类型的多个数据可以通过Stream接口的静态方法of(T... values)生成流
        Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
        Stream<Integer> intStream = Stream.of(10, 20, 30);
    }
}

四、Stream流中间操作方法

中间操作代表执行该操作后依然可以继续执行其他操作。

常见方法

方法名说明
Stream<T> filter(Predicate predicate)用于对流中的数据进行过滤
Stream<T> limit(long maxSize)返回此流中的元素组成的流,截取前指定参数个数的数据
Stream<T> skip(long n)跳过指定参数个数的数据,返回由该流的剩余元素组成的流
static <T> Stream<T> concat(Stream a, Stream b)合并a和b两个流为一个流
Stream<T> distinct()返回由该流的不同元素(根据Object.equals(Object) )组成的流

filter示例:

//需求1:把list集合中以张开头的元素在控制台输出
        list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);

//需求2:把list集合中长度为3的元素在控制台输出
        list.stream().filter(s -> s.length() == 3).forEach(System.out::println);

//需求3:把list集合中以张开头的,长度为3的元素在控制台输出
        list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);

limit&skip示例:

//需求1:取前3个数据在控制台输出
        list.stream().limit(3).forEach(System.out::println);
        System.out.println("--------");

//需求2:跳过3个元素,把剩下的元素在控制台输出
        list.stream().skip(3).forEach(System.out::println);
        System.out.println("--------");

//需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
        list.stream().skip(2).limit(2).forEach(System.out::println);

concat&distinct示例:

//需求1:取前4个数据组成一个流
        Stream<String> s1 = list.stream().limit(4);

//需求2:跳过2个数据组成一个流
        Stream<String> s2 = list.stream().skip(2);

//需求3:合并需求1和需求2得到的流,并把结果在控制台输出
        Stream.concat(s1,s2).forEach(System.out::println);

//需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
        Stream.concat(s1,s2).distinct().forEach(System.out::println);

五、Stream流终结操作方法

执行完此方法之后,Stream流将不能再执行其他操作。

常见方法

方法名说明
void forEach(Consumer action)对此流的每个元素执行操作
long count()返回此流中的元素数

示例:

//需求1:把集合中的元素在控制台输出
        list.stream().forEach(System.out::println);

//需求2:统计集合中有几个以张开头的元素,并把统计结果在控制台输出
        long count = list.stream().filter(s -> s.startsWith("张")).count();
        System.out.println(count);

六、Stream流的收集操作

对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中。

1、常用方法

方法名说明
R collect(Collector collector)把结果收集到集合中

2、工具类Collectors提供的具体收集方法

方法名说明
public static <T> Collector toList()把元素收集到List集合中
public static <T> Collector toSet()把元素收集到Set集合中
public static Collector toMap(Function keyMapper,Function valueMapper)把元素收集到Map集合中

Collector toList示例:

//需求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);
}

Collector toSet示例:

//需求3:得到年龄大于25的流
        Stream<Integer> setStream = set.stream().filter(age -> age > 25);

//需求4:把使用Stream流操作完毕的数据收集到Set集合中并遍历
        Set<Integer> ages = setStream.collect(Collectors.toSet());
        for(Integer age : ages) {
            System.out.println(age);
        }

Collector toMap示例:

//需求5:得到字符串中年龄数据大于28的流
        Stream<String> arrayStream = Stream.of(strArray).filter(s -> 
        Integer.parseInt(s.split(",")[1]) > 28);

//需求6:把使用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) {
            Integer value = map.get(key);
            System.out.println(key + "," + value);
        }

七、总结

1、Stream基于函数式编程思想,使用 Stream 流可以让开发者以一种更简洁、更易读的方式表达数据处理的逻辑,对一个整数集合进行过滤、映射和求和操作;传统的方式可能需要使用多个循环和中间变量,而使用 Stream 流可以在一条语句中完成。

2、中间操作会返回一个新的 Stream 流,允许进行链式操作。

3、Stream 流可以很方便地实现并行处理,以充分利用多核处理器的优势,提高程序的执行效率。

4、传统的集合遍历通常使用for循环或者迭代器,而 Stream 流提供了更简洁的forEach方法来遍历集合。

5、通过mapflatMap等操作可以方便地对集合中的元素进行转换。通过reducecollect等操作可以实现数据的聚合。例如使用collect方法将流中的元素收集到一个新的集合中。

JavaStreamJava8引入的一个新特性,用于处理集合和数组等数据源的元素。它是一种函数式编程风格的API,可以通过链式调用一系列的操作来实现对数据源的处理,包括过滤、映射、排序、聚合等操作。 Stream分为间操作和终止操作两种类型。间操作是指对数据源进行的转换操作,每次间操作都会返回一个新的Stream对象,可以链式调用多个间操作。终止操作是指对数据源进行的最终操作,会返回一个非Stream类型的结果,例如forEach、count、collect等。 以下是一个简单的示例,演示如何使用Stream对一个整数列表进行过滤、映射和统计操作: ```java List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // 过滤出偶数 List<Integer> evenNumbers = numbers.stream() .filter(n -> n % 2 == 0) .collect(Collectors.toList()); // 将偶数加倍 List<Integer> doubledNumbers = evenNumbers.stream() .map(n -> n * 2) .collect(Collectors.toList()); // 统计偶数的个数 long count = evenNumbers.stream().count(); ``` 在上面的示例,我们首先创建了一个整数列表numbers,然后使用stream()方法将其转换为一个Stream对象。接着使用filter()方法过滤出偶数,并使用collect()方法将结果转换为一个List对象。然后使用map()方法将偶数加倍,并再次使用collect()方法将结果转换为一个List对象。最后使用count()方法统计偶数的个数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值