当前位置: 首页 > news >正文

Java8实战-总结22

Java8实战-总结22

  • 使用流
    • 数值流
      • 原始类型流特化
      • 数值范围
      • 数值流应用:勾股数

使用流

数值流

可以使用reduce方法计算流中元素的总和。例如,可以像下面这样计算菜单的热量:

int calories = menu.stream().map(Dish::getcalories).reduce(0, Integer::sum);

这段代码的问题是,它有一个暗含的装箱成本。每个Integer都必须拆箱成一个原始类型,再进行求和。要是可以直接像下面这样调用sum方法,效果会更好:

int calories = menu.stream().map(Dish::getcalories).sum();

但这是不可能的。问题在于map方法会生成一个Stream<T>。虽然流中的元素是Integer类型,但Streams接口没有定义sum方法。Stream API提供了原始类型流特化,专门支持处理数值流的方法。

原始类型流特化

Java 8引入了三个原始类型特化流接口来解决这个问题:IntStreamDoubleStreamLongStream,分别将流中的元素特化为intlongdouble,从而避免了暗含的装箱成本。每个接口都带来了进行常用数值归约的新方法,比如对数值流求和的sum,找到最大元素的max。此外还有在必要时再把它们转换回对象流的方法。要记住的是,这些特化的原因并不在于流的复杂性,而是装箱造成的复杂性——即类似intInteger之间的效率差异。

  1. 映射到数值流

将流转换为特化版本的常用方法是mapToIntmapToDoublemapToLong。这些方法和前面说的map方法的工作方式一样,只是它们返回的是一个特化流,而不是stream<T>。例如,可以像下面这样用mapToIntmenu中的卡路里求和:

int calories = menu.stream().mapToInt(Dish::getcalories)//返回一个IntStream.sum();//返回一个Stream<Dish>

这里,mapToInt会从每道菜中提取热量(用一个Integer表示),并返回一个IntStream(而不是一个Stream<Integer>)。然后就可以调用IntStream接口中定义的sum方法,对卡路里求和了!请注意,如果流是空的,sum默认返回0IntStream还支持其他的方便方法,如maxminaverage等。

  1. 转换回对象流

同样,一旦有了数值流,也可以把它转换回非特化流。例如,IntStream上的操作只能产生原始整数:IntStreammap操作接受的Lambda必须接受int并返回int(一个IntUnaryoperator)。但是可能想要生成另一类值,比如Dish。为此,需要访问stream接口中定义的那些更广义的操作。要把原始流转换成一般流(每个int都会装箱成一个Integer),可以使用boxed方法,如下所示:
将Stream转

IntStream intStream = menu.stream().mapToInt(Dish::getcalories);//将Stream转换为数值流
Stream<Integer> stream = intStream.boxed();//将数值流转换为Stream

在需要将数值范围装箱成为一个一般流时,boxed尤其有用。

  1. 默认值optionalInt

求和的例子很容易,因为它有一个默认值:0。但是,如果要计算IntStream中的最大元素,就得换个法子了,因为0是错误的结果。如何区分没有元素的流和最大值真的是0的流呢?前面介绍了optional类,这是一个可以表示值存在或不存在的容器。Optional可以用IntegerString等参考类型来参数化。对于三种原始流特化,也分别有一个optional原始类型特化版本:optionalIntoptionalDoubleoptionalLong
例如,要找到IntStream中的最大元素,可以调用max方法,它会返回一个optionalInt:

OptionalInt maxCalories = menu.stream().mapToInt(Dish::getcalories).max();

现在,如果没有最大值的话,就可以显式处理optionalInt去定义一个默认值了:

int max = maxCalories.orElse(1);如果没有最大值的话,显式提供一个默认最大值

数值范围

和数字打交道时,有一个常用的东西就是数值范围。比如,假设想要生成1和100之间的所有数字。Java 8引入了两个可以用于IntStreamLongStream的静态方法,帮助生成这种范围:rangerangeClosed。这两个方法都是第一个参数接受起始值,第二个参数接受结束值。但range是不包含结束值的,而rangeClosed则包含结束值。例子:

//表示范围[1,100]
IntStream evenNumbers = IntStream.rangeclosed(1, 100).filter(n -> n % 2 == 0);//一个从1到100的偶数流System.out.println(evenNumbers.count());//从1到100有50个偶数

这里用了rangeClosed方法来生成1100之间的所有数字。它会产生一个流,然后可以链接filter方法,只选出偶数。到目前为止还没有进行任何计算。最后,对生成的流调用count。因为count是一个终端操作,所以它会处理流,并返回结果50,这正是1100(包括两端)中所有偶数的个数。请注意,比较一下,如果改用IntStream.range(1, 100),则结果将会是49个偶数,因为range是不包含结束值的。

数值流应用:勾股数

现在来看一个难一点儿的例子。

  1. 勾股数

某些三元数(a,b,c)满足公式a * a + b * b = c * c,其中a、b、c都是整数。例如,(3, 4, 5)就是一组有效的勾股数,因为3 * 3 + 4 * 4 = 5 * 59 + 16 = 25。这样的三元数有无限组。例如,(5 , 12, 13)(6, 8, 10)(7, 24, 25)都是有效的勾股数。勾股数很有用,因为它们描述的正好是直角三角形的三条边长,如下图所示:
在这里插入图片描述

  1. 表示三元数

第一步是定义一个三元数。虽然更恰当的做法是定义一个新的类来表示三元数,但这里可以使用具有三个元素的int数组,比如new int[]{3, 4, 5},来表示勾股数(3, 4, 5)。现在就可以用数组索引访问每个元素了。

  1. 筛选成立的组合

假定提供了三元数中的前两个数字:ab。怎么知道它是否能形成一组勾股数呢?需要测试a * a + b * b的平方根是不是整数,也就是说它没有小数部分——在Java里可以使用expr % 1表示。如果它不是整数,那就是说c不是整数。可以用filter操作表达这个要求:

filter(b -> Math.sqrt(a * a + b * b) % 1 == 0)

假设周围的代码给a提供了一个值,并且stream提供了b可能出现的值,filter将只选出那些可以与a组成勾股数的bMath.sqrt(a * a + b * b) %1 == 0这一行是一种测试Math.sqrt(a * a + b * b)返回的结果是不是整数的方法。如果平方根的结果带了小数,这个条件就不成立。

  1. 生成三元组

在筛选之后,知道ab能够组成一个正确的组合。现在需要创建一个三元组。可以使用map操作,像下面这样把每个元素转换成一个勾股数组:

stream.filter(b -> Math.sqrt(a*a + b*b) % 1 == 0).map(b -> new int[]{a, b, (int)Math.sqrt(a*a + b*b)});
  1. 生成b值

现在需要生成b的值。前面已经看到,Stream.rangeClosed可以在给定区间内生成一个数值流。可以用它来给b提供数值,这里是1100:

IntStream.rangeClosed(1, 100).filter(b -> Math.sqrt(a*a + b*b) % 1 == 0).boxed().map(b -> new int[]{a, b, (int)Math.sqrt(a*a + b*b)});

filter之后调用boxed,从rangeClosed返回的IntStream生成一个Stream<Integer>。这是因为map会为流中的每个元素返回一个int数组。而IntStream中的map方法只能为流中的每个元素返回另一个int,这不是想要的。可以用IntStreammapToObj方法改写它,这个方法会返回一个对象值流:

IntStream.rangeClosed(1, 100).filter(b -> Math.sqrt(a*a + b*b) % 1 == 0).mapToobj(b -> new int[]{a, b, (int)Math.sqrt(a*a + b*b)});

6 . 生成值

这里有一个关键的假设:给出了a的值。 现在,只要已知a的值,就有了一个可以生成勾股数的流。就像b一样,需要为a生成数值。最终的解决方案如下所示:

Streamcint[]> pythagoreanTriples = IntStream.rangeClosed(1, 100).boxed().flatMap(a ->IntStream.rangeClosed(a, 100).filter(b -> Math.sqrt(a*a + b*b) % 1 == 0).mapToobj(b ->new int[]{a, b, (int)Math.sqrt(a * a + b* b)})
);

首先,创建一个从1100的数值范围来生成a的值。对每个给定的a值,创建一个三元数流。要是把a的值映射到三元数流的话,就会得到一个由流构成的流。flatMap方法在做映射的同时,还会把所有生成的三元数流扁平化成一个流。这样就得到了一个三元数流。还要注意,b的范围改成了a100。没有必要再从1开始了,否则就会造成重复的三元数,例如(3,4,5)(4,3,5)

  1. 运行代码

现在可以运行解决方案,并且可以利用前面的limit命令,明确限定从生成的流中要返回多少组勾股数了:

pythagoreanTriples.limit(5).forEach(t ->System.out.println(t[0] + "," + t[1] + "," + t[2]));

这会打印:

3, 4, 5
5, 12, 13
6, 8, 10
7, 24, 25
8, 15, 17
  1. 最优

目前的解决办法并不是最优的,因为要求两次平方根。让代码更为紧凑的一种可能的方法是,先生成所有的三元数(a*a, b*b, a*a + b*b),然后再筛选符合条件的:

Streamcdouble[]> pythagoreanTriples2 =IntStream.rangeClosed(1, 100).boxed().flatMap(a ->IntStream.rangeClosed(a,100).mapToObj(b -> new double[]{a, b, Math.sqrt(a*a + b*b)})//产生三元数.filter(t -> t[2] % 1 == 0));//元组中的第三个元素必须是整数

相关文章:

Java8实战-总结22

Java8实战-总结22 使用流数值流原始类型流特化数值范围数值流应用&#xff1a;勾股数 使用流 数值流 可以使用reduce方法计算流中元素的总和。例如&#xff0c;可以像下面这样计算菜单的热量&#xff1a; int calories menu.stream().map(Dish::getcalories).reduce(0, Int…...

matlab 实现点云ICP 配准算法

一、算法步骤 (1)在目标点云P中取点集pi∈P; (2)找出源点云Q中的对应点集qi∈Q,使得||qi-pi||=min; (3)计算旋转矩阵R和平移矩阵t,使得误差函数最小; (4)对pi使用上一步求得的旋转矩阵R和平移矩阵t进行旋转和平移变换,的到新的对应点集pi’={pi’=Rpi+t,pi∈P};…...

python提取word文本和word图片

提取文本 docx只支持docx格式&#xff0c;所以如果想读取doc需要另存为docx格式即可 import docx # pip3 install python-docx doc docx.Document(three.docx) for paragraph in doc.paragraphs:print(paragraph.text)提取图片 import zipfile import os, re # docx本质上…...

iOS开发Swift-9-SFSymbols,页面跳转,view屏幕比例,启动页-和风天气AppUI

1.创建项目 2.设置好测试机型,App显示名称,以及关闭横向展示. 3.下载SF Symbols. https://developer.apple.com/sf-symbols/ 右上角搜索 search ,可以找到很多系统自带图标.选择喜欢的图标,拷贝图标的名字. 插入一个Button,在Image中粘贴图标名称并选择,即可将Button变成想要的…...

代码优化工具-测试程序执行时间-IDEAdebug+StopWatch

参考&#xff1a; [技巧]IDEA的debugStopWatch监测程序运行时间 添加链接描述 1创建类StopWatchExpand import lombok.extern.slf4j.Slf4j;import org.springframework.util.StopWatch;import java.text.NumberFormat;/*** 检测程序片段运行时间拓展** author sdevil507* cr…...

力扣每日一题---2594. 修车的最少时间

文章目录 思路解题方法复杂度Code 思路 请注意&#xff0c;能力值越低&#xff0c;修车越快&#xff0c;应该翻译成「排名」&#xff0c;排名越靠前&#xff0c;修车越快。&#xff09;根据题意可以知道r * n * n < t 的&#xff0c;所以可以利用数学知识进行改变公式&#…...

【jvm】运行时数据区

目录 一、运行时数据区一、作用二、说明三、线程共用与私有区域 一、运行时数据区 一、作用 1.内存是非常重要的系统资源&#xff0c;是硬盘和CPU 的中间仓库及桥梁&#xff0c;承载着操作系统和应用程序的实时运行。JVM内存布局规定了Java在运行过程中内存申请、分配、管理的策…...

SpringMVC相对路径和绝对路径

1.相对地址与绝对地址定义 在jsp&#xff0c;html中使用的地址&#xff0c;都是在前端页面中的地址&#xff0c;都是相对地址 地址分类&#xff1a;&#xff08;1&#xff09;&#xff0c;绝对地址&#xff0c;带有协议名称的是绝对地址&#xff0c;http://www.baidu.com&…...

IIS perl python cbrother php脚本语言配置及简单测试样例程序

上篇笔记写了 IIS 配置 CGI&#xff0c; IIS CGI配置和CGI程序FreeBasic, VB6, VC 简单样例_Mongnewer的博客-CSDN博客 这篇在IIS上配置一些脚本语言。为了操作方便&#xff0c;每种语言在站点下分设文件夹。 1. IIS perl配置 Perl CGI方式是曾经流行的做法。先下载一个开源…...

Oracle Scheduler中日期表达式和PLSQL表达式的区别

参考文档&#xff1a; Database Administrator’s Guide 29.4.5.4 Differences Between PL/SQL Expression and Calendaring Syntax Behavior There are important differences in behavior between a calendaring expression and PL/SQL repeat interval. These differenc…...

Java设计模式:一、六大设计原则-06:依赖倒置原则

文章目录 一、定义&#xff1a;依赖倒置原则二、模拟场景&#xff1a;依赖倒置原则三、违背方案&#xff1a;依赖倒置原则3.1 工程结构3.2 抽奖系统**3.2.1 定义抽奖用户类**3.2.2 抽奖控制 3.3 单元测试 四、改善代码&#xff1a;依赖倒置原则4.1 工程结构4.2 抽奖控制改善4.2…...

信息系统数据同步解决方案

实施数据同步解决方案时&#xff0c;重要的是确保数据同步是安全的、可靠的&#xff0c;并且能够适应系统变化。定期测试和监控数据同步过程&#xff0c;以确保其稳定运行&#xff0c;并随着需求的变化进行适当的调整和优化。 应用场景&#xff1a;信息系统A和信息系统B实现员…...

LRU算法 vs Redis近似LRU算法

LRU(Least Recently Use)算法&#xff0c;是用来判断一批数据中&#xff0c;最近最少使用算法。它底层数据结构由Hash和链表结合实现&#xff0c;使用Hash是为了保障查询效率为O(1)&#xff0c;使用链表保障删除元素效率为O(1)。 LRU算法是用来判断最近最少使用到元素&#xf…...

浅析ARMv8体系结构:异常处理机制

文章目录 概述异常类型中断终止Abort复位Reset系统调用 异常处理流程异常入口异常返回异常返回地址 堆栈选择 异常向量表异常向量表的配置 同步异常解析相关参考 概述 异常处理指的是处理器在运行过程中发生了外部事件&#xff0c;导致处理器需要中断当前执行流程转而去处理异…...

Golang开发--Goroutine的使用

Go 语言天生支持并发编程&#xff0c;提供了丰富的原语和工具来编写并发程序。Goroutine 是 Go 语言中的轻量级执行单位。它们是由 Go 运行时&#xff08;runtime&#xff09;管理的&#xff0c;并且能够在单个线程上运行成千上万个 Goroutine。创建 Goroutine 非常高效&#x…...

【Linux】package ‘python-yaml‘ has no installation candidate 如何解决

要解决此问题&#xff0c;可以尝试以下几个步骤&#xff1a; 确保系统已经更新到最新版本。可以使用以下命令进行系统更新&#xff1a; sudo apt update sudo apt upgrade确保您的软件源列表中包含了正确的软件源。可以使用以下命令编辑软件源列表&#xff1a; sudo nano /etc/…...

Selector选择器在AspNetCore中的用法

Selector选择器在AspNetCore中的用法 背景 项目编辑过程中会选择其所属的上级项目&#xff0c;而上级项目在数据结构中是以ParentID的方式表达&#xff0c;而非Project类型&#xff0c;用户不会记录也不应该记录ID值&#xff0c;因此应提供Selector项目下拉框供用户选择。 但…...

anaconda3最新版安装|使用详情|Error: Please select a valid Python interpreter

Win11查看安装的Python路径及安装的库 anaconda3最新版安装|使用详情|Error: Please select a valid Python interpreter 介绍开源包管理系统和环境管理系统 &#xff0c;包括多种语言的包安装&#xff0c;运行&#xff0c;更新&#xff0c;删除&#xff0c;最重要的是可以解…...

java八股文面试[多线程]——锁的分类

1.1 可重入锁、不可重入锁 Java中提供的synchronized&#xff0c;ReentrantLock&#xff0c;ReentrantReadWriteLock都是可重入锁。 重入&#xff1a;当前线程获取到A锁&#xff0c;在获取之后尝试再次获取A锁是可以直接拿到的。 不可重入&#xff1a;当前线程获取到A锁&…...

儿童安全门和围栏,以及游戏围栏等美国站要求的合规标准是什么?

儿童安全门和围栏 儿童安全门和围栏用于在门口&#xff08;如门道&#xff09;内设置围栏&#xff0c;或用作自支撑围栏&#xff0c;将幼儿可能在其中活动的区域围起来。这些商品可能由塑料、金属、乙烯树脂或木制组件等材料制成。此政策包括但不限于可扩展围栏、伸缩安全门和…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...