标签:his object 切片 port import 优化 cto 跳过 sre
在上一篇中我们带领大家简单的了解流的概念及使用场景,知道了流的本质操作是将外部迭代转为了内部迭代,由此从程序并发性上得到了很大的优化。在本节我们就来好好的介绍流的常见用法。
对于一串流,我们有时需要取出我们需要的流中某些元素,主要是通过谓词筛选。看代码:
首先定义一个POJO,后续操作都基于此来实例化元素。
1 package com.hz; 2 3 /** 4 * 民警实体类 5 */ 6 public class Police { 7 /** 8 * 民警警号 9 */ 10 private String policeNo; 11 /** 12 * 民警姓名 13 */ 14 private String policeName; 15 /** 16 * 民警年龄 17 */ 18 private Integer policeAge; 19 /** 20 * 是否退休 21 */ 22 private boolean policeIsRetire; 23 24 public Police(String policeNo, String policeName, Integer policeAge, boolean policeIsRetire) { 25 this.policeNo = policeNo; 26 this.policeName = policeName; 27 this.policeAge = policeAge; 28 this.policeIsRetire = policeIsRetire; 29 } 30 31 public String getPoliceNo() { 32 return policeNo; 33 } 34 35 public void setPoliceNo(String policeNo) { 36 this.policeNo = policeNo; 37 } 38 39 public String getPoliceName() { 40 return policeName; 41 } 42 43 public void setPoliceName(String policeName) { 44 this.policeName = policeName; 45 } 46 47 public Integer getPoliceAge() { 48 return policeAge; 49 } 50 51 public void setPoliceAge(Integer policeAge) { 52 this.policeAge = policeAge; 53 } 54 55 public boolean isPoliceIsRetire() { 56 return policeIsRetire; 57 } 58 59 public void setPoliceIsRetire(boolean policeIsRetire) { 60 this.policeIsRetire = policeIsRetire; 61 } 62 63 @Override 64 public String toString() { 65 return "Police{" + 66 "policeNo=‘" + policeNo + ‘\‘‘ + 67 ", policeName=‘" + policeName + ‘\‘‘ + 68 ", policeAge=" + policeAge + 69 ", policeIsRetire=‘" + policeIsRetire + ‘\‘‘ + 70 ‘}‘; 71 } 72 73 @Override 74 public boolean equals(Object o) { 75 if (this == o) return true; 76 if (!(o instanceof Police)) return false; 77 78 Police police = (Police) o; 79 80 if (policeIsRetire != police.policeIsRetire) return false; 81 if (!policeNo.equals(police.policeNo)) return false; 82 if (!policeName.equals(police.policeName)) return false; 83 return policeAge.equals(police.policeAge); 84 } 85 86 @Override 87 public int hashCode() { 88 int result = policeNo.hashCode(); 89 result = 31 * result + policeName.hashCode(); 90 result = 31 * result + policeAge.hashCode(); 91 result = 31 * result + (policeIsRetire ? 1 : 0); 92 return result; 93 } 94 }
1 package com.hz; 2 3 import java.util.Arrays; 4 import java.util.List; 5 6 import static java.util.stream.Collectors.toList; 7 8 /** 9 * 筛选某些元素 10 * 包含:filter / distinct / limit / skip 11 */ 12 public class FilterAndLimitStreamDemo { 13 public static void main(String[] args) { 14 List<Police> policeList = Arrays.asList( 15 new Police("P001", "余警官", 27, false), 16 new Police("P002", "李警官", 32, false), 17 new Police("P003", "程警官", 25, false), 18 new Police("P004", "杨警官", 35, false), 19 new Police("P005", "张警官", 70, true), 20 new Police("P006", "王警官", 68, true), 21 new Police("P007", "赵警官", 77, true), 22 new Police("P008", "刘警官", 64, true), 23 new Police("P008", "刘警官", 64, true) 24 ); 25 26 //***** 1-使用谓词筛选 27 List<Police> filterPolices = policeList.stream().filter(Police::isPoliceIsRetire).collect(toList()); 28 System.out.println("结果1: " + filterPolices); 29 30 System.out.println("---------------- 分割线 ---------------------"); 31 32 //***** 2-筛选 大于60岁 并 去除重复的数据(是否重复 根据HashCode和equal决定 两者同时) 33 policeList.stream().filter(p -> p.getPoliceAge() > 60).distinct().forEach(System.out :: println); 34 35 System.out.println("---------------- 分割线 ---------------------"); 36 37 //***** 3-截流 截取前三位退休的民警 38 policeList.stream().filter(Police :: isPoliceIsRetire).limit(3).forEach(System.out :: println); 39 40 System.out.println("---------------- 分割线 ---------------------"); 41 42 //***** 4-跳过几个元素 获取退休民警 并跳过前两位退休民警 43 policeList.stream().filter(Police :: isPoliceIsRetire).skip(2).forEach(System.out :: println); 44 } 45 }
映射即将流中的元素进行处理后返回新的流。
1 package com.hz; 2 3 import java.util.Arrays; 4 import java.util.List; 5 import java.util.stream.Stream; 6 7 import static java.util.stream.Collectors.toList; 8 9 /** 10 * 流中映射 11 */ 12 public class StreamMapDemo { 13 public static void main(String[] args) { 14 List<Police> policeList = Arrays.asList( 15 new Police("P001", "余警官", 27, false), 16 new Police("P002", "李警官", 32, false), 17 new Police("P003", "程警官", 25, false), 18 new Police("P004", "杨警官", 35, false), 19 new Police("P005", "张警官", 70, true), 20 new Police("P006", "司马警官", 68, true), 21 new Police("P007", "赵科", 77, true), 22 new Police("P008", "刘警官", 64, true), 23 new Police("P008", "刘警官", 64, true) 24 ); 25 26 //***** 1-对流元素中的字段进行处理 获取民警的姓名 和 获取民警姓名长度 27 policeList.stream().map(Police :: getPoliceName).forEach(System.out :: println); 28 29 List<Integer> policesNameLength = policeList.stream().map(Police::getPoliceName).map(String::length).collect(toList()); 30 System.out.println("结果: " + policesNameLength); 31 32 System.out.println("------------ 分割线 ----------------"); 33 34 //***** 2-流的扁平化 将一组单词 重复的字母去除 35 String[] words = {"gong", "zi", "chuan", "qi"}; 36 Stream<String> wordsStream = Arrays.stream(words); //将数组转为流对象 37 Stream<String> wordsStream2 = Arrays.stream(words); //将数组转为流对象 38 39 //此时为 将每个单词为一个数组转为一个流即四个流 流本身没有重复 两个流之间是存在重复的 40 List<Stream<String>> streamsList = wordsStream.map(s -> s.split("")).map(Arrays::stream).distinct().collect(toList()); 41 System.out.println(streamsList); 42 //wordsStream为一个流 不可多次使用 43 // java8中有个扁平化的处理 为将流中的值组成一个大的流 flatMap 44 List<String> disWordsList = wordsStream2.map(s -> s.split("")).flatMap(Arrays::stream).distinct().collect(toList()); 45 System.out.println("结果:" + disWordsList); 46 47 System.out.println("---------------- 分割线 --------------------"); 48 49 //***** 3-一个实例 给定两个数字列表,如何返回所有的数对呢? 50 // 例如,给定列表[1, 2, 3]和列表[3, 4],应该返回[(1, 3), (1, 4), (2, 3), (2, 4), (3, 3), (3, 4)] 51 Integer[] ints1 = {1, 2, 3}; 52 Integer[] ints2 = {3, 4}; 53 54 // List<List<int[]>> result = Arrays.stream(ints1).map(i -> { 55 // List<int[]> tempList = Arrays.stream(ints2).map(j -> { 56 //// int[] temp = new int[2]; 57 //// temp[0] = i; 58 //// temp[1] = j; 59 //// return temp; 60 // return new int[]{i, j}; 61 // }).collect(toList()); 62 // return tempList; 63 // }).collect(toList()); 64 65 //更简化 66 List<List<int[]>> result = Arrays.stream(ints1).map(i -> Arrays.stream(ints2).map(j -> new int[]{i, j}).collect(toList())).collect(toList()); 67 68 result.forEach(l -> l.forEach(is -> System.out.println((is[0] + "," + is[1])))); 69 } 70 }
有时我们需要查看数据集中的某些元素是否匹配一个给定的属性。
1 package com.hz; 2 3 import java.util.*; 4 5 /** 6 * 流中查找和匹配 7 */ 8 public class FindAndMatchDemo { 9 public static void main(String[] args) { 10 List<Police> policeList = Arrays.asList( 11 new Police("P001", "余警官", 27, false), 12 new Police("P002", "李警官", 32, false), 13 new Police("P003", "程警官", 25, false), 14 new Police("P004", "杨警官", 35, false), 15 new Police("P005", "张警官", 70, true), 16 new Police("P006", "司马警官", 68, true), 17 new Police("P007", "赵科", 77, true), 18 new Police("P008", "刘警官", 64, true), 19 new Police("P008", "刘警官", 64, true) 20 ); 21 22 //***** 1-检查流中元素至少匹配一个 民警列表中至少有一名退休民警 23 System.out.println("--------------- anyMatch分割线 ------------------"); 24 if (policeList.stream().anyMatch(Police :: isPoliceIsRetire)) { 25 System.out.println("列表存在退休民警..."); 26 } else { 27 System.out.println("当前没有退休民警..."); 28 } 29 30 System.out.println("----------- allMatch分割线 ------------"); 31 32 //***** 2-检查流中是否匹配所有元素 是否为退休民警列表 33 if (policeList.stream().allMatch(Police :: isPoliceIsRetire)) { 34 System.out.println("该列表为一个退休民警列表..."); 35 } else { 36 System.out.println("该列表中存在未退休的民警..."); 37 } 38 39 System.out.println("------------- noneMatch分割线 -----------"); 40 //与allMatch对应的是noneMatch 即所有都不匹配 41 if (policeList.stream().noneMatch(Police::isPoliceIsRetire)) { 42 System.out.println("该列表都不是退休民警"); 43 } else { 44 System.out.println("该列表存在退休民警"); 45 } 46 47 System.out.println("--------------- 查找分割线 --------------------"); 48 49 //***** 3-查找元素 从民警列表中找出任一元素 50 Optional<Police> anyPolice = policeList.stream().findAny(); 51 System.out.println(anyPolice); 52 //在这里Optional这是一个容器类,该容器中只能存储一个对象 其中Optional中实现了一些方法用来操作和判断该容器是否有值 53 //这里我们简单了解下,详细后面我们在好好介绍下该类 54 //***** 案例:找出任意一个退休民警 并打印该民警姓名 ifPresent若有值则执行 55 policeList.stream().filter(Police :: isPoliceIsRetire).findAny().ifPresent(p -> System.out.println(p.getPoliceName())); 56 boolean hasValue = policeList.stream().filter(Police::isPoliceIsRetire).findAny().isPresent(); //是否有值isPresent 57 System.out.println("容器中是否有匹配的值:" + hasValue); 58 // 若容器中有值则返回,否则返回一个默认的值 59 Police police = policeList.stream().filter(Police :: isPoliceIsRetire).findAny().orElse(new Police("","",0, false)); 60 System.out.println("返回民警: " + police); 61 //获取匹配的民警 有则返回 没有则异常java.util.NoSuchElementException: No value present 62 Police police1 = policeList.stream().filter(Police::isPoliceIsRetire).findAny().get(); 63 System.out.println("获取民警: " + police1); 64 65 System.out.println("---------------"); 66 //***** 4-查找流中第一个元素 67 Police police2 = policeList.stream().filter(Police::isPoliceIsRetire).findFirst().get(); 68 System.out.println("结果: " + police2); 69 } 70 }
有时我们又需要将流中所有的元素结合着来处理,此时就需要归约。
package com.hz; import java.util.Arrays; import java.util.List; import java.util.Optional; public class ReduceDemo { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(5, 4, 3, 9); //***** 1-将一组数值求和 Integer sum = numbers.stream().reduce(0, (a, b) -> a + b); System.out.println("sum: " + sum); //若reduce未指定第一个参数,则不知实际返回类型,此时语言本身返回一个Optional容器对象 Optional<Integer> sumOptional = numbers.stream().reduce((a, b) -> a + b); System.out.println("sum-optional: " + sumOptional); //变化 sum = numbers.stream().reduce(0, Integer :: sum); System.out.println("sum2: " + sum); System.out.println("------------ 分割线 --------------"); //***** 2-获取一组数的最大和最小值 Optional<Integer> max = numbers.stream().reduce(Integer::max); System.out.println("max: " + max); Optional<Integer> min = numbers.stream().reduce(Integer :: min); System.out.println("min: " + min); System.out.println("---------- 分割线 --------"); //**** 3-一个案例:使用map和reduce统计民警列表中有多少民警 List<Police> policeList = Arrays.asList( new Police("P001", "余警官", 27, false), new Police("P002", "李警官", 32, false), new Police("P003", "程警官", 25, false), new Police("P004", "杨警官", 35, false), new Police("P005", "张警官", 70, true), new Police("P006", "司马警官", 68, true), new Police("P007", "赵科", 77, true), new Police("P008", "刘警官", 64, true) ); Integer policeNum = policeList.stream().map(p -> 1).reduce(0, Integer::sum); System.out.println("列表中民警数量: " + policeNum); } }
下面我们通过一个案例来总结一下流的所有操作。
package com.hz; import java.util.*; /** * 关于流操作的一个案例 */ public class StreamDemo { public static void main(String[] args) { List<Police> polices = Arrays.asList( new Police("P001", "Y警官", 27, "浙江", 2019), new Police("P002", "L警官", 32, "安徽", 2019), new Police("P003", "C警官", 25, "安徽", 2015), new Police("P004", "Y警官", 35, "浙江", 2015), new Police("P005", "Z警官", 31, "上海", 2018), new Police("P006", "W警官", 42, "浙江", 2018), new Police("P007", "Z警官", 31, "浙江", 2019), new Police("P009", "Z警官", 32, "浙江", 2019), new Police("P008", "L警官", 49, "浙江", 2019) ); // (1) 找出2019年入职的民警,并按年龄排序(从低到高)。 polices.stream().filter(p -> p.getPoliceEntryYear() == 2019).sorted(Comparator.comparing(Police::getPoliceAge)).forEach(System.out::println); System.out.println("---------------- 分割线 --------------------------"); // (2) 民警籍贯都在哪里? polices.stream().map(Police::getPoliceNativePlace).distinct().forEach(System.out::println); System.out.println("---------------- 分割线 --------------------------"); // (3) 查找所有来自于浙江的民警,并按姓名排序。 polices.stream().filter(p -> "浙江".equals(p.getPoliceNativePlace())).sorted(Comparator.comparing(Police::getPoliceName)).forEach(System.out::println); System.out.println("---------------- 分割线 --------------------------"); // (4) 返回所有民警的警号,并按警号顺序排序。 polices.stream().map(Police::getPoliceNo).sorted().forEach(System.out::println); System.out.println("---------------- 分割线 --------------------------"); // (5) 有没有民警籍贯是在安徽的? if (polices.stream().anyMatch(p -> "安徽".equals(p.getPoliceNativePlace()))) { System.out.println("存在籍贯为安徽的民警..."); } else { System.out.println("不存在籍贯为安徽的民警..."); } System.out.println("---------------- 分割线 --------------------------"); // (6) 获取籍贯为浙江的民警的年龄之和 Integer ageSum = polices.stream().filter(p -> "浙江".equals(p.getPoliceNativePlace())).map(Police::getPoliceAge).reduce(0, Integer::sum); //以上方式暗中存在一个装箱操作 其实stream中有个数值流可以省去这个隐藏操作 ageSum = polices.stream().filter(p -> "浙江".equals(p.getPoliceNativePlace())).mapToInt(Police::getPoliceAge).sum(); System.out.println("所有浙江民警年龄总和:" + ageSum); System.out.println("---------------- 分割线 --------------------------"); // (7) 所有民警中,年龄最大的是多少? Optional<Integer> ageMaxOptional = polices.stream().map(Police::getPoliceAge).reduce(Integer::max); // 或使用流的max方法 ageMaxOptional = polices.stream().max(Comparator.comparing(Police::getPoliceAge)).map(Police::getPoliceAge); //同样 该方式也可以转为数值流计算 OptionalInt maxAgeOp = polices.stream().mapToInt(Police::getPoliceAge).max(); System.out.println(maxAgeOp.getAsInt()); if (ageMaxOptional.isPresent()) { System.out.println("所有民警最大年龄为: " + ageMaxOptional.get()); } else { System.out.println("没有民警..."); } System.out.println("---------------- 分割线 --------------------------"); // (8) 找到民警中年龄最小的民警 Optional<Police> ageMinPoliceOptional = polices.stream().reduce((p1, p2) -> p1.getPoliceAge() < p2.getPoliceAge() ? p1 : p2); if (ageMinPoliceOptional.isPresent()) { System.out.println("年龄最小的民警: " + ageMinPoliceOptional); } else { System.out.println("列表中没有民警..."); } //其实还有更加简单的方式,流中有个min方法 ageMinPoliceOptional = polices.stream().min(Comparator.comparing(Police::getPoliceAge)); System.out.println(ageMinPoliceOptional); } static class Police { private String policeNo; private String policeName; private Integer policeAge; private Integer policeEntryYear; private String policeNativePlace; public Police(String policeNo, String policeName, Integer policeAge, String policeNativePlace, Integer policeEntryYear) { this.policeNo = policeNo; this.policeName = policeName; this.policeAge = policeAge; this.policeNativePlace = policeNativePlace; this.policeEntryYear = policeEntryYear; } public String getPoliceNo() { return policeNo; } public void setPoliceNo(String policeNo) { this.policeNo = policeNo; } public String getPoliceName() { return policeName; } public void setPoliceName(String policeName) { this.policeName = policeName; } public Integer getPoliceAge() { return policeAge; } public void setPoliceAge(Integer policeAge) { this.policeAge = policeAge; } public String getPoliceNativePlace() { return policeNativePlace; } public void setPoliceNativePlace(String policeNativePlace) { this.policeNativePlace = policeNativePlace; } public Integer getPoliceEntryYear() { return policeEntryYear; } public void setPoliceEntryYear(Integer policeEntryYear) { this.policeEntryYear = policeEntryYear; } @Override public String toString() { return "Police{" + "policeNo=‘" + policeNo + ‘\‘‘ + ", policeName=‘" + policeName + ‘\‘‘ + ", policeAge=" + policeAge + ", policeEntryYear=‘" + policeEntryYear + ‘\‘‘ + ", policeNativePlace=‘" + policeNativePlace + ‘\‘‘ + ‘}‘; } } }
关于数值流我们在上节实例中已经做了简单说明,在流的创建过程中,有时我们并不知道流的内容,此时需要根据变化来创建流对象。
1 package com.hz; 2 3 import java.io.IOException; 4 import java.nio.charset.Charset; 5 import java.nio.file.Files; 6 import java.nio.file.Paths; 7 import java.util.ArrayList; 8 import java.util.Arrays; 9 import java.util.List; 10 import java.util.stream.Stream; 11 12 /** 13 * 我们之前创建的流都是通过一个List对象或数组 14 * 其他方式也是可以创建流的 15 */ 16 public class CreateStreamDemo { 17 public static void main(String[] args) { 18 // 1-List创建流 19 List<String> list = new ArrayList<>(); 20 Stream<String> stream = list.stream(); 21 22 // 2-数组创建流 23 String[] strings = {"Gong", "Zi", "Qi"}; 24 Stream<String> stream1 = Arrays.stream(strings); 25 26 // 3-静态方法创建流 27 Stream<String> stream2 = Stream.of("Gong", "Zi", "Qi"); 28 Stream.iterate(0, i -> i + 2).limit(10).forEach(System.out::println); 29 Stream<Object> stream4 = Stream.generate(() -> "GongZiQi"); 30 //说明: iterate 和 generate 在生成流是需要注意截取,它们都可以做无限流的生成 如下 31 // Stream.iterate(0, i -> i + 2).forEach(System.out::println); //生成所有偶数 注意 32 // Stream.generate(Math::random).forEach(System.out::println); //生成所有随机数 0~1之间 注意 33 34 // 4-文件生成流 35 try { 36 Stream<String> stream3 = Files.lines(Paths.get("data.txt"), Charset.defaultCharset()); 37 } catch (IOException e) { 38 e.printStackTrace(); 39 } 40 } 41 }
标签:his object 切片 port import 优化 cto 跳过 sre
原文地址:https://www.cnblogs.com/chuanqi1415583094/p/12168166.html