文章目录
- 源码:
- 分析笔记:
- 1.private String PreProcessData(String value)
- 2.private String GetStringByName(String rawJson, String keysName)
- 3.private String GetPhoneSize(String rawJson)
- 4.private String GetPhoneColor(String rawValue)
- 5.private boolean CheckData(String[] paramArr)
- 6.private String GenerateOutputData(String phoneBrand,String buyColor,String phoneSize)
- 7.protected void map(LongWritable key, Text value, Context context)
- 最后
源码:
(源码来自网络)
package testDemo;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
/**
* @Auther: lp
* @Date: 2018/10/16 16:04
* @Description:
*/
public class Phone_Map extends Mapper<LongWritable,Text,Text,NullWritable> {
Text text = new Text();
@Override
protected void map(LongWritable key, Text value, Context context) {
// 数据预处理
String rawValue = PreProcessData(value.toString());
try{
// 解析JSON格式数据,从数据中获取需要的字段
// 提取手机品牌名称
String phoneBrand = GetStringByName(rawValue, "phone_brand");
// 提取手机屏幕尺寸
String phoneSize = GetPhoneSize(rawValue);
// 提取用户购买手机颜色
String buyColor = GetPhoneColor(rawValue);
System.out.println(buyColor);
// 检查获取的数据,若为空,则认为是无效数据
String[] params = {phoneBrand, phoneSize, buyColor};
if(CheckData(params)){
String outputData = GenerateOutputData(phoneBrand, buyColor, phoneSize);
text.set(outputData);
//System.out.println(text);
context.write(text,NullWritable.get());
}
} catch (Exception e) {
return;
}
}
/**
* 清洗特殊字符|和\r,清洗规则如下:
* 1. 将|替换为-
* 2. 将换行符删除
* @param value
* @return 处理完成的数据
*/
private String PreProcessData(String value){
String retValue = value;
// 将|替换为-
retValue = value.toString().replace('|', '-');
// 将换行符删除
retValue = retValue.toString().replaceAll("\\r\\t", "");
return retValue;
}
/**
* 解析JSON格式数据,根据数如参数从JSON中提取目标字符串
* @param rawJson 原始JSON格式字符串
* @param keysName 目标数据key名称
* @return 提取到的字符串
*/
private String GetStringByName(String rawJson, String keysName){
JSONObject object = JSONObject.parseObject(rawJson);
if(object.containsKey(keysName)){
return object.getString(keysName).trim();
}
else{
return "";
}
}
/**
* 获取手机屏幕尺寸数据
* @param rawJson
* @return 手机屏幕尺寸数据
*/
private String GetPhoneSize(String rawJson){
// 获取parameter参数数据
String parameter = GetStringByName(rawJson, "parameter");
// 解析为数组
JSONArray arrParam = JSONArray.parseArray(parameter);
String keyName = "主屏幕尺寸(英寸)";
// 遍历数组,寻找目标数据
for(int iIndex = 0; iIndex < arrParam.size(); iIndex++){
String rawValue = GetStringByName(arrParam.get(iIndex).toString(), keyName);
if("" == rawValue.trim()){
continue;
}
else{
return rawValue;
}
}
return "";
}
/**
*
* @param rawValue
* @return String
*/
private String GetPhoneColor(String rawValue){
String jsonComments = GetStringByName(rawValue, "comments");
String buyColor = GetStringByName(jsonComments, "buy_color");
// System.out.println(jsonComments);
String[] arrColor = new String[]{"红","黑","白","金","蓝","黄","紫","绿","粉","银","灰","青"};
int iIndex = 0;
for ( ; iIndex < arrColor.length; iIndex++){
if (buyColor.contains(arrColor[iIndex])){
buyColor = arrColor[iIndex];
break;
}
}
if(arrColor.length == iIndex) {
buyColor = "其他";
}
return buyColor;
}
/**
* 检查获取到的数据是否存在空字符串
* @param paramArr
* @return 手机屏幕尺寸数据
*/
private boolean CheckData(String[] paramArr){
for(int iIndex = 0; iIndex < paramArr.length; iIndex++){
if("" == paramArr[iIndex].trim()){
return false;
}
}
return true;
}
/**
* 将数据按照要求的格式组装
* @param phoneBrand
* @param buyColor
* @param phoneSize
* @return 组装好的输出数据
*/
private String GenerateOutputData(String phoneBrand,String buyColor,String phoneSize){
return String.format("%s|%s|%s", phoneBrand, buyColor, phoneSize);
}
}
分析笔记:
1.private String PreProcessData(String value)
对读取的数据进行预处理;
主要功能为将字符’|‘替换为’-’,将换行符删除;
函数参数为String类型的kv对中的value值;
首先先用一个String类型的retValue接受传进来的值value;
再通过replace()函数将’|‘替换成’-’,返回值传给retValue;
利用replaceAll()函数将特殊字符串’\r\t’删掉;//经证明,replace()函数也可以实现该效果
最后将处理好的retValue作为函数的返回值;
2.private String GetStringByName(String rawJson, String keysName)
通过kv对的key获取value,并将结果返回;
函数参数为String类型的JSON内容的字符串和String类型的key内容的字符串;
首先用把String类型的rawJson通过一个JSONObject类型的变量object接收一下;//方便进行json类型的操作
再利用containsKey()函数判断key的内容是否为存在,如果存在,就返回相应的value值;
如果不存在就返回空字符串;
3.private String GetPhoneSize(String rawJson)
获取其中一个key对应的数据;
函数的参数是String类型的JSON内容的字符串rawJson;
创建一个String类型的变量parameter,其值为key为parameter的kv对的value;
再创建一个JSONArray类型的变量arrParam,用来存储获取的parameter值;//JSONArray结果格式类似Python的列表
定义我们要寻找的kv对的key,并给他一个变量名为keyName;
对JSONArray进行循环,查看keyName对应的value是否为空,若不为空则返回该值,否则返回空字符串;
4.private String GetPhoneColor(String rawValue)
获取其中另外一个key对应的数据;理论上可以和上一个函数写成差不多的逻辑,但是这个函数有点意思;
函数参数为String类型的rawValue;
首先创建一个String类型的jsonComments变量用来存储key为comments的kv对的value;
创建一个String类型的buyColor变量存储key为buy_color的kv对的value;
然后定义了一个arrColor字符串数组,用来存放所有指定的值,也就是说你获得值只能从这里边选,不会出现无效值,若出现无效值,也是可控的无效值;
对arrColor数组进行循环,对buycolor和给定的颜色数组进行比对与赋值;
如果没有可以匹配的颜色就赋值为‘其他’;
将buyColor进行返回;
(这真的是这个类里边我最喜欢的函数!真的逻辑太妙了!星星眼)
5.private boolean CheckData(String[] paramArr)
检查数据;主要是判空;
参数为名为paramArr的String数组;//参考前边的函数及变量的命名方式,这应该是尺寸的那个数组;
对数据数组进行循环,如果值是空的就返回false,如果不是空的就返回true;
6.private String GenerateOutputData(String phoneBrand,String buyColor,String phoneSize)
按照要求格式整理字符串;
参数是String类型的phoneBrand,String类型的buyColor,String类型的phoneSize;
直接利用String.format()函数对字符串格式化,并返回;
7.protected void map(LongWritable key, Text value, Context context)
最后就是这个map;为啥最后再说它呢,因为它主要是调用了各种上述函数;
函数的参数有LongWritable类型的key,Text类型的value,Context类型的context;这个应该是继承Mapper类之后必须要重写的方法;
首先我们定义了一个String类型的rawValue,用来接收预处理后的value数据;
用String类型的phoneBrand变量接收key为phone_brand的value值;//此时的value值已经通过用户自定义函数GetStringByName()变成了String类型
用String类型的phoneSize变量接收执行了用户自定义函数GetPhoneSize()后的结果;
用String类型的buyColor变量接收执行了用户自定义函数GetPhoneColor()后的结果;
在控制台输出了buyColor这个变量;//个人感觉这个应该是测试数据吧hhhh
定义了一个String类型的数组params,其内容是前边我们获取的phoneBrand,phoneSize,buyColor;
对该数组进行判空,如果非空,就用用户自定义函数GenerateOutputData()对数据进行整合,整合为指定格式,再利用context.write()函数返回最后的数据;
最后
- 注意:每行数据都会进行一次map,所以如果想把上述函数具体化的话,可以想象只有一行数据,对该行数据进行处理;
- 温馨提示:本人也是小白菜,分析仅供参考,如有错误请指出!谢谢!!