1 什么是Stream流
Stream 流是Java对集合数据进行操作的一种抽象概念。它允许我们以声明式的方式对集合中的元素进行各种操作,如过滤、映射、排序、聚合等,而无需编写复杂的循环和条件语句。
2 Stream 流的基本用法
2.1 获取Stream流
2.1.1 普通类型
// 基本数据类型
int[] arr= {1,2,3,4,6,7,8,9};
Arrays.stream(arr).forEach(s -> System.out.print(s + " "));
System.out.println("--------------------------");
// 引用类型数据
String[] arr2 = {"a","ab","bc"};
Arrays.stream(arr2).forEach(s -> System.out.print(s + " "));
System.out.println();
System.out.println("--------------------------");
输出结果
2.1.2 集合类型
// 1、单列集合获取stream流
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "a","b","c","d");
// 获取一条流水线,并把数据放到流上去
Stream<String> stream = list.stream();
// 输出集合的元素
list.stream().forEach(s -> System.out.print(s + " "));
// 2、双列集合获取stream流
HashMap<String,Integer> tm = new HashMap<>();
tm.put("aaa",111);
tm.put("bbb",111);
tm.put("ccc",111);
tm.put("ddd",111);
// 2.1 先转为单列再获取流
Set<String> keySet = tm.keySet();
keySet.stream().forEach(s -> System.out.print(s + " "));
// 2.2 直接用链式获取单列集合
tm.keySet().stream().forEach(s -> System.out.print(s + " "));
输出结果
2.2 Stream流的中间方法
中间方法主要包括filter、limit、skip、distinct、concat、map等等。
过滤(filter)、获取前几个元素(limit)、跳过前几个元素(skip)。
// Stream流的中间方法
// 注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
// 注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张一山","谢广坤","张二","周三风","张云云","张翠山","胡彪", "张二");
ArrayList<String> list1 = new ArrayList<>();
Collections.addAll(list,"张无忌","周芷若");
// 1、filter 过滤 把张开头的留下,其他的不要
// 先获取list的stream流,过滤掉"张"开头的,再获取长度为3的,最后打印
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s -> System.out.print(s + " "));
// 2、limit 获取前几个元素
list.stream().limit(3).forEach(s -> System.out.print(s + " "));
// 3、skip 跳过前几个元素
list.stream().skip(4).forEach(s -> System.out.print(s + " "));
输出结果
元素去重(distinct)、合并(concat)、映射(map)。
输出结果
2.3 Stream流的终结方法
常用的终结方法包括:遍历(forEach)、统计(count)、收集(toArray)等等。
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张无忌","张无忌","周芷若","赵敏","张三丰","张翠山","张良","王二麻子","谢广坤");
// 1、forEach 遍历
list.stream().forEach(s -> System.out.println(s));
// 2、count 统计
long count = list.stream().count();
System.out.println(count);
// 3、toArray 收集流的数据,放到数组中
Object[] objects = list.stream().toArray();
System.out.println(Arrays.toString(objects));
// IntFunction的泛型:具体类型的数组
// apply的形参:流中数据的个数,要跟数组的长度保持一致
// apply的返回值:具体类型的数组
// 方法体:就是创建数组
String[] strings = list.stream().toArray(new IntFunction<String[]>() {
@Override
public String[] apply(int value) {
return new String[value];
}
});
System.out.println(Arrays.toString(strings));
// toArray方法的参数的作用:负责创建一个指定类型的数组
// toArray方法的底层,会依次得到流里面的每一个数据,并把数据放到数组中
// toArray方法的返回值,是一个装着流里面所有数据的数组
String[] strings1 = list.stream().toArray(value -> new String[value]);
System.out.println(Arrays.toString(strings1));
输出结果
3 使用场景
需求:将查询到的订单商品和数据拼接成一个字符串。
private String getOrderGoodsStr(Orders orders) {
// 查询订单商品详细信息(订单中的商品和数量)
List<OrdersDetail> ordersDetails = ordersDetailMapper.getByOrderId(orders.getId());
// 将每条订单商品信息拼接为字符串(格式:卫衣 * 3)
List<String> orderGoodsList = ordersDetails.stream().map( x -> {
String orderGood = x.getGoodsName() + "*" + x.getGoodsNumber() + ";";
return orderGood;
}).collect(Collectors.toList());
return String.join("",orderGoodsList);
}
4 总结
比起传统的循环和条件语句,Stream 流的代码更加简洁,减少了代码量和复杂度,但由于 Stream 流的操作是链式调用的,需要注意操作顺序可能会影响结果。