微信推广和网站推广哪个好,南京发布最新通报,如何快速进行网站开发,网站建设请款报告通过前面几篇文章的学习#xff0c;大家应能掌握几种容器类型的常见用法#xff0c;对于简单的增删改和遍历操作#xff0c;各容器实例都提供了相应的处理方法#xff0c;对于实际开发中频繁使用的清单List#xff0c;还能利用Arrays工具的asList方法给清单对象做初始化赋…通过前面几篇文章的学习大家应能掌握几种容器类型的常见用法对于简单的增删改和遍历操作各容器实例都提供了相应的处理方法对于实际开发中频繁使用的清单List还能利用Arrays工具的asList方法给清单对象做初始化赋值另外提供了专门的Collections工具进行排序、求最大元素、求最小元素等操作。那么涉及到更加复杂的数据处理游荡如何有针对性地筛选和进一步加功能依次遍历目标容器对所有元素逐个加以分析判断并酌情将具体数据调整至满意的状态这种千篇一律的业务流程固然能够解决问题可惜由此带来的副作用是显而易见的包括但不限于代码冗长、分支众多、逻辑繁琐、不易重用等等。为了改进相关业务逻辑的编程方式帮助开发者形成良好的编码风格Java的每次版本更新都试图给出有效的解决方案其中影响深远的当数Java8推出的两项新特性新增的泛型接口与流式处理。关于前一个泛型接口特性用于容器操作的泛型接口主要有三个分别是断言接口、消费接口和函数接口有关的应用案例可参见之前的泛型接口文章这里不再赘述。真正具有革命性意义的才是本文的主角——流式处理。所谓流隐含着流水线的意思也就是由开发者事先设定一批处理指令说明清楚每条指令的前因后果然后启动流水线作业即可得到最终的处理结果。流式处理的精髓在于一气呵成只要万事俱备决不拖泥带水。开展流式处理主要包括三个步骤获得容器的流对象、设置流的各项筛选和加工指令以及规划处理结果的展示形式。下面就分别予以详细介绍。1、获得容器的流对象Java8给每种容器都准备了两条流水线一条是串行流另一条是并行流。串行流顾名思义各项任务是前后串在一起的只有处理完前一项任务才能继续执行后一项任务。调用容器实例的stream方法即可获得该容器的串行流对象而调用容器实例的parallelStream方法可获得该容器的并行流对象。流对象的获取操作同时也是流式处理的开始指令每次进行流式处理之前都必须先获取当前容器的流对象要么获取串行流要么获取并行流。2、设置流的各项筛选和加工指令不管是串行流还是并行流它们承载的都是容器内部的原始数据这些原材料要经过各道加工工序之后才会得到具备初步形态的半成品。加工数据期间所调用的流方法说明如下filter按照指定条件过滤。即筛选出符合条件的那部分数据。sorted根据指定字段对所有记录排序。可选择升序或者降序。map映射成指定的数据类型。limit只取前面若干条数据。distinct去掉重复记录。保证每条记录都是唯一的。以上的加工方法属于流式处理的中间指令每次流水线作业都允许设置一条或者多条中间指令。3、规划处理结果的展示形式前一步的各项加工处理完毕还要弄个包装才能输出最终的成品也就是这条流水线生产出来的数据到底长什么模样。结果数据的记录包装有三种形式分别对应如下的三个方法count统计结果数据的数量。forEach依次遍历结果数据并逐条进行个性化处理。collect搜集和整理结果数据并返回指定格式的清单记录。上面的三个包装方法属于流式处理的结束指令每次流水线作业必须配备有且仅有其中的一条结束指令。接下来列举几个实际应用的业务场景看看采取流式处理时该如何编码。首先准备一个原始的苹果清单后续将对这个苹果清单发动流水作业。原始清单的获取代码示例如下// 获取默认的苹果清单private static ArrayList getAppleList() {ArrayList appleList new ArrayList();appleList.add(new Apple(红苹果, RED, 150d, 10d));appleList.add(new Apple(大苹果, green, 250d, 10d));appleList.add(new Apple(红苹果, red, 300d, 10d));appleList.add(new Apple(大苹果, yellow, 200d, 10d));appleList.add(new Apple(红苹果, green, 100d, 10d));appleList.add(new Apple(大苹果, Red, 250d, 10d));return appleList;}然后需要统计红苹果总数的话可通过下列的流式代码开展统计操作// 统计红苹果的总数long redCount getAppleList().stream() // 串行处理.filter(Apple::isRedApple) // 过滤条件。专门挑选红苹果.count(); // 统计记录个数System.out.println(红苹果总数 redCount);注意到上述代码的filter方法内部出现了方法引用的确流式处理的主要方法都预留了函数式接口的调用所以经常会在流式代码中看到五花八门的方法引用与Lambda表达式。比如下面的结果遍历代码就在forEach方法中填充了Lambda表达式// 对每个红苹果依次进行处理getAppleList().stream() // 串行处理.filter(Apple::isRedApple) // 过滤条件。专门挑选红苹果.forEach(s - System.out.println(当前颜色为s.getColor())); // 逐条开展操作当然流水作业更常见的输出另一串清单数据此时流式处理的结束指令就得采用collect方法。下面便是从原始清单中挑出红苹果清单的流式代码// 挑出红苹果清单List redAppleList getAppleList().stream() // 串行处理//.parallelStream() // 并行处理.filter(Apple::isRedApple) // 过滤条件。专门挑选红苹果.sorted(Comparator.comparing(Apple::getWeight)) // 按苹果重量升序排列//.sorted(Comparator.comparing(Apple::getWeight).reversed()) // 按苹果重量降序排列.limit(3) // 只取前几条数据.distinct() // 去掉重复记录.collect(Collectors.toList()); // 返回一串清单System.out.println(红苹果清单 redAppleList.toString());结果清单可能不需要完整的苹果信息只需列出苹果名称字段那么得调用map方法把完整的苹果信息映射为单个的名称字段。此时的筛选代码变成下面这样// 挑出去重后的苹果名称清单List allNameList getAppleList().stream() // 串行处理.map(Apple::getName) // 映射成新的数据类型.distinct() // 去掉重复记录.collect(Collectors.toList()); // 返回一串清单System.out.println(苹果名称去重后的清单 allNameList.toString());除了普通的清单collect方法还能返回分组清单也就是把结果数据按照某种条件进行分组再统计每个分组的成员数目。仍以苹果清单为例红苹果可通过名称或者产地分组分组的同时计算每个小组里各有多少粒苹果。于是形成了以下的分组计数代码// 按照名称统计红苹果的分组个数Map redStatisticCount getAppleList().stream() // 串行处理.filter(Apple::isRedApple) // 过滤条件。专门挑选红苹果.collect(Collectors.groupingBy(Apple::getName, Collectors.counting())); // 返回分组计数System.out.println(红苹果分组计数 redStatisticCount.toString());分组计数仅仅是简单统计各组的成员数量有时还想单独计算某个字段的统计值比如每个小组里的苹果总价各是多少这时collect方法必须同时完成两项任务第一项要根据某种条件分组第二项要对各组的苹果价格求和如此改造之后的分组求和代码如下所示// 按照名称统计红苹果的分组总价Map redPriceSum getAppleList().stream() // 串行处理.filter(Apple::isRedApple) // 过滤条件。专门挑选红苹果.collect(Collectors.groupingBy(Apple::getName, Collectors.summingDouble(Apple::getPrice))); // 返回分组并对某字段求和System.out.println(红苹果分组总价 redPriceSum.toString());观察以上的具体案例发现流式处理的代码相当连贯每个步骤该做什么事情都一清二楚中间没有许多繁复的流程控制唯有一条条分工明确的处理指令同时充分发挥了方法引用及Lambda表达式的便利性使得原本令人头痛的容器加工变成了有章可循的流水线作业从而极大地提高了开发者的编码效率。