为什么要使用Stream流呢?使用这个流能帮到我们什么?
下面给出一个案例,动手敲代码实现一下。
正常代码:
import java.util.ArrayList;
public class StreamDemo1 {
public static void main(String[] args) {
// 创建一个集合,存储多个字符串元素
ArrayList<String> list1 = new ArrayList<>();
list1.add("张天道");
list1.add("周树人");
list1.add("张无忌");
list1.add("李太白");
list1.add("张柏");
list1.add("孙悟空");
// 把集合中以"张"开头的元素存储到一个新的集合
ArrayList<String> list2 = new ArrayList<>();
for (String s : list1) {
if (s.startsWith("张"))
list2.add(s);
}
// 把“张”开头的集合中长度为3的元素存储到一个新的集合
ArrayList<String> list3 = new ArrayList<>();
for (String s : list2) {
if (s.length()==3)
list3.add(s);
}
// 遍历上一步得到的集合
for (String s : list3) {
System.out.println(s);
}
}
}
那如果使用的是Stream流去解决这个问题呢?
import java.util.ArrayList;
public class StreamDemo2 {
public static void main(String[] args) {
// 创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("张天道");
list.add("周树人");
list.add("张无忌");
list.add("李太白");
list.add("张柏");
list.add("孙悟空");
list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(System.out::println);
}
}
可以看到,使用Stream中的filter()方法可以非常方便的实现数据的筛选、过滤。代码简洁了很多。
那么Stream流该怎么使用,如何生成呢?
Collection体系的集合包括List、ArrayList、LinkedList、Set等集合。
Map集合本身不能直接使用流,但是它的一些方法可以间接将Map对象转化为Collection对象,比如
而数组就是通过Stream.of()方法去生成流。
package Test;
import java.util.*;
import java.util.stream.Stream;
public class StreamDemo3 {
public static void main(String[] args) {
// Collection体系中的集合可以直接使用Stream流
List<String> list = new ArrayList<>();
Stream<String> listStream = list.stream();
Set set = new HashSet<>();
Stream setStream = set.stream();
// Map体系的集合是间接生成流的
Map<String,String> map = new HashMap<>();
Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();// 转换成Set集合
Stream<String> keyStream = map.keySet().stream();// 转换成Set集合
Stream<String> valuesStream = map.values().stream();// 转换成Collection集合
// 数组可以通过Stream接口中的静态方法of(T...values)生成流
String[] strArray = {"hello","world","泰罗奥特里"};
Stream<String> strArrayStream1 = Stream.of(strArray);
Stream<String> stringStream = Stream.of("奥特曼", "凹凸曼", "你好呀");
Stream<Integer> integerStream = Stream.of(1, 32, 65);
}
}
那既然学会了如何生成Stream流,那么接下来就是学习它的常用方法。
filter()方法我们最前面的案例中使用过了,可以到前面复习一下。接下来我们就新学习limit()、skip()方法。
- limit(long n):截取流中前n个元素。limit(3)就是截取流中前面的三个元素。
- skip(long n):跳过流中前n个元素,保留余下的元素。skip(3)就是跳过前面3个元素,余下的元素仍然保留在集合中。
// 创建一个集合,存储多个字符串元素 ArrayList<String> list = new ArrayList<String>(); list.add("张天道"); list.add("周树人"); list.add("张无忌"); list.add("李太白"); list.add("张柏"); list.add("孙悟空"); // 截取集合中的前面3个元素 list.stream().limit(3).forEach(System.out::println); System.out.println("----------------------"); // 跳过集合中的前面3个元素 list.stream().skip(3).forEach(System.out::println); System.out.println("----------------------");
concat(a,b):合并a和b两个流为一个流。
distict():返回由该流的不同元素组成的流。
// 创建一个集合,存储多个字符串元素 ArrayList<String> list = new ArrayList<String>(); list.add("张天道"); list.add("周树人"); list.add("张无忌"); list.add("李太白"); list.add("张柏"); list.add("孙悟空"); // 截取集合中的前面4个元素 Stream<String> stream1 = list.stream().limit(4); // 跳过集合中的前面2个元素 Stream<String> stream2 = list.stream().skip(2); // 合并a和b两个流 /*Stream.concat(stream1, stream2).forEach(s-> System.out.println(s));*/ // 合并a和b两个流,要求流中不能有重复的元素 Stream.concat(stream1,stream2).distinct().forEach(System.out::println);
sorted(): 将此流中的元素按照自然顺序排序,如1→9,a-z。
sorted(Comparator):按照我们自己的想法去实现比较器。
// 创建一个集合,存储多个字符串元素 ArrayList<String> list = new ArrayList<String>(); list.add("zhangtiandao"); list.add("zhoushuren"); list.add("zhangwuji"); list.add("litaibai"); list.add("zhangbaizhi"); list.add("sunwukong"); // 需求1:按照自然顺序排序 list.stream().sorted().forEach(System.out::println); System.out.println("-----------------"); // 需求2:根据字符串的长度进行排序 list.stream().sorted((s1,s2)->s1.length()-s2.length()).forEach(System.out::println); System.out.println("-----------------"); // 需求3:根据字符串的长度进行排序,若长度相等则按自然排序进行排列 list.stream().sorted((s1,s2)->{ int num = s1.length() - s2.length(); int num2 = num == 0 ? s1.compareTo(s2) : num; return num2; }).forEach(System.out::println);
// 创建集合 ArrayList<String> list = new ArrayList<>(); // 添加元素 list.add("10"); list.add("30"); list.add("60"); list.add("50"); list.add("45"); list.add("80"); list.add("16"); // 需求:将集合中的字符串数据转换成整数后在控制台输出 list.stream().map(s -> Integer.parseInt(s)).forEach(System.out::println); System.out.println("-----------------"); list.stream().mapToInt(Integer::parseInt).forEach(System.out::println); System.out.println("-----------------"); // 需求:返回此流中元素的总和 int result = list.stream().mapToInt(Integer::parseInt).sum(); System.out.println("总和="+result);
这两个方法比较的简单,就不写代码了。
Stream流的数据收集
Stream流中有一个方法:collect(),该方法可以将流中的数据保存到List/Set集合中。
collect()方法:
collect(Collectors.toList()):将流中的数据存放到List集合中。 collect(Collectors.toSet()):将流中的数据存放到Set集合中。
当然,collect也有一些其他的方法,例如tomap(),toCollection()等等。
案例代码:
package Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamCollection {
public static void main(String[] args) {
// 创建集合
List<String> list = new ArrayList<>();
// 添加元素
list.add("奥特曼");
list.add("波特曼");
list.add("如梦");
list.add("笑苍穹");
// Stream流:得到名字为3个字的流
Stream<String> listStream = list.stream().filter(s -> s.length() == 3);
// 将流中数据存放到list集合中保存
List<String> nameList = listStream.collect(Collectors.toList());
// 遍历数据
for (String s : nameList) {
System.out.println(s);
}
}
}