宁金诚信建设网站,网站盈利模式分析怎么做,小学学校网站设计模板,淘宝网站建设方式1.Stream流由来 首先我们应该知道#xff1a;Stream流的出现#xff0c;主要是用在集合的操作上。在我们日常的工作中#xff0c;经常需要对集合中的元素进行相关操作。诸如#xff1a;增加、删除、获取元素、遍历。 最典型的就是集合遍历了。接下来我们先举个例子来看看 J…1.Stream流由来 首先我们应该知道Stream流的出现主要是用在集合的操作上。在我们日常的工作中经常需要对集合中的元素进行相关操作。诸如增加、删除、获取元素、遍历。 最典型的就是集合遍历了。接下来我们先举个例子来看看 JDK8 Stream流式操作出现之前我们对集合操作的过程从中来了解一下 JDK8 之前集合操作数据的弊端。 Demo现在有一个List集合集合中有如下数据张无忌、周芷若、杨逍、张强、张三丰、赵敏 public static void main(String[] args) {ListString list new ArrayList();Collections.addAll(list,张无忌,周芷若,杨逍,张强,张三丰,赵敏);/*** 需求* 1.拿到所有姓张的名字* 2.拿到长度为3个字的名字* 3.将最终结果进行打印*///JDK8 以前遍历操作集合for (String name : list) {if(name.startsWith(张) name.length() 3){System.out.println(name);}}//JDK8 以后使用Stream()流遍历操作集合/**************3.使用 Stream流来操作******************/list.stream().filter(name.startsWith(张) name-name.length()3).forEach(name- System.out.println(111------name));} 使用stream流式操作直接阅读代码的字面意思即可完美展示无关逻辑方式的语义①获取流 ② 过滤姓张 ③过滤长度为3 ④遍历打印。我们真正要做的事情内容便能够被更好的体现在代码中。
2.Stream流式思想 注意Stream流 和 IO 流(InputStream/OutputStream)没有任何关系请暂时忘记对传统IO流的固有印象。 Stream流式思想类似于工厂车间的生产流水线Stream流不是一种数据结构不会保存数据而是对数据进行加工处理。Stream 可以看做是流水线上的一个工序。在流水线上通过多个工序让一个原材料加工成一个商品。 3.获取Stream流的两种方式
java.util.stream.StreamT 是 JDK8 新加入的流接口。获取一个流非常简单有以下两种常用的方式 1.所有的 Collection 集合都可以通过 .stream() 方法来获取流
2.使用 Stream 接口的 .of() 静态方法可以获取流。 public static void main(String[] args) {//方式1根据Collection获取流//Collection接口中有一个默认的方法:default StreamE stream()//1.List获取流ListString list new ArrayList();StreamString stream01 list.stream();//2.Set获取流SetString set new HashSet();StreamString stream02 set.stream();//3.Map获取流//Map 并没有继承自 Collection 接口,所有无法通过该 map.stream()获取流。但是可用通过如下三种方式获取:MapString,String map new HashMap();StreamString stream03 map.keySet().stream();StreamString stream04 map.values().stream();ListMap.EntryString, String collect map.entrySet().stream().collect(Collectors.toList());StreamMap.EntryString, String stream map.entrySet().stream();//方式2Stream中的静态方法of获取流// staticT StreamT of(T... values)// T... values:可变参数实际原理就是可变数组(传递String数组进去)//1.字符串获取流StreamString stream06 Stream.of(aa, bb, cc);//2.数组类型(基本类型除外)String[] strs {aa,bb,cc};StreamString stream07 Stream.of(strs);//3.基本数据类型的数组int[] arr {1,2,3,4};//看着没报错但是看到返回值是 int[],这是 Stream流把整个数组看做一个元素来操作而不是操作数组中的int元素(这样子是不行的!!!)Streamint[] stream08 Stream.of(arr);}
4.Stream流常用方法 Stream流模型的操作很丰富这里介绍一些常用的API。这些方法可以被分成两种类型 终结方法返回值类型不再是 Stream 类型的方法不再支持链式调用。本小节中终结方法包括 count() 和 forEach() 方法非终结方法又叫函数拼接方法。值返回值类型仍然是 Stream 类型的方法支持链式调用除了终结方法外其与方法均为非终结方法
5.Stream流使用注意事项 Stream流只能操作一次
Stream方法返回的是新的流
Stream不调用终止方法中间的操作不会执行。 6.Stream流常用方法 提醒以下所有代码部分能简化部分尽量简化均使用最简格式 1.forEach
void forEach(Consumer? super T action); forEach() 方法用来遍历流中的数据是一个终结方法。该方法接收一个 Consumer 接口函数会将每一个流元素交给该函数进行处理。示例如下
public class StreamDemo{public static void main(String[] args){ListString list new ArrayList();Collections.addAll(list,Mary,Lucy,James,Johson,Steve);//forEach()遍历//未简写//list.forEach((String str)-{// System.out.println(str);//});//简写1//list.forEach(str- System.out.println(str));//最终简写list.forEach(System.out::println);}
}
测试结果 2.count long count(); count() 方法用来统计集合中的元素个数是一个终结方法。该方法返回一个 long 值代表元素个数示例如下 public static void main(String[] args) {ListString list new ArrayList();Collections.addAll(list, Mary, Lucy, James, Johson, Steve);//count()计算集合中元素个数long count list.stream().count();System.out.println(元素个数为: count);} 3.filter
StreamT filter(Predicate? super T predicate);
filter() 方法用于过滤数据返回符合过滤条件的数据是一个非终结方法。我们可以通过 filter() 方法将一个流转换成另一个子集流。该接口接收一个 Predicate 函数式接口参数(可以是一个 Lambda 或 方法引用) 作为筛选条件。 public static void main(String[] args) {ListString list new ArrayList();Collections.addAll(list,Mary,Lucy,James,Johson,Steve);//filter()过滤,返回以J开头的名字list.stream().filter(str-str.startsWith(J)).forEach(System.out::println);//写法二list.stream().filter(str-{if (str.startsWith(J)){return true;}return false;}).forEach(System.out::println);} 测试结果
4.limit
StreamT limit(long maxSize); limit() 方法用来对 Stream 流中的数据进行截取只取用前 n 个是一个非终结方法。参数是一个 long 型如果集合当前长度大于参数则进行截取否则不进行操作。因为 limit() 是一个非终结方法所以必须调用终止方法。示例如下 public static void main(String[] args) {ListString list new ArrayList();Collections.addAll(list, Mary, Lucy, James, Johson, Steve);//limit()截取,截取list集合前三个元素list.stream().limit(3).forEach(System.out::println);} 5.skip 如果希望跳过前几个元素去取后面的元素则可以使用 skip()方法获取一个截取之后的新流它是一个非终结方法。参数是一个 long 型如果 Stream 流的当前长度大于 n则跳过前 n 个否则将会得到一个长度为 0 的空流。因为 limit() 是一个非终结方法所以必须调用终止方法。示例如下
StreamT skip(long n); public static void main(String[] args) {ListString list new ArrayList();Collections.addAll(list,Mary,Lucy,James,Johson,Steve);//skip()跳过list集合前2个元素,获取剩下的元素list.stream().skip(2).forEach(System.out::println);}备注使用 skip() 和 limit() 方法即可实现类似分页的操作了。示例如下 //一页10条 分页操作//第一页skip(0).limit(10)//第二页skip(10).limit(10)//第三页skip(20).limit(10)...
6.map
R StreamR map(Function? super T, ? extends R mapper); map() 方法可以将流中的元素映射到另一个流中。即可以将一种类型的流转换为另一种类型的流(区别map返回的是指定类型(比如int)而flatMap返回的还是一个Stream流)map() 方法是一个非终结方法。该接口需要一个 Function 函数式接口参数可以将当前流中的T类型数据转换为另一种R类型的流。 这个方法有三个对于原始类型的变种方法分别是mapToIntmapToLong 和 mapToDouble。这三个方法也比较好理解比如 mapToInt 就是把原始 Stream 转换成一个新的 Stream这个新生成的 Stream 中的元素都是 int 类型。之所以会有这样三个变种方法可以免除自动装箱/拆箱的额外消耗。参考本文 15 mapToInt/mapToLong/mapToDouble 因为 map() 方法是一个非终结方法所以必须调用终止方法。通过如下示例使用 map() 方法通过方法引用便将字符串类型转换成了 Integer 类型。示例如下 public static void main(String[] args) {ListString list new ArrayList();Collections.addAll(list, 11, 22, 33, 44, 55);//通过map()方法,可以将String类型的流转换为int类型的流/*list.stream().map((String str)-{return Integer.parseInt(str);}).forEach((Integer num) - {System.out.println(num);});*///简化://list.stream().map(str-Integer.parseInt(str)).forEach(str-System.out.println(str));//简化后:list.stream().map(Integer::parseInt).forEach(System.out::println);} 7.flatMap
R StreamR flatMap(Function? super T, ? extends Stream? extends R mapper);
flatMap 的使用同 map 类似。map只是一维 1对1 的映射返回的是指定的类型 而flatMap返回的则还是一个Stream流可以对其进行进一步操作。(区别map返回的是指定类型(比如int)而flatMap返回的还是一个Stream流) 我的理解为假如你的集合流中包含子集合(或者需要更深进一步操作)那么使用 flatMap 可以返回该子集合的集合流。示例代码如下所示
public class Province {private String name;private ListString city;//get/set 方法
}public class flatMapDemo{public static void main(String[] args) {ListProvince provinceList new ArrayList();ListString bjCityList new ArrayList();bjCityList.add(海淀);bjCityList.add(朝阳);ListString shCityList new ArrayList();shCityList.add(黄埔);shCityList.add(闵行);Province bjProvince new Province();bjProvince.setName(北京);bjProvince.setCity(bjCityList);provinceList.add(bjProvince);Province shProvince new Province();shProvince.setName(上海);shProvince.setCity(shCityList);provinceList.add(shProvince);//使用map,需要多次forEachprovinceList.stream().map(str-str.getCity()).forEach(cityList - cityList.forEach(System.out::println));System.out.println(----------);//使用 flatMapprovinceList.stream().flatMap(str-str.getCity().stream()).forEach(System.out::println);}
} 测试结果
8.sorted
sorted() 方法可以用来对 Stream 流中的数据进行排序。sorted()方法共有以上两种情况 //根据元素的自然规律排序StreamT sorted();//根据比较器指定的规则排序StreamT sorted(Comparator? super T comparator); 因为 sorted() 方法是一个非终结方法所以必须调用终止方法。 场景①sorted() 方法按照自然规律默认为升序排序。 ②sorted(Comparator comparator) 方法按照指定的比较器规则排序以降序为例。 示例如下 public static void main(String[] args){//sorted()根据元素的自然规律排序StreamInteger stream01 Stream.of(66,33,11,55);stream01 .sorted().forEach(System.out::println);System.out.println( ----- );//sorted(Comparator? super T comparator):根据比较器规则降序排序StreamInteger stream02 Stream.of(66,33,11,55);stream02 .sorted((i1,i2)- i2-i1).forEach(System.out::println);}9.distinct
distinct() 方法可以用来去除重复数据。因为 distinct() 方法是一个非终结方法所以必须调用终止方法。 去除重复数据此处有几种情况①基本类型去重 ②String类型去重 ③引用类型去重(对象去重) ①②使用 distinct() 方法可以直接去重 ③对象类型需要重写 equals() 和 hasCode() 方法使用 distinct() 方法才能去重成功。示例如下
public static void main(String[] args){//基本类型去重StreamInteger stream01 Stream.of(66,33,11,55,33,22,55,66);stream01 .distinct().forEach(System.out::println);//字符串去重StreamString stream02 Stream.of(AA,BB,AA);stream02.distinct().forEach(System.out::println);//自定义对象去重//(Person对象类,有String name,Integer age 两个属性,两参数构造器,get/set()方法,重写了equals(),hashCode(),toString()方法。此处就不附Person实体类了)BiFunctionString,Integer,Person fn1 Person::new;StreamPerson stream14 Stream.of(fn1.apply(西施, 18), fn1.apply(貂蝉, 20), fn1.apply(王昭君, 22), fn1.apply(杨玉环, 23), fn1.apply(杨玉环, 23));stream14.distinct().forEach(System.out::println);} 测试结果 6633115522----AABB----Person{name西施, age18}Person{name貂蝉, age20}Person{name王昭君, age22}Person{name杨玉环, age23}
10.match
//allMatch 全匹配(匹配所有,所有元素都需要满足条件--返回true)
boolean allMatch(Predicate? super T predicate);
//anyMatch 匹配某个元素(只要有一个元素满足条件即可--返回true)
boolean anyMatch(Predicate? super T predicate);
//noneMatch 匹配所有元素(所有元素都不满足指定条件--返回true)
boolean noneMatch(Predicate? super T predicate); match() 方法可以用来判断 Stream 流中的数据是否匹配指定的条件。allMatch()、anyMatch()、noneMatch() 方法都是终结方法返回值为 bollean。示例如下 public static void main(String[] args){StreamInteger stream01 Stream.of(5, 3, 6, 1);boolean allMatch stream01.allMatch(i - i 0);System.out.println(allMatch匹配:allMatch);StreamInteger stream02 Stream.of(5, 3, 6, 1);boolean anyMatch stream02 .anyMatch(i - i 5);System.out.println(anyMatch匹配:anyMatch);StreamInteger stream03 Stream.of(5, 3, 6, 1);boolean noneMatch stream03 .noneMatch(i - i 3);System.out.println(noneMatch匹配:noneMatch);} 11.max / min OptionalT max(Comparator? super T comparator);OptionalT min(Comparator? super T comparator); max() 和 min() 方法用来获取 Stream 流中的最大值和最小值。该接口需要一个 Comparator 函数式接口参数根据指定排序规则来获取最大值最小值。 为了保证数据的准确性此处排序规则需要是升序排序。因为max() 方法获取的是排序后的最后一个值min() 方法获取的是排序后的第一个值。如果使用降序排序后那么 max() 和 min() 方法就相反了就有异常了。示例如下 public static void main(String[] args){//max()StreamInteger stream01 Stream.of(33, 11, 22, 5);OptionalInteger max stream01.max((i1, i2) - i1 - i2);System.out.println(最大值:max.get());//min()StreamInteger stream02 Stream.of(33, 11, 22, 5);OptionalInteger min stream02.min((i1, i2) - i1 - i2);System.out.println(最小值:min.get());}
测试结果 12.reduce
//1.
OptionalT reduce(BinaryOperatorT accumulator);
//2.
T reduce(T identity, BinaryOperatorT accumulator);
//3.
U U reduce(U identity,BiFunctionU, ? super T, U accumulator,BinaryOperatorU combiner); 如果需要将 Sream 流中的所有数据归纳得到一个数据的情况可以使用 reduce() 方法。如果需要对 Stream 流中的数据进行求和操作、求最大/最小值等(都是归纳为一个数据的情况)此处就可以用到 reduce() 方法。示例如下 public static void main(String[] args){//reduce():求和操作StreamInteger stream01 Stream.of(4,3,5,6);Integer sum stream01.reduce(0,(x,y)- x y);System.out.println(求和:sum);//reduce():求最大值操作StreamInteger stream03 Stream.of(4,3,5,6);Integer max stream03.reduce(0,(x,y)- x y ? x : y);System.out.println(最大值为:max);//reduce():求最小值操作StreamInteger stream02 Stream.of(4,3,5,6);OptionalInteger max1 stream02.reduce((x, y)- x y ? x : y);System.out.println(最小值为:max1.get());} 测试结果 结果分析(求和分析) 求和流程 第一次将默认值赋值给x取出集合第一个元素赋值给y 第二步将上一次返回的结果赋值给x取出集合第二个元素赋值给y 第三步:继续执行第二步(如下图所示) 13.map 和 reduce 方法组合使用 map() 和 reduce() 方法组合使用可以解决很多日常工作中遇到的问题。我们就从如下场景了解 场景一现在有一个 Person 类有两个属性name 和 age新建四个 Person类然后完成如下操作① 求出所有年龄的总和 ②求出 Person 类中的最大年龄 public static void main(String[] args){BiFunctionString,Integer,Person fn2 Person::new;//1.求出所有年龄的总和(年龄为int值,默认为0,此处可以使用待默认值的reduce()方法)StreamPerson stream01 Stream.of(fn2.apply(刘德华, 58), fn2.apply(张学友, 56), fn2.apply(郭富城, 54), fn2.apply(黎明, 52));//基本写法//Integer total stream01.map(p - p.getAge()).reduce(0,(x, y) - x y);//(方法引用)简化后Integer total stream01.map(p - p.getAge()).reduce(0,Integer::sum);System.out.println(年龄总和为:total);//2.找出最大年龄StreamPerson stream02 Stream.of(fn2.apply(刘德华, 58), fn2.apply(张学友, 56), fn2.apply(郭富城, 54), fn2.apply(黎明, 52));//基本写法 //Integer maxAge stream02.map(p - p.getAge()).reduce(0, (x, y) - x y ? x : y);//(方法引用)简化后Integer maxAge stream02.map(p - p.getAge()).reduce(0, Integer::max);System.out.println(最大年龄为:maxAge);} 测试结果 年龄总和为:220最大年龄为:58 场景二统计字符串 a 出现的次数 public static void main(String[] args){StreamString stream03 Stream.of(a, b, c, d, a, c, b, a);//map() 和 reduce() 方法组合使用Integer aTotal stream03.map(str - {if (str a) {return 1;} else {return 0;}}).reduce(0, Integer::sum);System.out.println(a次数:aTotal);} 14.mapToInt / mapToDouble / mapToLong
//mapToInt()
IntStream mapToInt(ToIntFunction? super T mapper);
//mapToLong()
LongStream mapToLong(ToLongFunction? super T mapper);
//mapToDouble()
DoubleStream mapToDouble(ToDoubleFunction? super T mapper); 我们通过 StreamInteger stream Stream.of(1,2,3,4,5); 这种方式返回值为 StreamInteger 这种包装类的泛型这种方式虽然用起来没有问题但是它在效率上还是存在着一定的问题。 当我们将一对数字转成 Stream 流时因为泛型的原因只能使用 Integer 包装类。会先把这些数字包装成 Integer 类
//1.Integer是一个类占用的内存肯定比 int 大
//2.Stream流在操作时会存在自动装箱和拆箱操作
StreamInteger stream Stream.of(2,3,5,6,7);//把大于3的打印出来(num在Stream流中是Integer类型在与3比较时显然会存在自动拆装箱问题)效率会有影响
stream.filter(num - num 3).forEach(System.out::println); 所以在 JDK8 中对 Stream 流还新增了一个 mapToInt()方法。该方法可以将流中操作的 Integer 包装类在 Stream 流中转换成直接来操作 int 类型效率明显会高一点。
示例如下 public static void main(String[] args){//使用 mapToInt()方法IntStream intStream Stream.of(1, 2, 3, 4, 5, 6).mapToInt((Integer num) - {return num.intValue();});//(使用方法引用)简化后IntStream intStream1 Stream.of(1, 2, 3, 4, 5, 6).mapToInt(Integer::intValue);intStream1.filter(n-n3).forEach(System.out::println);/*** 使用mapToInt(),返回值是一个IntStream类型.我们看一下它们的继承结构图(如下所示)* IntStream 和 StreamInteger 类型进行比较。发现他们都继承自 BaseStream。所以它们区别不大* 只不过 IntStream 内部操作的是 int 基本类型的数据省去自动拆装箱过程。从而可以节省内存开销*/} 继承结构图
提示 mapToDouble() / mapToLong() 的使用与 mapToInt()一致此处不再介绍。
15.concat
public static T StreamT concat(Stream? extends T a, Stream? extends T b) {Objects.requireNonNull(a);Objects.requireNonNull(b);SuppressWarnings(unchecked)SpliteratorT split new Streams.ConcatSpliterator.OfRef((SpliteratorT) a.spliterator(), (SpliteratorT) b.spliterator());StreamT stream StreamSupport.stream(split, a.isParallel() || b.isParallel());return stream.onClose(Streams.composedClose(a, b));
} concat() 方法可以将两个Stream流合并成一个流进行返回。如果是三个流则需要两两合并不能一次性合并三个流。concat() 方法是 Stream 接口的静态方法我们可以直接使用【类名.方法名】调用。
注意concat() 方法此处接收的是 Stream 类型不能接收 IntStream 等类型。concat() 是一个静态方法与 java.lang.String 中的 concat() 方法是不同的。 public static void main(String[] args){//concat()方法StreamInteger aStream Stream.of(1, 2, 3);StreamInteger bStream Stream.of(4, 5, 6);StreamInteger concatStream Stream.concat(aStream, bStream);concatStream.forEach(System.out::println);} 测试结果
16.peek
介绍该方法会生成一个包含原 Stream 的所有元素的新 Stream同时会提供一个消费函数Consumer实例新Stream每个元素被消费的时候都会执行给定的消费函数
存在此方法的目的主要是为了在您需要的地方支持调试查看元素流过管道中特定点的情况
主要用于开发过程中调试使用 public static void main(String[] args){ListString list Stream.of(one, two, three, four).filter(e - e.length() 3).peek(e - System.out.println(大于三--- e)).map(String::toUpperCase).peek(e - System.out.println(转大写--- e)).collect(Collectors.toList());} 17.allMatch / anyMatch / noneMatch 匹配相关
这三个方法均返回 boolean 类型 allMatch是不是Stream中的所有元素都满足给定的匹配条件
anyMatchStream中是否存在任何一个元素满足匹配条件
noneMatch是不是Stream中的所有元素都不满足给定的匹配条件 public static void main(String[] args) {
// Stream中元素所有元素长度都2boolean flag Stream.of(one, two, three, four).allMatch(str - str.length() 2);System.out.println(flag); // 返回值:true// Stream中元素是不是存在任何一个元素长度4boolean flag1 Stream.of(one, two, three, four).anyMatch(str - str.length() 4);System.out.println(flag1); // 返回值:true// Stream中元素所有元素长度没有一个元素1boolean flag2 Stream.of(one, two, three, four).noneMatch(str - str.length() 1);System.out.println(flag2); // 返回值:true} 18.findFirst / findAny findFirst返回Stream中的第一个元素如果Stream为空返回空Optional
findAny返回的元素是不确定的对于同一个列表多次调用findAny()有可能会返回不同的值。使用findAny()是为了更高效的性能。如果是数据较少串行地情况下一般会返回第一个结果如果是并行的情况那就不能确保是第一个public static void main(String[] args) {OptionalString first Stream.of(one, two, three, four).findFirst();System.out.println(first.get());OptionalString any Stream.of(one, two, three, four).findAny();System.out.println(any.get());OptionalString any1 Stream.of(one, two, three, four).parallel().findAny();System.out.println(any1.get());} 19.collect
collect() 方法的使用也有很多内容学习此处内容过多不做一一列举。 如需了解 Stream 流 collect() 方法的使用介绍你可以看博主下一文章学习了解。请点击如下链接跳转JDK8新特性(二)Stream流 collect() 方法的详细使用介绍