Stream流的使用
在 Java 8 中, 集合接口有两个方法来生成流:
stream() − 为集合创建串行流。
parallelStream() − 为集合创建并行流。
串行流
如果是数组的话,可以使用 Arrays.stream()
或者 Stream.of()
创建流;如果是集合的话,可以直接使用 stream()
方法创建流,因为该方法已经添加到 Collection 接口中。
示例1:
//集合创建流的方法
public static void main(String[] args) {
String[] arr = new String[]{"aaa", "bbb", "ccc"};
Stream<String> stream = Arrays.stream(arr);
//方法一
stream = Stream.of("aaa", "bbb", "ccc");
//方法二
List<String> list = new ArrayList<>();
list.add("xxx");
list.add("yyy");
list.add("zzz");
stream = list.stream();
}
示例2:
//Map创建流的方法
public static void main(String[] args) {
//map获取流
Map<Object, Object> map = new HashMap<>();
map.put("a","111");
map.put("b","222");
map.put("c","333");
map.put("d","444");
Stream<Object> keyStream = map.keySet().stream();
Stream<Object> valueStream = map.values().stream();
Stream<Map.Entry<Object, Object>> entryStream = map.entrySet().stream();
//筛选过滤 筛选出value = "111","222"的数据
Map<Object, Object> collect = entryStream.filter(s -> "111".equals(s.getValue()) || "222".equals(s.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.println(collect); //结果:{a=111, b=222}
}
并行流
并行流就是将一个流的内容分成多个数据块,并用不同的线程分别处理每个不同数据块的流。
可以调用的 parallelStream()
方法。当然也可以通过 stream.parallel()
将普通流转换成并行流。并行流也能通过sequential()
方法转换为顺序流,但要注意:流的并行和顺序转换不会对流本身做任何实际的变化,仅仅是打了个标记而已。并且在一条流水线上对流进行多次并行 / 顺序的转换,生效的是最后一次的方法调用。
示例:
public static void main(String[] args) {
//1、直接获取并行流
List<Integer> list = new ArrayList<>();
Stream<Integer> parallelStream = list.parallelStream();
//2、串行流转并行流
List<Integer> list2 = new ArrayList<>();
Stream<Integer> parallelStream2 = list2.stream().parallel();
//3、并行流转顺序流
Stream<Integer> sequential = parallelStream2.sequential();
}
操作流
Stream 类提供了很多有用的操作流的方法如下:
方法 | 作用 |
---|---|
filter() | 接收lambda,从流中排除某些操作 |
limit() | 截断流,使其元素不超过给定对象 |
skip(n) | 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补 |
distinct | 筛选,通过流所生成元素的hashCode()和equals去除重复元素 |
map | 接受Lambda,将元素转换成其他形式或提取信息。接受一个函数作为参数,该函数会被应用到每个元素上,并 |
sorted() | 自然排序(Comparable) |
sorted(Comparator com) | 定制排序(Comparator) |
allMatch | 检查是否匹配所有元素 |
anyMatch | 检查是否至少匹配一个元素 |
noneMatch | 检查是否没有匹配所有元素 |
findFirst | 返回第一个元素 |
findAny | 返回当前流中的任意元素 |
count | 返回流中元素的总个数 |
max | 返回流中最大值 |
min | 返回流中最小值 |
reduce | 归约操作可以将流中元素反复结合起来,得到一个值 |
collect | 将流转换为其他形式,接收一个Collector接口实现,用于给Stream中汇总的方法 |
操作流程
1、创建一个Stream:从一个数据源,如集合、数组中获取流
2、使用Stream操作数据:一个操作的中间链,对数据源的数据进行操作
3、终止Stream:一个终止操作,执行中间操作链,并产生结果
1)过滤
示例:
public static void main(String[] args) {
//通过 filter() 方法可以从流中筛选出我们想要的元素
List<String> list = new ArrayList<>();
list.add("徐凤年");
list.add("李淳罡");
list.add("青鸟");
list.add("邓太阿");
//筛选出带有“邓”的字符串。
Stream<String> stream = list.stream().filter(s-> s.contains("邓"));
stream.forEach(System.out::println);
}
2)截断
示例:
public static void main(String[] args) {
//通过 limit() 方法可以从流中截取出我们想要的元素
List<String> list = new ArrayList<>();
list.add("徐凤年");
list.add("李淳罡");
list.add("青鸟");
list.add("邓太阿");
//筛选出前3条数据
list.stream().limit(3).forEach(System.out::println);
}
3)跳过元素
示例:
public static void main(String[] args) {
//通过 skip() 方法可以从流中跳过某元素筛选出我们想要的元素
List<String> list = new ArrayList<>();
list.add("徐凤年");
list.add("李淳罡");
list.add("青鸟");
list.add("邓太阿");
//筛选出跳过"徐凤年"的list
list.stream().skip(1).forEach(System.out::println);
}
4)去重
示例:
public static void main(String[] args) {
// 通过distinct()方法去重
List<String> stringList = new ArrayList<String>() {{
add("A");
add("A");
add("B");
add("B");
add("C");
}};
stringList = stringList.stream().distinct().collect(Collectors.toList());
System.out.println(stringList);
//实体类列表的去重【注意:实体类需要重写equals() 以及 hashCode() 方法,否则distinct()不生效】
List<UserInfo> userInfoList = new ArrayList<UserInfo>() {{
add(new UserInfo("张三","18"));
add(new UserInfo("张三","18"));
add(new UserInfo("李四","21"));
add(new UserInfo("王五","44"));
add(new UserInfo("赵六","48"));
add(new UserInfo("赵六","88"));
}};
userInfoList = userInfoList.stream().distinct().collect(Collectors.toList());
System.out.println("userInfoList:"+userInfoList);
//根据 List<Object> 中 Object 某个属性去重【指定属性去重】
List<UserInfo> userInfoList2 = userInfoList.stream().collect(
collectingAndThen(
toCollection(() -> new TreeSet<>(Comparator.comparing(UserInfo::getUserName))), ArrayList::new)
);
System.out.println("userInfoList2:"+userInfoList2);
}
5)映射
示例:
public static void main(String[] args) {
//map()方法指定映射
List<String> list = new ArrayList<>();
list.add("徐凤年");
list.add("李淳罡");
list.add("青鸟");
list.add("邓太阿");
Stream<Integer> stream = list.stream().map(String::length);
stream.forEach(System.out::println); //结果 3 3 2 3
}
6)排序
示例:
public static void main(String[] args) {
//sorted()方法 实体类列表的排序
List<UserInfo> userInfoList = new ArrayList<UserInfo>() {{
add(new UserInfo("张三", "18"));
add(new UserInfo("李四", "21"));
add(new UserInfo("王五", "66"));
add(new UserInfo("赵六", "16"));
add(new UserInfo("赵六", "88"));
}};
//升序排序
userInfoList = userInfoList.stream().sorted(Comparator.comparing(UserInfo::getAge)).collect(Collectors.toList());
//降序排序 reversed()
userInfoList = userInfoList.stream().sorted(Comparator.comparing(UserInfo::getAge).reversed()).collect(Collectors.toList());
}
7)匹配
示例:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("徐凤年");
list.add("李淳罡");
list.add("青鸟");
list.add("邓太阿");
//anyMatch:判断的条件里,任意一个元素成功,返回true
boolean anyMatchFlag = list.stream().anyMatch(s-> s.contains("徐"));
//allMatch:判断条件里的元素,所有的都是,返回true
boolean allMatchFlag = list.stream().allMatch(s-> s.length() > 1);
//noneMatch:与allMatch相反,判断条件里的元素,所有的都不是,返回true
boolean noneMatchFlag = list.stream().noneMatch(s -> s.endsWith("李"));
System.out.println(anyMatchFlag);
System.out.println(allMatchFlag);
System.out.println(noneMatchFlag);
}
8)返回第一个元素
示例:
public static void main(String[] args) {
//findFirst()方法 返回列表中的第一个元素
List<String> list = Arrays.asList("C", "C++", "JAVA", "Python","JON","COM");
Optional<String> first = list.parallelStream().filter(s -> s.startsWith("C")).findFirst();
//findAny()方法,返回的元素是不确定的
Optional<String> findAny = list.parallelStream().filter(s -> s.startsWith("C")).findAny();
System.out.println("first:"+first);
System.out.println("findAny:"+findAny);
}
9)返回流中的任意元素
示例:
public static void main(String[] args) {
//findAny()方法 返回任意一条数据
List<UserInfo> userInfoList = new ArrayList<UserInfo>() {{
add(new UserInfo("张三","18"));
add(new UserInfo("李四","21"));
add(new UserInfo("王五","44"));
add(new UserInfo("赵六","48"));
}};
//筛选出"王五"的数据,返回实体,orElse (null)表示如果一个都没找到返回null【orElse ()中可以塞默认值。】
UserInfo userInfo = userInfoList.stream().filter(s->"王五".equals(s.getUserName())).findAny().orElse(null);
System.out.println(userInfo);
}
10)聚合函数
示例:
public static void main(String[] args) {
//count()方法 统计元素总数
List<String> list = Arrays.asList("AAA", "BBB", "CCC", "DDD");
long count = list.stream().count();
System.out.println("count:" + count); //结果 count:4
//max()最大值
List<Integer> maxList = Arrays.asList(10, 20, 30, 40);
Optional<Integer> maxOptional = maxList.stream().max(Comparator.comparing(Function.identity()));
System.out.println("max:"+maxOptional.get()); //结果 max:40
//min()最小值
List<Integer> minList = Arrays.asList(10, 20, 30, 40);
Optional<Integer> maxOptional2 = minList.stream().min(Comparator.comparing(Function.identity()));
System.out.println("min:"+maxOptional2.get());//结果 min:10
}
11)归约操作
``
示例:
public static void main(String[] args) {
//reduce()方法 归约操作
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 方法一
int sum = Arrays.stream(numbers).reduce(0, (a, b) -> a + b);// 55
//方法二
int sum2 = Arrays.stream(numbers).reduce(0, Integer::sum);// 55
//数学运算
int sum3 = Arrays.stream(numbers).reduce(0, (a, b) -> a - b);// -55
int sum4 = Arrays.stream(numbers).reduce(0, (a, b) -> a * b);// 0
int sum5 = Arrays.stream(numbers).reduce(0, (a, b) -> a / b); // 0
//最大和最小
int max = Arrays.stream(numbers).reduce(0, (a, b) -> a > b ? a : b); // 10
int max1 = Arrays.stream(numbers).reduce(0, Integer::max); // 10
int min = Arrays.stream(numbers).reduce(0, (a, b) -> a < b ? a : b); // 0
int min1 = Arrays.stream(numbers).reduce(0, Integer::min); // 0
}
11)规约操作
将流转换为其他形式,接收一个Collector接口实现,用于给Stream中汇总的方法
示例:
public static void main(String[] args) {
//collect()方法 将流转换为其他形式,接收一个Collector接口实现,用于给Stream中汇总的方法
String[] strings = {"AAA", "BBB", "CCC", "DDD"};
//Collectors.toList() 收集元素到List集合
List<String> collectList = Arrays.stream(strings).collect(Collectors.toList());
//Collectors.toSet() 收集元素到set集合
Set<String> collectSet = Arrays.stream(strings).collect(Collectors.toSet());
//Collectors.toMap(String::toString,o->o) 收集元素到map集合
Map<String, Object> collectMap =Arrays.stream(strings).collect(Collectors.toMap(String::toString,o->o));
//Collectors.toCollection() 收集元素到指定集合
ArrayList<String> arrayList = Arrays.stream(strings).collect(Collectors.toCollection(ArrayList::new));
}
注意:记录stream流的一些常用的操作方法(●'◡'●)