当前位置: 首页 > 编程日记 > 正文

Hadoop学习之Mapreduce执行过程详解

一、MapReduce执行过程

MapReduce运行时,首先通过Map读取HDFS中的数据,然后经过拆分,将每个文件中的每行数据分拆成键值对,最后输出作为Reduce的输入,大体执行流程如下图所示:

整个流程图具体来说:每个Mapper任务是一个java进程,它会读取HDFS中的文件,解析成很多的键值对,经过我们覆盖的map方法处理后,转换为很多的键值对再输出,整个Mapper任务的处理过程又可以分为以下几个阶段,如图所示。

在上图中,把Mapper任务的运行过程分为六个阶段

      • 第一阶段是把输入文件按照一定的标准分片 (InputSplit),每个输入片的大小是固定的。默认情况下,输入片(InputSplit)的大小与数据块(Block)的大小是相同的。如果数据块(Block)的大小是默认值64MB,输入文件有两个,一个是32MB,一个是72MB。那么小的文件是一个输入片,大文件会分为两个数据块,那么是两个输入片,一共产生三个输入片。每一个输入片由一个Mapper进程处理,这里的三个输入片,会有三个Mapper进程处理。
      • 第二阶段是对输入片中的记录按照一定的规则解析成键值对,有个默认规则是把每一行文本内容解析成键值对,这里的“键”是每一行的起始位置(单位是字节),“值”是本行的文本内容。
      • 第三阶段是调用Mapper类中的map方法,在第二阶段中解析出来的每一个键值对,调用一次map方法,如果有1000个键值对,就会调用1000次map方法,每一次调用map方法会输出零个或者多个键值对。
      • 第四阶段是按照一定的规则对第三阶段输出的键值对进行分区,分区是基于键进行的,比如我们的键表示省份(如北京、上海、山东等),那么就可以按照不同省份进行分区,同一个省份的键值对划分到一个区中。默认情况下只有一个区,分区的数量就是Reducer任务运行的数量,因此默认只有一个Reducer任务。
      • 第五阶段是对每个分区中的键值对进行排序。首先,按照键进行排序,对于键相同的键值对,按照值进行排序。比如三个键值 对<2,2>、<1,3>、<2,1>,键和值分别是整数。那么排序后的结果 是<1,3>、<2,1>、<2,2>。如果有第六阶段,那么进入第六阶段;如果没有,直接输出到本地的linux 文件中。
      • 第六阶段是对数据进行归约处理,也就是reduce处理,通常情况下的Comber过程,键相等的键值对会调用一次reduce方法,经过这一阶段,数据量会减少,归约后的数据输出到本地的linxu文件中。本阶段默认是没有的,需要用户自己增加这一阶段的代码。

二、Reducer任务的执行过程详解

     每个Reducer任务是一个java进程。Reducer任务接收Mapper任务的输出,归约处理后写入到HDFS中,可以分为如下图所示的几个阶段。


1、第一阶段是Reducer任务会主动从Mapper任务复制其输出的键值对,Mapper任务可能会有很多,因此Reducer会复制多个Mapper的输出。

2、第二阶段是把复制到Reducer本地数据,全部进行合并,即把分散的数据合并成一个大的数据,再对合并后的数据排序。

3、第三阶段是对排序后的键值对调用reduce方法,键相等的键值对调用一次reduce方法,每次调用会产生零个或者多个键值对,最后把这些输出的键值对写入到HDFS文件中。


三、键值对的编号

    在对Mapper任务、Reducer任务的分析过程中,会看到很多阶段都出现了键值对,这里对键值对进行编号,方便理解键值对的变化情况,如下图所示。


在上图中,对于Mapper任务输入的键值对,定义为key1和value1,在map方法中处理后,输出的键值对,定义为key2和value2,reduce方法接收key2和value2处理后,输出key3和value3。在下文讨论键值对时,可能把key1和value1简写 为<k1,v1>,key2和value2简写为<k2,v2>,key3和value3简写为<k3,v3>。

四、实例

2014010114
2014010216
2014010317
2014010410
2014010506
2012010609
2012010732
2012010812
2012010919
2012011023
2001010116
2001010212
2001010310
2001010411
2001010529
2013010619
2013010722
2013010812
2013010929
2013011023
2008010105
2008010216
2008010337
2008010414
2008010516
2007010619
2007010712
2007010812
2007010999
2007011023
2010010114
2010010216
2010010317
2010010410
2010010506
2015010649
2015010722
2015010812
2015010999
2015011023

 比如:2010012325表示在2010年01月23日的气温为25度。现在要求使用MapReduce,计算每一年出现过的最大气温。

  1 package com.abc.yarn;
  2  
  3 import java.io.IOException;
  4  
  5 import org.apache.hadoop.conf.Configuration;
  6 import org.apache.hadoop.fs.Path;
  7 import org.apache.hadoop.io.IntWritable;
  8 import org.apache.hadoop.io.LongWritable;
  9 import org.apache.hadoop.io.Text;
 10 import org.apache.hadoop.mapreduce.Job;
 11 import org.apache.hadoop.mapreduce.Mapper;
 12 import org.apache.hadoop.mapreduce.Reducer;
 13 import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
 14 import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
 15  
 16 public class Temperature {
 17     /**
 18      * 四个泛型类型分别代表:
 19      * KeyIn        Mapper的输入数据的Key,这里是每行文字的起始位置(0,11,...)
 20      * ValueIn      Mapper的输入数据的Value,这里是每行文字
 21      * KeyOut       Mapper的输出数据的Key,这里是每行文字中的“年份”
 22      * ValueOut     Mapper的输出数据的Value,这里是每行文字中的“气温”
 23      */
 24     static class TempMapper extends
 25             Mapper<LongWritable, Text, Text, IntWritable> {
 26         @Override
 27         public void map(LongWritable key, Text value, Context context)
 28                 throws IOException, InterruptedException {
 29             // 打印样本: Before Mapper: 0, 2000010115
 30             System.out.print("Before Mapper: " + key + ", " + value);
 31             String line = value.toString();
 32             String year = line.substring(0, 4);
 33             int temperature = Integer.parseInt(line.substring(8));
 34             context.write(new Text(year), new IntWritable(temperature));
 35             // 打印样本: After Mapper:2000, 15
 36             System.out.println(
 37                     "======" +
 38                     "After Mapper:" + new Text(year) + ", " + new IntWritable(temperature));
 39         }
 40     }
 41  
 42     /**
 43      * 四个泛型类型分别代表:
 44      * KeyIn        Reducer的输入数据的Key,这里是每行文字中的“年份”
 45      * ValueIn      Reducer的输入数据的Value,这里是每行文字中的“气温”
 46      * KeyOut       Reducer的输出数据的Key,这里是不重复的“年份”
 47      * ValueOut     Reducer的输出数据的Value,这里是这一年中的“最高气温”
 48      */
 49     static class TempReducer extends
 50             Reducer<Text, IntWritable, Text, IntWritable> {
 51         @Override
 52         public void reduce(Text key, Iterable<IntWritable> values,
 53                 Context context) throws IOException, InterruptedException {
 54             int maxValue = Integer.MIN_VALUE;
 55             StringBuffer sb = new StringBuffer();
 56             //取values的最大值
 57             for (IntWritable value : values) {
 58                 maxValue = Math.max(maxValue, value.get());
 59                 sb.append(value).append(", ");
 60             }
 61             // 打印样本: Before Reduce: 2000, 15, 23, 99, 12, 22, 
 62             System.out.print("Before Reduce: " + key + ", " + sb.toString());
 63             context.write(key, new IntWritable(maxValue));
 64             // 打印样本: After Reduce: 2000, 99
 65             System.out.println(
 66                     "======" +
 67                     "After Reduce: " + key + ", " + maxValue);
 68         }
 69     }
 70  
 71     public static void main(String[] args) throws Exception {
 72         //输入路径
 73         String dst = "hdfs://localhost:9000/intput.txt";
 74         //输出路径,必须是不存在的,空文件加也不行。
 75         String dstOut = "hdfs://localhost:9000/output";
 76         Configuration hadoopConfig = new Configuration();
 77          
 78         hadoopConfig.set("fs.hdfs.impl", 
 79             org.apache.hadoop.hdfs.DistributedFileSystem.class.getName()
 80         );
 81         hadoopConfig.set("fs.file.impl",
 82             org.apache.hadoop.fs.LocalFileSystem.class.getName()
 83         );
 84         Job job = new Job(hadoopConfig);
 85          
 86         //如果需要打成jar运行,需要下面这句
 87         //job.setJarByClass(NewMaxTemperature.class);
 88  
 89         //job执行作业时输入和输出文件的路径
 90         FileInputFormat.addInputPath(job, new Path(dst));
 91         FileOutputFormat.setOutputPath(job, new Path(dstOut));
 92  
 93         //指定自定义的Mapper和Reducer作为两个阶段的任务处理类
 94         job.setMapperClass(TempMapper.class);
 95         job.setReducerClass(TempReducer.class);
 96          
 97         //设置最后输出结果的Key和Value的类型
 98         job.setOutputKeyClass(Text.class);
 99         job.setOutputValueClass(IntWritable.class);
100          
101         //执行job,直到完成
102         job.waitForCompletion(true);
103         System.out.println("Finished");
104     }
105 }

上面代码中,注意Mapper类的泛型不是java的基本类型,而是Hadoop的数据类型Text、IntWritable。我们可以简单的等价为java的类String、int。
代码中Mapper类的泛型依次是<k1,v1,k2,v2>。map方法的第二个形参是行文本内容,是我们关心的。核心代码是把行文本内容按照空格拆分,把每行数据中“年”和“气温”提取出来,其中“年”作为新的键,“温度”作为新的值,写入到上下文context中。在这里,因为每一年有多行数据,因此每一行都会输出一个<年份, 气温>键值对。

Before Mapper: 0, 2014010114======After Mapper:2014, 14
Before Mapper: 11, 2014010216======After Mapper:2014, 16
Before Mapper: 22, 2014010317======After Mapper:2014, 17
Before Mapper: 33, 2014010410======After Mapper:2014, 10
Before Mapper: 44, 2014010506======After Mapper:2014, 6
Before Mapper: 55, 2012010609======After Mapper:2012, 9
Before Mapper: 66, 2012010732======After Mapper:2012, 32
Before Mapper: 77, 2012010812======After Mapper:2012, 12
Before Mapper: 88, 2012010919======After Mapper:2012, 19
Before Mapper: 99, 2012011023======After Mapper:2012, 23
Before Mapper: 110, 2001010116======After Mapper:2001, 16
Before Mapper: 121, 2001010212======After Mapper:2001, 12
Before Mapper: 132, 2001010310======After Mapper:2001, 10
Before Mapper: 143, 2001010411======After Mapper:2001, 11
Before Mapper: 154, 2001010529======After Mapper:2001, 29
Before Mapper: 165, 2013010619======After Mapper:2013, 19
Before Mapper: 176, 2013010722======After Mapper:2013, 22
Before Mapper: 187, 2013010812======After Mapper:2013, 12
Before Mapper: 198, 2013010929======After Mapper:2013, 29
Before Mapper: 209, 2013011023======After Mapper:2013, 23
Before Mapper: 220, 2008010105======After Mapper:2008, 5
Before Mapper: 231, 2008010216======After Mapper:2008, 16
Before Mapper: 242, 2008010337======After Mapper:2008, 37
Before Mapper: 253, 2008010414======After Mapper:2008, 14
Before Mapper: 264, 2008010516======After Mapper:2008, 16
Before Mapper: 275, 2007010619======After Mapper:2007, 19
Before Mapper: 286, 2007010712======After Mapper:2007, 12
Before Mapper: 297, 2007010812======After Mapper:2007, 12
Before Mapper: 308, 2007010999======After Mapper:2007, 99
Before Mapper: 319, 2007011023======After Mapper:2007, 23
Before Mapper: 330, 2010010114======After Mapper:2010, 14
Before Mapper: 341, 2010010216======After Mapper:2010, 16
Before Mapper: 352, 2010010317======After Mapper:2010, 17
Before Mapper: 363, 2010010410======After Mapper:2010, 10
Before Mapper: 374, 2010010506======After Mapper:2010, 6
Before Mapper: 385, 2015010649======After Mapper:2015, 49
Before Mapper: 396, 2015010722======After Mapper:2015, 22
Before Mapper: 407, 2015010812======After Mapper:2015, 12
Before Mapper: 418, 2015010999======After Mapper:2015, 99
Before Mapper: 429, 2015011023======After Mapper:2015, 23
Before Reduce: 2001, 12, 10, 11, 29, 16, ======After Reduce: 2001, 29
Before Reduce: 2007, 23, 19, 12, 12, 99, ======After Reduce: 2007, 99
Before Reduce: 2008, 16, 14, 37, 16, 5, ======After Reduce: 2008, 37
Before Reduce: 2010, 10, 6, 14, 16, 17, ======After Reduce: 2010, 17
Before Reduce: 2012, 19, 12, 32, 9, 23, ======After Reduce: 2012, 32
Before Reduce: 2013, 23, 29, 12, 22, 19, ======After Reduce: 2013, 29
Before Reduce: 2014, 14, 6, 10, 17, 16, ======After Reduce: 2014, 17
Before Reduce: 2015, 23, 49, 22, 12, 99, ======After Reduce: 2015, 99

程序执行结果:

对分析的验证:从打印的日志中可以看出:

  • Mapper的输入数据(k1,v1)格式是:默认的按行分的键值对<0, 2010012325>,<11, 2012010123>...
  • Reducer的输入数据格式是:把相同的键合并后的键值对:<2001, [12, 32, 25...]>,<2007, [20, 34, 30...]>...
  • Reducer的输出数(k3,v3)据格式是:经自己在Reducer中写出的格式:<2001, 32>,<2007, 34>...

    其中,由于输入数据太小,Map过程的第1阶段这里不能证明。但事实上是这样的。结论中第一点验证了Map过程的第2阶段:“键”是每一行的起始位置(单位是字节),“值”是本行的文本内容。另外,通过Reduce的几行

Before Reduce: 2001, 12, 10, 11, 29, 16, ======After Reduce: 2001, 29
Before Reduce: 2007, 23, 19, 12, 12, 99, ======After Reduce: 2007, 99
Before Reduce: 2008, 16, 14, 37, 16, 5, ======After Reduce: 2008, 37
Before Reduce: 2010, 10, 6, 14, 16, 17, ======After Reduce: 2010, 17
Before Reduce: 2012, 19, 12, 32, 9, 23, ======After Reduce: 2012, 32
Before Reduce: 2013, 23, 29, 12, 22, 19, ======After Reduce: 2013, 29
Before Reduce: 2014, 14, 6, 10, 17, 16, ======After Reduce: 2014, 17
Before Reduce: 2015, 23, 49, 22, 12, 99, ======After Reduce: 2015, 99

可以证实Map过程的第4阶段:先分区,然后对每个分区都执行一次Reduce(Map过程第6阶段),对于Mapper的输出,前文中提到:如果没有Reduce过程,Mapper的输出会直接写入文件,于是我们把Reduce方法去掉(注释掉第95行即可),再执行,下面是控制台打印结果:

Before Mapper: 0, 2014010114======After Mapper:2014, 14
Before Mapper: 11, 2014010216======After Mapper:2014, 16
Before Mapper: 22, 2014010317======After Mapper:2014, 17
Before Mapper: 33, 2014010410======After Mapper:2014, 10
Before Mapper: 44, 2014010506======After Mapper:2014, 6
Before Mapper: 55, 2012010609======After Mapper:2012, 9
Before Mapper: 66, 2012010732======After Mapper:2012, 32
Before Mapper: 77, 2012010812======After Mapper:2012, 12
Before Mapper: 88, 2012010919======After Mapper:2012, 19
Before Mapper: 99, 2012011023======After Mapper:2012, 23
Before Mapper: 110, 2001010116======After Mapper:2001, 16
Before Mapper: 121, 2001010212======After Mapper:2001, 12
Before Mapper: 132, 2001010310======After Mapper:2001, 10
Before Mapper: 143, 2001010411======After Mapper:2001, 11
Before Mapper: 154, 2001010529======After Mapper:2001, 29
Before Mapper: 165, 2013010619======After Mapper:2013, 19
Before Mapper: 176, 2013010722======After Mapper:2013, 22
Before Mapper: 187, 2013010812======After Mapper:2013, 12
Before Mapper: 198, 2013010929======After Mapper:2013, 29
Before Mapper: 209, 2013011023======After Mapper:2013, 23
Before Mapper: 220, 2008010105======After Mapper:2008, 5
Before Mapper: 231, 2008010216======After Mapper:2008, 16
Before Mapper: 242, 2008010337======After Mapper:2008, 37
Before Mapper: 253, 2008010414======After Mapper:2008, 14
Before Mapper: 264, 2008010516======After Mapper:2008, 16
Before Mapper: 275, 2007010619======After Mapper:2007, 19
Before Mapper: 286, 2007010712======After Mapper:2007, 12
Before Mapper: 297, 2007010812======After Mapper:2007, 12
Before Mapper: 308, 2007010999======After Mapper:2007, 99
Before Mapper: 319, 2007011023======After Mapper:2007, 23
Before Mapper: 330, 2010010114======After Mapper:2010, 14
Before Mapper: 341, 2010010216======After Mapper:2010, 16
Before Mapper: 352, 2010010317======After Mapper:2010, 17
Before Mapper: 363, 2010010410======After Mapper:2010, 10
Before Mapper: 374, 2010010506======After Mapper:2010, 6
Before Mapper: 385, 2015010649======After Mapper:2015, 49
Before Mapper: 396, 2015010722======After Mapper:2015, 22
Before Mapper: 407, 2015010812======After Mapper:2015, 12
Before Mapper: 418, 2015010999======After Mapper:2015, 99
Before Mapper: 429, 2015011023======After Mapper:2015, 23
Finished

控制台执行结果:

    由于没有执行Reduce操作,因此这个就是Mapper输出的中间文件的内容了。从打印的日志可以看出:Mapper的输出数据(k2, v2)格式是:经自己在Mapper中写出的格式:<2010, 25>,<2012, 23>...从这个结果中可以看出,原数据文件中的每一行确实都有一行输出,那么Map过程的第3阶段就证实了。从这个结果中还可以看出,“年份”已经不是输入给Mapper的顺序了,这也说明了在Map过程中也按照Key执行了排序操作,即Map过程的第5阶段。

转载于:https://www.cnblogs.com/sunfie/p/4651609.html

相关文章:

汇编试验十五:安装新的int 9中断例程

安装新的int 9中断例程&#xff08;按A键后显示满屏幕的A&#xff09; int 9 是外中断&#xff0c;同样&#xff0c;程序编写还是和其他中断例程类似&#xff0c;安装&#xff08;复制&#xff09;&#xff0c;调用&#xff1b; 不同点是在于&#xff0c;他要从端口读取数据60h…

php判断前端传的多个字段与数据库匹配

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 代码 <?phpheader("Content-Type:text/html;charsetutf8"); header("Access-Control-Allow-Origin: *"); //解决跨域header(Access-Control-Allow-Methods:POST);// 响应类型 …

javascript编写_用JavaScript深入探讨:为什么对编写好的代码至关重要。

javascript编写Using simple terminology and a real world example, this post explains what this is and why it is useful.这篇文章使用简单的术语和一个真实的例子&#xff0c;解释了this是什么以及为什么有用。 这是给你的吗 (Is this for you) I have noticed that man…

peak num

class Solution {public: int findPeakElement(vector<int>& nums) { int i0; int nnums.size(); while(i<n){ if(i0){ //处理第一位 if(nums[1] < nums[0]) return 0; else { …

用Eclipse的snippets功能实现代码重用

snippets功能实现代码重用 Snippets 代码片段是Eclipse的一个插件。 很多时候可以通过这个功能&#xff0c;重复使用常用的代码片段&#xff0c;加快开发效率。 创建一个代码段的步骤&#xff1a; 在Eclipse的editor中选中一块代码段&#xff0c;右键点击【Add to Snippets…

JS删除选中的数组

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 js // 删除数组deleteArr: function (e) {let middlearr [{a:1},{b:2}];//全部数组let items [{a:1}];//选中的数组for (var i 0; i < items.length; i) {for (var j 0; j < middlearr.lengt…

Git合并和变基简介:它们是什么,以及如何使用它们

by Vali Shah通过瓦利沙阿 Git合并和Git变基简介&#xff1a;它们做什么以及何时使用它们 (An Introduction to Git Merge and Git Rebase: What They Do and When to Use Them) As a Developer, many of us have to choose between Merge and Rebase. With all the reference…

[转]单点登录原理与简单实现

一、单系统登录机制 1、http无状态协议 web应用采用browser/server架构&#xff0c;http作为通信协议。http是无状态协议&#xff0c;浏览器的每一次请求&#xff0c;服务器会独立处理&#xff0c;不与之前或之后的请求产生关联&#xff0c;这个过程用下图说明&#xff0c;三次…

[JAVA] DUMP

jmap -dump:live,formatb,fileD:\heap.bin 31563156是PID转载于:https://www.cnblogs.com/MasterMonkInTemple/p/4655547.html

ThinkPHP 5.0 入门教程 一:安装ThinkPHP并在Web浏览器访问

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 严格来说&#xff0c;ThinkPHP无需安装过程&#xff0c;这里所说的安装其实就是把ThinkPHP框架放入WEB运行环境&#xff08;前提是你的WEB运行环境已经OK&#xff09; 下面我们开始安装ThinkPHP的运行环…

以太坊区块链同步_以太坊69:如何在10分钟内建立完全同步的区块链节点

以太坊区块链同步by Lukas Lukac卢卡斯卢卡奇(Lukas Lukac) Ethereu M 69&#xff1a;如何在10分钟内建立完全同步的区块链节点 (Ethereum 69: how to set up a fully synced blockchain node in 10 mins) Welcome in the first article of our new go-ethereum series!欢迎来…

微信小程序客服实现自动回复图文消息链接,点击去关注公众号

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 用户打开客服消息&#xff0c;发送任意消息自动回复图文链接&#xff0c;达到关注公众号的目的。 先看效果&#xff1a; 打开芝麻小客服的后台&#xff0c;选择一键接入小程序智能客服 点击跳转 1.授权…

HtmlUnit、httpclient、jsoup爬取网页信息并解析

转载&#xff1a;http://tianxingzhe.blog.51cto.com/3390077/1755511转载于:https://www.cnblogs.com/puhongtao/p/7063563.html

《Maven 实战》笔记之setting.xml介绍

maven是什么&#xff1f;有什么用&#xff1f; Maven是一个跨平台的项目管理工具,主要服务于Java平台的项目构建,依赖管理和项目信息管理。项目构建包括创建项目框架、清理、编译、测试、到生成报告&#xff0c;再到打包和部署&#xff0c;项目信息包括项目描述,开发者列表,版本…

框架依赖注入和普通依赖注入_依赖注入快速入门:它是什么,以及何时使用它...

框架依赖注入和普通依赖注入by Bhavya Karia通过Bhavya Karia 介绍 (Introduction) In software engineering, dependency injection is a technique whereby one object (or static method) supplies the dependencies of another object. A dependency is an object that ca…

微信小程序自定义弹出框组件,模拟wx.showModal

微信小程序开发交流qq群 173683895 效果图&#xff1a; 代码 wxml <view wx:if{{showModal}}><view classmask_layer bindtapmodal_click_Hidden /><view classmodal_box><view class"title">取消订单</view><view classconte…

IOS tableView删除数据

NSMutableArray *_allshops; NSMutableArray *_deleteshops; -(IBAction)remove{ 1. //记录删除的行号 //创建动态数组存放行号的集合 NSMutableArray *deletepath [NSMutableArray array]; //遍历存放删除数据的数组&#xff0c;把行号放到deletepath中 for (Shop * s in _de…

vue.js 源代码学习笔记 ----- 工具方法 lang

/* flow */ // Object.freeze 使得这个对象不能增加属性, 修改属性, 这样就保证了这个对象在任何时候都是空的 export const emptyObject Object.freeze({}) /*** Check if a string starts with $ or _ ascii unicode 的区别 charcodeAt是一个字符的 unicode编码, 但是…

Tim Berners-Lee重新分散的新Web SOLID简介

by Arnav Bansal通过Arnav Bansal Tim Berners-Lee重新分散的新Web SOLID简介 (An introduction to SOLID, Tim Berners-Lee’s new, re-decentralized Web) Recently, Prof. Tim Berners-Lee lifted the veil off a project called Solid. I decided to check it out. In thi…

AngularJS2.0 教程系列(一)

Why Angular2 Angular1.x显然非常成功&#xff0c;那么&#xff0c;为什么要剧烈地转向Angular2&#xff1f; 性能的限制 AngularJS当初是提供给设计人员用来快速构建HTML表单的一个内部工具。随着时间的推移&#xff0c;各种特性 被加入进去以适应不同场景下的应用开发。然而由…

Vue组件绑定自定义事件

Vue组件使用v-on绑定自定义事件&#xff1a;   可以分为3步理解&#xff1a;     1.在组件模板中按照正常事件机制绑定事件&#xff1a;       template: <button v-on:click"increment">{{ counter }}</button>,       如上&#xff…

phpstudy本地调试运行TP5的后台源码

本地访问后台步骤&#xff1a; 1.打开 phpstudy 2.点击其它选项菜单 3.点击软件设置 4.点击端口常规设置 5.修改网站根目录为&#xff1a; C:\phpStudy\PHPTutorial\WWW\wxpet_2019\public phpstudy 切换php版本&#xff1a;5.6.27 public目录下的 .htacc…

如何使用TensorFlow Eager执行训练自己的FaceID ConvNet

by Thalles Silva由Thalles Silva Faces are everywhere — from photos and videos on social media websites, to consumer security applications like the iPhone Xs FaceID.人脸无处不在-从社交媒体网站上的照片和视频到iPhone Xs FaceID等消费者安全应用程序。 In this…

jquery判断一个元素是否为某元素的子元素

$(node).click(function(){if($(this).parents(.aa).length > 0){//是aa类下的子节点}else{//不是aa类下的子节点} });在判断点击body空白处隐藏弹出框时用到转载于:https://www.cnblogs.com/qdog/p/7067909.html

Sublime Text 3 (含:配置 C# 编译环境)

Sublime Text 3http://www.sublimetext.com/3http://www.sublimetext.com/3dev1. 关闭自动更新 菜单&#xff1a;Preferences->Settings User&#xff0c;打开User配置文档&#xff0c;在大括号内加入&#xff08;或更改&#xff09;&#xff1a; "update_check&q…

小程序仿安卓动画滑动效果滑动动画效果实现

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 效果图&#xff1a; 源码 var start_clientY; //记录当前滑动开始的值 var end_clientY; //记录当前滑动结束的值 var animation wx.createAnimation({duration: 400 }); //初始化动画var history_dis…

react中使用scss_我如何将CSS模块和SCSS集成到我的React应用程序中

react中使用scssby Max Goh由Max Goh 我如何将CSS模块和SCSS集成到我的React应用程序中 (How I integrated CSS Modules with SCSS into my React application) I recently started on an Isomorphic React project. I wanted to use this opportunity to utilize tools that …

-bash:syntax error near unexpected token '('

在Xshell5中编写int main(int argc,char** argv)时&#xff0c; 出现-bash:syntax error near unexpected token ( &#xff1b; 可是我是按照Linux语句编写的&#xff0c;其他代码没有出错&#xff1b; 检查发现&#xff0c; Xshell5对应的Linux版本是Linux5&#xff0c;在Li…

iOS手机 相册 相机(Picker Write)

把图片写到相册UIImageWriteToSavedPhotosAlbum(<#UIImage *image#>, nil, nil, nil); ————————————————————————————从相册&#xff0c;相机获取图像设置代理《UINavigationControllerDelegate, UIImagePickerControllerDelegate》 #pragm…

php删除指定对象的属性及属性值

微信小程序开发交流qq群 173683895 承接微信小程序开发。扫码加微信。 unset($address[/Api/User/addAddress]); 删除了 address 对象的 /Api/User/addAddress 属性