Java8 Stream流相关学习记录
Stream流学习记录
Java8中 基于函数式编程引入Stream的概念,它将集合元素看成一种流,通过流的概念对集合元素进行相应的操作。应用于业务逻辑中,可以减少很多代码量并且代码风格更为简洁。本文简单记录学习过程及demo,随时修改补充。
特点
1.Stream不存储数据:stream不是集合容器,它只是根据定义的规则(过滤,转换,统计等api)对数据进行操作。这里类比于Iterator迭代器。
2. Stream不会改变数据源:Stream不会修改原来的数据源,它会产生一个新的集合或值。
3.待补充
使用步骤
获取流 -> 中间操作 -> 终结操作
1.获取流:
/* 获取一个流非常简单,有以下几种常用的方式:
- 所有的Collection集合都可以通过stream默认方法获取流;
default Stream<E> stream()
- Stream接口的静态方法of可以获取数组对应的流。
static <T> Stream<T> of(T... values)
参数是一个可变参数,那么我们就可以传递一个数组
*/
public static void main(String[] args) {
//把集合转换为Stream流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
Map<String, String> map = new HashMap<>();
//获取键,存储到一个Set集合中
Set<String> keySet = map.keySet();
Stream<String> stream3 = keySet.stream();
//获取值,存储到一个Collection集合中
Collection<String> values = map.values();
Stream<String> stream4 = values.stream();
//获取键值对(键与值的映射关系 entrySet)
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();
//把数组转换为Stream流
Integer[] arr = {1, 2, 3, 4, 5};
String[] arr2 = {"a", "bb", "ccc"};
Stream<Integer> stream6 = Stream.of(arr);
Stream<String> stream7 = Stream.of(arr2);
}
2.中间操作(Intermediate)(常用方法)
可以有零个或多个;打开流,过滤/映射;返回新流;交给下一个操作使用
2.1:map
/*
Stream流中的常用方法_map:用于类型转换
如果需要将流中的元素映射到另一个流中,可以使用map方法.
*/
public static void main(String[] args) {
//获取一个String类型的Stream流
Stream<String> stream = Stream.of("1", "2", "3", "4");
stream.map(s ->Integer.parseInt(s)).forEach(s -> System.out.println(s));
//使用map方法,把字符串类型的整数,转换(映射)为Integer类型的整数
stream.map(s -> Integer.parseInt(s)).forEach(i -> System.out.println(i));
}
结果:
2.2:filter
/*
Stream流中的常用方法_filter:用于对Stream流中的数据进行过滤
*/
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("张1", "张2", "赵1", "周23", "张3");
stream.filter(name ->name.startsWith("张"))
.forEach(name -> System.out.println(name));
//对Stream流中的元素进行过滤,只要姓张的人
Stream<String> stream2 = stream.filter(name -> name.startsWith("张"));
//遍历stream2流
stream2.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));
}
结果:2.3:skip
/*
Stream流中的常用方法_skip:用于跳过元素
如果希望跳过前几个元素,可以使用skip方法获取一个截取之后的新流:
Stream<T> skip(long n);
如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。
*/
public static void main(String[] args) {
//获取一个Stream流
String[] arr = {"1", "2", "3", "4", "5"};
Stream<String> stream = Stream.of(arr);
//使用skip方法跳过前3个元素
stream.skip(3).forEach(name -> System.out.println(name));
Integer[] ids = {1111, 2222, 3333, 4444};
List<Integer> collect = Stream.of(ids).collect(Collectors.toList());
for (Integer id : collect) {
System.out.println(id);
}
}
结果:
2.4:concat
/*
Stream流中的常用方法_concat:用于把流组合到一起
如果有两个流,希望合并成为一个流,那么可以使用Stream接口的静态方法concat
*/
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream1 = Stream.of("11", "22", "33", "44", "55");
//获取一个Stream流
String[] arr = {"A","B","C","D","E"};
Stream<String> stream2 = Stream.of(arr);
//把以上两个流组合为一个流
Stream.concat(stream1, stream2).forEach(name -> System.out.println(name));
}
结果:3.终结操作(Terminal)(常用方法)
只能有一个;最后的操作;常用方法也叫短路操作;
3.1:forEach
/*
Stream流中的常用方法_forEach
forEach方法,用来遍历流中的数据
是一个终结方法,遍历之后就不能继续调用Stream流中的其他方法
*/
public static void main(String[] args) {
//获取一个Stream流
Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六", "田七");
//使用Stream流中的方法forEach对Stream流中的数据进行遍历
stream.forEach(name -> System.out.println(name));
}
结果:
3.2:count
/*
Stream流中的常用方法_count:
用于统计Stream流中元素的个数
long count();
count方法是一个终结方法,返回值是一个long类型的整数
所以不能再继续调用Stream流中的其他方法了
*/
public static void main(String[] args) {
ArrayList<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);
//获取一个Stream流,统计元素个数
list.stream().count();
long count = list.stream().count();
System.out.println(count);
}
结果:
3.3:collect
/*
Stream流的收集方法
它是通过工具类Collectors提供了具体的收集方式
*/
public static void main(String[] args) {
//创建List集合对象
List<String> list = new ArrayList<String>();
list.add("张张张");
list.add("李李李");
list.add("赵赵赵");
list.add("林林");
// 需求1:得到名字为3个字的流
Stream<String> stringStream = list.stream().filter(name -> name.length() == 3);
// 需求2:把使用Stream流操作完毕的数据收集到List集合中并遍历
List<String> collect = stringStream.collect(Collectors.toList());
collect.stream().forEach(name -> System.out.println("需求2:"+name));
// 需求3:得到年龄大于25的流
//创建Set集合对象
Set<Integer> set = new HashSet<Integer>();
set.add(10);
set.add(20);
set.add(30);
set.add(33);
set.add(35);
Stream<Integer> integerStream = set.stream().filter(age -> age > 25);
// 需求4:把使用Stream流操作完毕的数据收集到Set集合中并遍历
Set<Integer> collect1 = integerStream.collect(Collectors.toSet());
// 需求5:得到字符串中年龄数据大于28的流
//定义一个字符串数组,每一个字符串数据由姓名数据和年龄数据组合而成
String[] strArray = {"张张张,30", "李李李,35", "赵赵赵,33", "林林,25"};
Stream<String> stringStream1 = Stream.of(strArray).filter(age -> Integer.parseInt(age.split(",")[1]) > 28);
// 需求6:把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作键,年龄作值
Map<String, Integer> collect2 = stringStream1.collect(Collectors.toMap(
s -> s.split(",")[0],
s -> Integer.parseInt(s.split(",")[1])
));
collect2.entrySet().forEach(entry -> System.out.println("需求6:"+entry.getKey()+"---"+entry.getValue()+"岁"));
}
结果:简单的demo练习,后续随时补充。