集合补充---Stream流式编程

一、Stream 核心概念

Stream流可以认为是省事的遍历集合或者其他的包装类,我们可以通过一些方法或者手段获得某个集合的Stream实例对象,然后就可以使用这个对象自带的方法去完成各种各样的操作了;

其实逻辑并不难;

那问题是什么样的对象可以通过手段得到Stream流对象呢?

图片来源黑马程序员

我们要想使用Stream流的功能,首先就必须先得到Stream流对象,由上诉的表格可以得知,通常情况下,单列集合,数组,和一些类型相同的零散数据可以直接通过各自的手段得到相应的Stream流对象,至于双列集合必须先得到其相应的键值对或者键的Set集合才能得到相应的Stream流对象;

具体的创建流的方式,只要一看代码案例就完全明白了,逻辑比较清晰明了;


二、Stream 操作类型

1. 创建流

主要四类,分别展示相应的创建流的方式

1.1 单列集合

很简单,单列集合有特定的方法直接获得相应的Stream流

List<String> arrayList = new ArrayList<>();
arrayList.add("Java");
arrayList.add("Python");

//直接调用方法获得相应的Stream流,很简单
Stream<String> stream1 = list.stream();

1.2 双列集合

HashMap<String, Integer> hm = new HashMap<>();
hm.put("aaa", 111);
hm.put("bbb", 222);
hm.put("ccc", 333);
hm.put("ddd", 444);


//逻辑依旧清晰明了
Stream<String> stream1 =hm.keySet().stream();

1.3 数组

数组的逻辑稍微有些不同,主要体现在,他要想得到Stream流对象,必须通过数组的静态方法,并不像集合那样有相应的方法直接获取

int[] arr1 = {1,2,3,4,5,6,7,8,9,10};
String[] arr2 = {"a","b","c"};

//其实。逻辑也很清晰,没啥记住就行了
Stream<String> stream1=Arrays.stream(arr1);

Stream<String> stream2=Arrays.stream(arr2);

1.4 同类型的数据

这个也有些不同,直接上代码,一看便知

调用的是Stream自己的方法创建得到的

Stream<String> stream1=Stream.of(1,2,3,4,5);

Stream<String> stream2=Stream.of(“a”, “b”, “c”, “d”, “e”);

2. 流的方法(核心)

创建流肯定是为了使用流的方法;

而Stream流的方法主要分为两大类,通过下面的代码和名字估计就能猜出他们的区别:

具体的请看以下代码案例自行体会;

2.1 中间操作

    • filter():会对Stream流中的数据进行过滤和筛选,返回过滤之后的Stream流;
    • map():转换元素
    • distinct():去重操作,依赖HashCode方法和equals方法
    • limit():获取前几个数据
    • skip():跳过几个数据后再获取后面全部的数据
    • concat():这是Stream类的静态方法,和其他方法有一定区别;合并俩流,最好保证俩流的数据类型是一样的
//准备集合
List<String> words = new ArrayList<>();
words.add("apple");
words.add("banana");
words.add("cherry");
words.add("date");

//Stream流的链式编程成为它的特征和标配
// 过滤操作
words.stream().filter(s -> s.length() > 5).forEach(s->System.out.println(s);
// banana,cherry

// 获取操作
words.stream().limit(2).forEach(s->System.out.println(s); // apple, banana

// 跳获取操作
words.stream().skip(2).forEach(s->System.out.println(s); //cherry, date

//合并
Stream.concat(list1.stream(), list2.stream()).forEach(s -> System.out.println(s));

// 映射操作
words.stream().map(String::length); 

2.2. 终止操作

触发实际计算并关闭流,产生最终结果或副作用(如遍历、收集、统计等);最显著的特征是,在链式调用中这几个方法只能作为最后一个方法,因为它们没有返回Stream流;

    • forEach():遍历元素 ,返回值为void
    • collect():收集到集合
    • count():统计元素数量
    • reduce():聚合计算(如求和)
    • findFirst():查找第一个元素
    • toArray():将最终结果放大数组之中
//准备集合
List<String> words = new ArrayList<>();
words.add("apple");
words.add("banana");
words.add("cherry");
words.add("date");

// 遍历元素
words.stream().forEach(s -> System.out.println(s));

// 收集结果,转化为什么集合类型取决你想要什么,其集合类型完全和集合原来的特性一样
//诸如:Collectors.toSet(),还有一个Collectors.toMap()用法稍微麻烦些
List<String> filtered = words.stream()
                           .filter(s -> s.contains("a"))
                           .collect(Collectors.toList()); // [apple, banana, date]

//如何收集到Map集合之中,关键在于Map集合中键和值分别是什么,其实也不用害怕也挺简单的
//关键就在于.collect(Collectors.toMap(键的规则, 值的规则));中规则如何去写
//还有要注意的就是产生的数据中键不能重复,负责报错,其实也就是让你在生成Map集合时自己掂量掂量
//符不符合生成Map集合最基本的条件
Map<String,String> aFilteredMap = words.stream()
                           .filter(s -> s.contains("a"))
                           .collect(Collectors.toMap(
                                    s -> s+"值:",
                                    s -> s
                            ));

// 统计数量
long count = words.stream()
                .filter(s -> s.startsWith("a"))
                .count(); // 1
//转化数组
String[] arr = words.stream().toArray(value -> new String[value]);

在转化为Map集合时,一定要注意键的唯一性,不然会报错


三、典型应用场景

案例1:对象集合处理
class Person {
    String name;
    int age;
    // 构造方法和getter省略
}

List<Person> people = Arrays.asList(
    new Person("Alice", 23),
    new Person("Bob", 17),
    new Person("Charlie", 35)
);

// 获取成年人姓名列表(年龄>=18)
List<String> adultNames = people.stream()
    .filter(p -> p.getAge() >= 18)
    .map(Person::getName)
    .sorted()
    .collect(Collectors.toList());
// 结果:[Alice, Charlie]

通过Stream API可以实现声明式的数据处理,使代码更简洁且易于维护。合理使用能显著提升集合操作效率,特别是在大数据量场景下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值