Java8中Stream流API最佳实践Lambda表达式使用示例
文章目录
- 一、创建流
- 二、中间操作和收集操作
- 筛选 filter
- 去重distinct
- 截取
- 跳过
- 映射
- 合并多个流
- 是否匹配任一元素:anyMatch
- 是否匹配所有元素:allMatch
- 是否未匹配所有元素:noneMatch
- 获取任一元素findAny
- 获取第一个元素findFirst
- 归约
- 数值流的使用
- 中间操作和收集操作总结
- Collector 收集
- 归约
- 一般性归约
- 汇总
- 分组
- 多级分组
- 转换类型
- 数据分区
- 并行流
stream在使用中主要分为以上图示阶段,接下来将详细展示java8中stream api的具体的实践使用案例。
一、创建流
在使用流之前,首先需要拥有一个数据源,并通过StreamAPI提供的一些方法获取该数据源的流对象。数据源可以有多种形式:
1. 集合
这种数据源较为常用,通过stream()方法即可获取流对象:
List<Person> list = new ArrayList<Person>();
Stream<Person> stream = list.stream();
2. 数组
通过Arrays类提供的静态函数stream()获取数组的流对象:
String[] names = {"chaimm","peter","john"};
Stream<String> stream = Arrays.stream(names);
3. 值
直接将几个值变成流对象:
Stream<String> stream = Stream.of("chaimm","peter","john");
4. 文件
try(Stream lines = Files.lines(Paths.get(“文件路径名”),Charset.defaultCharset())){//可对lines做一些操作
}catch(IOException e){
}
5. iterator
创建无限流
Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);
PS:Java7简化了IO操作,把打开IO操作放在try后的括号中即可省略关闭IO的代码。
二、中间操作和收集操作
筛选 filter
filter 函数接收一个Lambda表达式作为参数,该表达式返回boolean,在执行过程中,流将元素逐一输送给filter,并筛选出执行结果为true的元素。
如,筛选出所有学生:
List<Person> result = list.stream().filter(Person::isStudent).collect(toList());
去重distinct
去掉重复的结果:
List<Person> result = list.stream().distinct().collect(toList());
截取
截取流的前N个元素:
List<Person> result = list.stream().limit(3).collect(toList());
跳过
跳过流的前n个元素:
List<Person> result = list.stream().skip(3).collect(toList());
映射
对流中的每个元素执行一个函数,使得元素转换成另一种类型输出。流会将每一个元素输送给map函数,并执行map中的Lambda表达式,最后将执行结果存入一个新的流中。
如,获取每个人的姓名(实则是将Perosn类型转换成String类型):
List<Person> result = list.stream().map(Person::getName).collect(toList());
合并多个流
例:列出List中各不相同的单词,List集合如下:
List<String> list = new ArrayList<String>();
list.add("I am a boy");
list.add("I love the girl");
list.add("But the girl loves another girl");
思路如下:
首先将list变成流:
list.stream();
按空格分词:
list.stream().map(line->line.split(" "));
分完词之后,每个元素变成了一个String[]数组。
将每个 String[]
变成流:
list.stream().map(line->line.split(" ")).map(Arrays::stream)
此时一个大流里面包含了一个个小流,我们需要将这些小流合并成一个流。
将小流合并成一个大流:用 flatMap
替换刚才的 map
list.stream().map(line->line.split(" ")).flatMap(Arrays::stream)
去重
list.stream().map(line->line.split(" ")).flatMap(Arrays::stream).distinct().collect(toList());
是否匹配任一元素:anyMatch
anyMatch用于判断流中是否存在至少一个元素满足指定的条件,这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。
如,判断list中是否有学生:
boolean result = list.stream().anyMatch(Person::isStudent);
是否匹配所有元素:allMatch
allMatch用于判断流中的所有元素是否都满足指定条件,这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。
如,判断是否所有人都是学生:
boolean result = list.stream().allMatch(Person::isStudent);
是否未匹配所有元素:noneMatch
noneMatch与allMatch恰恰相反,它用于判断流中的所有元素是否都不满足指定条件:
boolean result = list.stream().noneMatch(Person::isStudent);
获取任一元素findAny
findAny能够从流中随便选一个元素出来,它返回一个Optional类型的元素。
Optional<Person> person = list.stream().findAny();
获取第一个元素findFirst
Optional<Person> person = list.stream().findFirst();
归约
归约是将集合中的所有元素经过指定运算,折叠成一个元素输出,如:求最值、平均数等,这些操作都是将一个集合的元素折叠成一个元素输出。
在流中,reduce函数能实现归约。
reduce函数接收两个参数:
- 初始值
- 进行归约操作的Lambda表达式
元素求和:自定义Lambda表达式实现求和
例:计算所有人的年龄总和
@Test
public void contextLoads() {List<Person> list = new ArrayList<>();list.add(new Person().setAge(20));list.add(new Person().setAge(25));int age = list.stream().map(Person::getAge).reduce(0, Integer::sum);System.out.println(age);
}
@Data
@Accessors(chain = true)
class Person {private int age;
}
- reduce的第一个参数表示初试值为0;
- reduce的第二个参数为需要进行的归约操作,它接收一个拥有两个参数的Lambda表达式,reduce会把流中的元素两两输给Lambda表达式,最后将计算出累加之和。
元素求和:使用Integer.sum函数求和
上面的方法中我们自己定义了Lambda表达式实现求和运算,如果当前流的元素为数值类型,那么可以使用Integer提供了sum函数代替自定义的Lambda表达式,如:
int age = list.stream().reduce(0, Integer::sum);
Integer类还提供了 min
、max
等一系列数值操作,当流中元素为数值类型时可以直接使用。
数值流的使用
采用reduce进行数值操作会涉及到基本数值类型和引用数值类型之间的装箱、拆箱操作,因此效率较低。
当流操作为纯数值操作时,使用数值流能获得较高的效率。
将普通流转换成数值流
StreamAPI提供了三种数值流:IntStream、DoubleStream、LongStream,也提供了将普通流转换成数值流的三种方法:mapToInt、mapToDouble、mapToLong。
如,将Person中的age转换成数值流:
IntStream stream = list.stream().mapToInt(Person::getAge);
数值计算
每种数值流都提供了数值计算函数,如max、min、sum等。如,找出最大的年龄:
OptionalInt maxAge = list.stream().mapToInt(Person::getAge).max();
由于数值流可能为空,并且给空的数值流计算最大值是没有意义的,因此max函数返回OptionalInt,它是Optional的一个子类,能够判断流是否为空,并对流为空的情况作相应的处理。
此外,mapToInt、mapToDouble、mapToLong进行数值操作后的返回结果分别为:OptionalInt、OptionalDouble、OptionalLong
中间操作和收集操作总结
操作 | 类型 | 返回类型 | 使用的类型/函数式接口 | 函数描述符 |
---|---|---|---|---|
filter | 中间 | Stream<T> | Predicate<T> | T -> boolean |
distinct | 中间 | Stream<T> | ||
skip | 中间 | Stream<T> | long | |
map | 中间 | Stream<R> | Function<T, R> | T -> R |
flatMap | 中间 | Stream<R> | Function<T, Stream<R>> | T -> Stream<R> |
limit | 中间 | Stream<T> | long | |
sorted | 中间 | Stream<T> | Comparator<T> | (T, T) -> int |
anyMatch | 终端 | boolean | Predicate<T> | T -> boolean |
noneMatch | 终端 | boolean | Predicate<T> | T -> boolean |
allMatch | 终端 | boolean | Predicate<T> | T -> boolean |
findAny | 终端 | Optional<T> | ||
findFirst | 终端 | Optional<T> | ||
forEach | 终端 | void | Consumer<T> | T -> void |
collect | 终端 | R | Collector<T, A, R> | |
reduce | 终端 | Optional<T> | BinaryOperator<T> | (T, T) -> T |
count | 终端 | long |
Collector 收集
收集器用来将经过筛选、映射的流进行最后的整理,可以使得最后的结果以不同的形式展现。
collect
方法即为收集器,它接收 Collector
接口的实现作为具体收集器的收集方法。
Collector
接口提供了很多默认实现的方法,我们可以直接使用它们格式化流的结果;也可以自定义 Collector
接口的实现,从而定制自己的收集器。
归约
流由一个个元素组成,归约就是将一个个元素“折叠”成一个值,如求和、求最值、求平均值都是归约操作。
一般性归约
若你需要自定义一个归约操作,那么需要使用 Collectors.reducing
函数,该函数接收三个参数:
- 第一个参数为归约的初始值
- 第二个参数为归约操作进行的字段
- 第三个参数为归约操作的过程
汇总
Collectors类专门为汇总提供了一个工厂方法:Collectors.summingInt
。
它可接受一 个把对象映射为求和所需int的函数,并返回一个收集器;该收集器在传递给普通的 collect
方法后即执行我们需要的汇总操作。
分组
数据分组是一种更自然的分割数据操作,分组就是将流中的元素按照指定类别进行划分,类似于SQL语句中的 GROUPBY
。
多级分组
多级分组可以支持在完成一次分组后,分别对每个小组再进行分组。
使用具有两个参数的 groupingBy
重载方法即可实现多级分组。
- 第一个参数:一级分组的条件
- 第二个参数:一个新的
groupingBy
函数,该函数包含二级分组的条件
Collectors 类的静态工厂方法
工厂方法 | 返回类型 | 用途 | 示例 |
---|---|---|---|
toList | List<T> | 把流中所有项目收集到一个 List | List<Project> projects = projectStream.collect(toList()); |
toSet | Set<T> | 把流中所有项目收集到一个 Set,删除重复项 | Set<Project> projects = projectStream.collect(toSet()); |
toCollection | Collection<T> | 把流中所有项目收集到给定的供应源创建的集合 | Collection<Project> projects = projectStream.collect(toCollection(), ArrayList::new); |
counting | Long | 计算流中元素的个数 | long howManyProjects = projectStream.collect(counting()); |
summingInt | Integer | 对流中项目的一个整数属性求和 | int totalStars = projectStream.collect(summingInt(Project::getStars)); |
averagingInt | Double | 计算流中项目 Integer 属性的平均值 | double avgStars = projectStream.collect(averagingInt(Project::getStars)); |
summarizingInt | IntSummaryStatistics | 收集关于流中项目 Integer 属性的统计值,例如最大、最小、 总和与平均值 | IntSummaryStatistics projectStatistics = projectStream.collect(summarizingInt(Project::getStars)); |
joining | String | 连接对流中每个项目调用 toString 方法所生成的字符串 | String shortProject = projectStream.map(Project::getName).collect(joining(", ")); |
maxBy | Optional<T> | 按照给定比较器选出的最大元素的 Optional, 或如果流为空则为 Optional.empty() | Optional<Project> fattest = projectStream.collect(maxBy(comparingInt(Project::getStars))); |
minBy | Optional<T> | 按照给定比较器选出的最小元素的 Optional, 或如果流为空则为 Optional.empty() | Optional<Project> fattest = projectStream.collect(minBy(comparingInt(Project::getStars))); |
reducing | 归约操作产生的类型 | 从一个作为累加器的初始值开始,利用 BinaryOperator 与流中的元素逐个结合,从而将流归约为单个值 | int totalStars = projectStream.collect(reducing(0, Project::getStars, Integer::sum)); |
collectingAndThen | 转换函数返回的类型 | 包含另一个收集器,对其结果应用转换函数 | int howManyProjects = projectStream.collect(collectingAndThen(toList(), List::size)); |
groupingBy | Map<K, List<T>> | 根据项目的一个属性的值对流中的项目作问组,并将属性值作 为结果 Map 的键 | Map<String,List<Project>> projectByLanguage = projectStream.collect(groupingBy(Project::getLanguage)); |
partitioningBy | Map<Boolean,List<T>> | 根据对流中每个项目应用断言的结果来对项目进行分区 | Map<Boolean,List<Project>> vegetarianDishes = projectStream.collect(partitioningBy(Project::isVegetarian)); |
转换类型
有一些收集器可以生成其他集合。比如前面已经见过的 toList
,生成了 java.util.List
类的实例。
还有 toSet
和 toCollection
,分别生成 Set
和 Collection
类的实例。
到目前为止, 我已经讲了很多流上的链式操作,但总有一些时候,需要最终生成一个集合——比如:
- 已有代码是为集合编写的,因此需要将流转换成集合传入;
- 在集合上进行一系列链式操作后,最终希望生成一个值;
- 写单元测试时,需要对某个具体的集合做断言。
使用 toCollection
,用定制的集合收集元素
stream.collect(toCollection(TreeSet::new));
还可以利用收集器让流生成一个值。 maxBy
和 minBy
允许用户按某种特定的顺序生成一个值。
数据分区
分区是分组的特殊情况:由一个断言(返回一个布尔值的函数)作为分类函数,它称分区函数。
分区函数返回一个布尔值,这意味着得到的分组 Map
的键类型是 Boolean
,于是它最多可以分为两组: true是一组,false是一组。
分区的好处在于保留了分区函数返回true或false的两套流元素列表。
并行流
并行流就是一个把内容分成多个数据块,并用不不同的线程分别处理每个数据块的流。最后合并每个数据块的计算结果。
将一个顺序执行的流转变成一个并发的流只要调用 parallel()
方法
public static long parallelSum(long n){return Stream.iterate(1L, i -> i +1).limit(n).parallel().reduce(0L,Long::sum);
}
将一个并发流转成顺序的流只要调用 sequential()
方法
stream.parallel().filter(...).sequential().map(...).parallel().reduce();
这两个方法可以多次调用,只有最后一个调用决定这个流是顺序的还是并发的。
并发流使用的默认线程数等于你机器的处理器核心数。
通过这个方法可以修改这个值,这是全局属性。
System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "12");
并非使用多线程并行流处理数据的性能一定高于单线程顺序流的性能,因为性能受到多种因素的影响。
如何高效使用并发流的一些建议:
- 如果不确定, 就自己测试。
- 尽量使用基本类型的流 IntStream, LongStream, DoubleStream
- 有些操作使用并发流的性能会比顺序流的性能更差,比如limit,findFirst,依赖元素顺序的操作在并发流中是极其消耗性能的。findAny的性能就会好很多,应为不依赖顺序。
- 考虑流中计算的性能(Q)和操作的性能(N)的对比, Q表示单个处理所需的时间,N表示需要处理的数量,如果Q的值越大, 使用并发流的性能就会越高。
- 数据量不大时使用并发流,性能得不到提升。
- 考虑数据结构:并发流需要对数据进行分解,不同的数据结构被分解的性能时不一样的。
流的数据源和可分解性
源 | 可分解性 |
---|---|
ArrayList | 非常好 |
LinkedList | 差 |
IntStream.range | 非常好 |
Stream.iterate | 差 |
HashSet | 好 |
TreeSet | 好 |
流的特性以及中间操作对流的修改都会对数据对分解性能造成影响。 比如固定大小的流在任务分解的时候就可以平均分配,但是如果有filter操作,那么流就不能预先知道在这个操作后还会剩余多少元素。
考虑终端操作的性能:如果终端操作在合并并发流的计算结果时的性能消耗太大,那么使用并发流提升的性能就会得不偿失。
相关文章:
Java8中Stream流API最佳实践Lambda表达式使用示例
文章目录 一、创建流二、中间操作和收集操作筛选 filter去重distinct截取跳过映射合并多个流是否匹配任一元素:anyMatch是否匹配所有元素:allMatch是否未匹配所有元素:noneMatch获取任一元素findAny获取第一个元素findFirst归约数值流的使用中…...
构建Helm chart和chart使用管道与函数简介
目录 一.创建helm chart(以nginx为例) 1.通过create去创建模板 2.查看模板下的文件 3.用chart模版安装nginx 二.版本更新和回滚问题 1.使用upgrade -f values.yaml或者命令行--set来设置 2.查看历史版本并回滚 三.helm模板内管道和函数 1.defau…...
深入理解OnCalculate函数的运行机制
文章目录 一、学习 OnCalculate 函数的运行原理的意义二、OnCalculate 函数原型三、OnCalculate 函数在MT4与MT5区别四、OnCalculate 函数的运行原理 一、学习 OnCalculate 函数的运行原理的意义 OnCalculate函数是MQL语言中的一个重要函数,它用于计算技术指标的值。…...
快速从0-1完成聊天室开发——环信ChatroomUIKit功能详解
聊天室是当下泛娱乐社交应用中最经典的玩法,通过调用环信的 IM SDK 接口,可以快速创建聊天室。如果想根据自己业务需求对聊天室应用的 UI界面、弹幕消息、礼物打赏系统等进行自定义设计,最高效的方式则是使用环信的 ChatroomUIKit 。 文档地址…...
nginx实现多个域名和集群
要通过Nginx实现多个域名和集群,你需要配置Nginx作为反向代理服务器,将来自不同域名的请求转发到集群中的相应后端服务器。下面是一个基本的配置示例,你可以根据自己的需求进行修改和扩展。 首先,确保你已经安装了Nginxÿ…...
C. Left and Right Houses
Problem - C - Codeforces 题目分析 <1>0:想被分割至左边; 1:想被分割至右边 <2>使得左右两侧均有一半及其以上的人满意(我*******) <3>答案若有多个,取最接近中间位置的答案 <4…...
缓存与内存:加速你的Python应用
在现代计算中,缓存和内存是提高程序性能的关键组件。在这篇文章中,我们将深入探讨这两个概念,了解它们是如何工作的,以及如何在Python中有效地使用它们来优化你的程序。 缓存与内存:加速你的Python应用 缓存和内存&…...
Go语言之函数、方法、接口
一、函数 函数的基本语法: func 函数名(形参列表)(返回值列表) {执行语句...return 返回值列表 } 1.形参列表:表示函数的输入 2.函数中的语句:表示为了实现某一功能的代码块 3.函数可以有返回…...
【Week Y2】使用自己的数据集训练YOLO-v5s
Y2-使用自己的数据集训练YOLO-v5s 零、遇到的问题汇总(1)遇到git的import error(2)Error:Dataset not found(3)Error:删除中文后,训练图片路径不存在 一、.xml文件里保存…...
蓝桥杯--基础(哈夫曼)
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Scanner;public class BASIC28 {//哈夫曼书public static void main(String[] args) {Scanner Scannernew Scanner(System.in);int nScanner.nextInt();List<Integer&…...
【Redis内存数据库】NoSQL的特点和应用场景
前言 Redis作为当今最流行的内存数据库,已经成为服务端加速的必备工具之一。 NoSQL数据库采用了非关系型的数据存储模型,能够更好地处理海量数据和高并发访问。 内存数据库具有更快的读写速度和响应时间,因为内存访问速度比磁盘访问速度快…...
JavaScript基础知识2
求数组的最大值案例 let arr[2,6,1,7,400,55,88,100]let maxarr[0]let minarr[0]for(let i1;i<arr.length;i){max<arr[i]?maxarr[i]:maxmin>arr[i]?minarr[i]:min}console.log(最大值是:${max})console.log(最小值是:${min}) 操作数组 修改…...
Linux之线程同步
目录 一、问题引入 二、实现线程同步的方案——条件变量 1、常用接口: 2、使用示例 一、问题引入 我们再次看看上次讲到的多线程抢票的代码:这次我们让一个线程抢完票之后不去做任何事。 #include <iostream> #include <unistd.h> #inc…...
03 龙芯平台openstack部署搭建-keystone部署
#!/bin/bash #创建keystone数据库并授权,可通过mysql -ukeystone -ploongson验证授权登录 mysql -uroot -e “set password for rootlocalhost password(‘loongson’);” mysql -uroot -ploongson -e ‘CREATE DATABASE keystone;’ #本地登录 mysql -uroot -ploo…...
定义了服务器的端口号和Servlet的上下文路径
server: port: 1224 servlet: context-path: /applet 这个配置定义了服务器的端口号和Servlet的上下文路径。 下面是配置的解释: server.port: 1224:这表示服务器应该监听在1224端口上。server.servlet.context-path: /applet:这表…...
AI论文速读 | UniST:提示赋能通用模型用于城市时空预测
本文是时空领域的统一模型——UniST,无独有偶,时序有个统一模型新工作——UniTS,感兴趣的读者也可以阅读今天发布的另外一条。 论文标题:UniST: A Prompt-Empowered Universal Model for Urban Spatio-Temporal Prediction 作者&…...
rabbitmq-spring-boot-start配置使用手册
rabbitmq-spring-boot-start配置使用手册 文章目录 1.yaml配置如下2.引入pom依赖如下2.1 引入项目resources下libs中的jar包依赖如下2.2引入maven私服依赖如下 3.启动类配置如下4.项目中测试发送消息如下5.项目中消费消息代码示例6.mq管理后台交换机队列创建及路由绑定关系如下…...
操作系统知识-操作系统作用+进程管理-嵌入式系统设计师备考笔记
0、前言 本专栏为个人备考软考嵌入式系统设计师的复习笔记,未经本人许可,请勿转载,如发现本笔记内容的错误还望各位不吝赐教(笔记内容可能有误怕产生错误引导)。 本章的主要内容见下图: 1、操作系统的作用…...
Go语言中的锁与管道的运用
目录 1.前言 2.锁解决方案 3.管道解决方案 4.总结 1.前言 在写H5小游戏的时候,由于需要对多个WebSocket连接进行增、删、查的管理和对已经建立连接的WebSocket通过服务端进行游戏数据交换的需求。于是定义了一个全局的map集合进行连接的管理,让所有…...
前端 - 基础 表单标签 -- 表单元素( input - type属性) 文本框和密码框
表单元素 : 在表单域中可以定义各种表单元素,这些表单元素就是允许用户在表单中输入或选择 的内容控件。 表单元素的外观也各不一样,有小圆圈,有正方形,也有方框,乱七八糟的,各种各样…...
关于MySQL模糊搜索不区分大小写
在我们日常使用ORM框架进行模糊查询时,会发现,搜索的结果是不区分关键字的英文大小写的,那这是为什么呢? 原因是MySQL的like本就不区分大小写;如果在建表的时候,没有设置好字段区分大小 //包含j和J的都会被…...
论文阅读——MoCo
Momentum Contrast for Unsupervised Visual Representation Learning 动量在数学上理解为加权移动平均: yt-1是上一时刻输出,xt是当前时刻输入,m是动量,不想让当前时刻输出只依赖于当前时刻的输入,m很大时࿰…...
ARM 寄存器学习:(一)arm多种模式下得寄存器
一.ARM7种状态以及每种状态的寄存器: ARM 处理器共有 7 种不同的处理器模式,在每一种处理器模式中可见的寄存器包括 15 个通用寄存器( R0~R14)、一个或两个(User和Sys不是异常模式,没有spsr寄存器)状态寄存器(cpsr和spsr&…...
【nfs报错】rpc mount export: RPC: Unable to receive; errno = No route to host
NFS错误 问题现象解决方法 写在前面 这两天搭建几台服务器,需要使用nfs服务,于是六台选其一做服务端,其余做客户端,搭建过程写在centos7离线搭建NFS共享文件,但是访问共享时出现报错:rpc mount export: RPC…...
备战蓝桥杯---牛客寒假训练营2VP
题挺好的,收获了许多 1.暴力枚举(许多巧妙地处理细节方法) n是1--9,于是我们可以直接暴力,对于1注意特判开头0但N!1,对于情报4,我们可以把a,b,c,d的所有取值枚举一遍,那么如何判断有…...
QCustomPlot-绘制X轴为日期的折线图
主要代码如下: void Widget::InitQLineXDateAddData() {customPlot new QCustomPlot(this);// 创建日期时间类型的刻度生成器QSharedPointer<QCPAxisTickerDateTime> dateTimeTicker(new QCPAxisTickerDateTime);dateTimeTicker->setDateTimeFormat(&quo…...
腾讯春招后端一面(算法篇)
前言: 哈喽大家好,前段时间在小红书和牛客上发了面试的经验贴,很多同学留言问算法的具体解法,今天就详细写个帖子回复大家。 因为csdn是写的比较详细,所以更新比较慢,大家见谅~~ 就题目而言,…...
Filebeat rpm方式安装及配置
一、使用服务器root用户、filebeat8.11.1版本,rpm安装方式进行安装 curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.11.1-x86_64.rpm sudo rpm -vi filebeat-8.11.1-x86_64.rpm 二、配置核心的采集文件、使用inputs热更方式、配置filebeat本身…...
深入挖掘C语言之——枚举
目录 1. 枚举的定义 2. 枚举常量的赋值 3. 枚举的使用示例 4. 注意事项 在C语言中,枚举(Enum)是一种用户定义的数据类型,用于定义一组具名的整型常量。枚举常常用于提高代码的可读性和可维护性,使程序更易于理解。…...
【源码阅读】EVMⅢ
参考[link](https://blog.csdn.net/weixin_43563956/article/details/127725385 大致流程如下: 编写合约 > 生成abi > 解析abi得出指令集 > 指令通过opcode来映射成操作码集 > 生成一个operation 以太坊虚拟机的工作流程: 由solidity语言编…...
网站建设源代码交付/安徽网络seo
转载请标明出处:http://blog.csdn.net/xx326664162/article/details/50599911 文章出自:薛瑄的博客 你也可以查看我的其他同类文章,也会让你有一定的收货! 一、系统分区 # adb shell # mount rootfs / rootfs ro 0 0 tmpfs /d…...
大良营销网站建设流程/百度网盘app下载安装手机版
在每一段爱情的开始,双方都抱着真诚的态度,都想与伴侣携手终生。然而,有句俗话说“爱比相处容易”。爱是喝不饱的。无论你有多深的爱,你都无法满足日常生活的消费。很多情侣就是因为不懂得“如何爱对方”而与另一半遗憾告别。明明…...
医院网站党支部机构建设/114外链
网络协议系列文章 网络协议(一):基本概念、计算机之间的连接方式 网络协议(二):MAC地址、IP地址、子网掩码、子网和超网 网络协议(三):路由器原理及数据包传输过程 网络协议(四):网络分类、ISP、上网方式、公网私网、NAT 网络…...
做手机网站用什么程序好/网站建设设计
1、使用界面配置第二个网卡 Ip mask gw 2、修改这个网卡的配置文件 vim /etc/sysconfig/network-script/ifcfg-em1 3、重新启动电脑 4、route add -net 172.0.0.0 netmask 255.0.0.0 gw 172.19.232.254 5、route -n 会有2个172的配置 6、删除一个 route del -net 172.19.232.0…...
同城做推广哪个网站好/谷歌seo网络公司
平时我们如果要用到委托一般都是先声明一个委托类型,比如: private delegate string Say(); string说明适用于这个委托的方法的返回类型是string类型,委托名Say后面没有参数,说明对应的方法也就没有传入参数。 写一个适用于该委托…...
给 小企业 建设网站/百度百科词条创建入口
为何地图上的航线是曲线如果我们观察地图上的航线,就会发现航线是弯曲的。基本上可以认为地球是个球体,如果飞机在两个城市之间飞行,最好的飞行线路是取这两个城市之间的最短距离。这其实课看成球面上任意两点之间的最短距离。过球面上的任意…...