版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_34168157/article/details/81567978
1、需求:
前两天接到boss给我的一个任务,需要根据经纬度信息统计省份分布,boss给了我一张excel,包含数据包括:经度、纬度、使用次数,想要我统计每一个省份的次数之后
2、解决思路:
通过文件读取方式获得对应经度、纬度、使用次数数据,,然后调用阿里云或者高德地图的API就可以完成这一工作,思路很清晰,于是下面直接开始上代码
3、工具类:
StringToJsonUtil.java
**
* 通过工具类去获取String里面包含的数据信息
* User: yinkailong
* Date: 2018/8/10
*/
public class StringToJsonUtil {
public static String StringToGetValue(String address){
String detailAddress = "";
//调用阿里云接口返回数据格式
/**res{"queryLocation":[28.76817,121.501497],"addrList":[{"type":"poi","status":1,"name":"尤氏大药房(杜东药店)","id":"ANB02400T4ZW","admCode":"331082","admName":"浙江省,台州市,临海市,","addr":"杜桥解放街96号","nearestPoint":[121.50180,28.76764],"distance":61.400}]}*/
//进行转化获取值
JSONObject addressList = JSONObject.fromObject(address);
//次处需要判断转化之后类型是否是Object 否则会报错
if (addressList != null && !addressList.isNullObject()){
//System.out.println("addressList" + addressList);
//根据addrList 获取list值 //得到json数组
JSONArray addressArray = JSONArray.fromObject(addressList.getString("addrList"));
JSONObject addressObject = JSONObject.fromObject(addressArray.get(0));
//根据admName 获取省、市、区
String admName = addressObject.getString("admName");
//获取店铺名称
String name = addressObject.getString("name");
//获取门牌号地址
String addr = "";
if (addressObject.containsKey("addr")){
addr = addressObject.getString("addr");
}
//进行拼接得到详细地址
detailAddress = admName + name + addr;
//将查询的地址输出 过滤掉 ,
//System.out.println(detailAddress.replace(",", ""));
}
return detailAddress;
}
}
根据纬度和经度调用阿里云API 获取详细地址
AddressUtil.java
/**
* 调取阿里云的API
* User: yinkailong
* Date: 2018/8/7
*/
public class AddressUtil {
/**
* 调取阿里云的API
* 通过 poi 经纬度查询地址数据
*
* @param lat 必传
* @param lng 必传
* @return
*/
public static String getAddress(String lat, String lng) {
if (lat.contains("-") || lng.contains("-")) {
return "null";
}
//参数解释: 纬度,经度 type 001 (100代表道路,010代表POI,001代表门址,111可以同时显示前三项)
String urlString = "http://gc.ditu.aliyun.com/regeocoding?l=" + lng + "," + lat + "&type=010";
String res = "";
try {
//读取url请求地址 这里读取的是阿里云的查询
URL url = new URL(urlString);
//打开连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//设置参数编码
conn.setRequestMethod("POST");
//设置输出属性
conn.setDoOutput(true);
//设置缓存
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line = "";
//读取的下一行是否为空
while ((line = in.readLine()) != null) {
res += line + "\n";
}
//关闭缓冲流
in.close();
} catch (Exception e) {
System.out.println("读取过程中发生异常,请重试!!");
}
System.out.println("res" + res);
return res;
}
读取Excel文件然后进行获取值
ReadExcelUtil.java
/**
* 读取Excel文件然后调用
* User: yinkailong
* Date: 2018/8/7
*/
public class ReadExcelUtil {
public static List<String> readExcel(File file) throws IOException {
//TODO 存储 省份和使用次数的map,便于返回后面做特殊需求统计
List<String> addressAndTime = new ArrayList<>();
InputStream filaName= new FileInputStream(file);
//获取文件名称
String fileName = file.getName();
//获取文件名的后缀
int start = fileName.lastIndexOf(".");
int length = fileName.length();
//得到文件名的后缀
String lastTag = fileName.substring(start + 1, length);
//创建读取文件的WebBook
Workbook workbook = null;
//判断使用文件解析类型
// 根据文件名的后缀来判断使用判断文件后缀名是xls ,还是xlsx。
// 如果是xls使用HSSFWorkbook,否则使用XSSFWorkbook解析
if (lastTag.equals("xlsx")) {
//解析xls解析格式
workbook = new XSSFWorkbook(filaName);
} else if (lastTag.equals("xls")) {
workbook = new HSSFWorkbook(filaName);
} else {
//暂不支持的excel格式后缀
return Lists.newArrayListWithCapacity(0);
}
Sheet sheet = workbook.getSheetAt(0);//第一个工作表 ,第二个则为1,以此类推...
int firstRowIndex = sheet.getFirstRowNum();
int lastRowIndex = sheet.getLastRowNum();
for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) {
Row row = sheet.getRow(rIndex);
if (row != null) {
int firstCellIndex = row.getFirstCellNum();
// int lastCellIndex = row.getLastCellNum(); //次处暂时不用
String values = "";
for (int cIndex = firstCellIndex; cIndex < 3; cIndex++) {
Cell cell = row.getCell(cIndex);
String value = "";
if (cell != null) {
value = cell.toString();
values += value + ",";
}
if (value.length() == 3) {
String[] split = values.split(",");
String address = "";
if (split.length >= 2) {
address = AddressUtil.getAddress(split[0], split[1]);
JSONObject addressList = JSONObject.fromObject(address);
if (addressList != null && !addressList.isNullObject()) {
JSONArray addressArray = JSONArray.fromObject(addressList.getString("addrList"));
JSONObject addressObject = JSONObject.fromObject(addressArray.get(0));
//根据admName 获取省、市、区
String admName = addressObject.getString("admName");
String arr[] = admName.split(",");
if (values.split(",").length >= 3) {
addressAndTime.add(arr[0] + "," + values.split(",")[2]);
}
}
}
}
}
}
}
return addressAndTime;
}
4、测试方法
//调用main方法获取输出值
public static void main(String[] args) throws IOException {
//读取本地Excel文件 格式如下 100.228635 25.589721 3.0
File file = new File("D:/jingweidu.xlsx");
List<String> addressAndTime = readExcel(file);
//进行截取然后进行判断相加
double T = 0.0d;
String province = "";
HashMap<String,Double> provinceAndTime = new HashMap<>();
// TODO 特殊需求,根据省份相同进行统计使用次数
for (String subString : addressAndTime){
String[] splits = subString.split(",");
province = splits[0];
double time = Double.valueOf(splits[1]);
if (provinceAndTime.containsKey(province)){
T += time;
provinceAndTime.put(province,T);
}else if (province != null && !"".equals(province)){
provinceAndTime.put(province,time);
}
}
System.out.println(provinceAndTime);
}
}
以前的测试方法有误,现在重新改进写法
//调用main方法获取输出值
public static void main(String[] args) throws IOException {
//读取本地Excel文件 格式如下 100.228635 25.589721 3.0
File file = new File("D:/jingweidu.xlsx");
List<String> addressAndTime = readExcel(file);
//进行截取然后进行判断相加
double T = 0.0d;
String province = "";
HashMap<String, Double> provinceAndTime = new HashMap<>();
// TODO 特殊需求,根据省份相同进行统计使用次数
for (String subString : addressAndTime) {
String[] splits = subString.split(",");
province = splits[0];
double time = Double.parseDouble(splits[1]);
if (provinceAndTime.containsKey(province)) {
double value = provinceAndTime.get(province) + time;
provinceAndTime.put(province, value);
} else if (province != null && !"".equals(province)) {
provinceAndTime.put(province, time);
}
}
System.out.println(provinceAndTime);
List<Map.Entry<String, Double>> infoIds = new ArrayList<Map.Entry<String, Double>>(
provinceAndTime.entrySet());
System.out.println("--------------排序前--------------");
for (int i = 0; i < infoIds.size(); i++) {
String id = infoIds.get(i).toString();
System.out.println(id);
}
// 排序
Collections.sort(infoIds, new Comparator<Map.Entry<String, Double>>() {
public int compare(Map.Entry<String, Double> o1,
Map.Entry<String, Double> o2) {
return (int) (o1.getValue() - o2.getValue());
}
});
System.out.println("--------------排序后--------------");
for (int i = 0; i < infoIds.size(); i++) {
Map.Entry<String, Double> ent = infoIds.get(i);
System.out.println(ent.getKey() + "=" + ent.getValue());
}
}
}
5、运行结果:
6、采坑总结
1、Excel文件读取需要主要 后缀格式不同,调用的方法不同,
// 根据文件名的后缀来判断使用判断文件后缀名是xls ,还是xlsx。
// 如果是xls使用HSSFWorkbook,否则使用XSSFWorkbook解析
if (lastTag.equals("xlsx")) {
//解析xls解析格式
workbook = new XSSFWorkbook(filaName);
} else if (lastTag.equals("xls")) {
workbook = new HSSFWorkbook(filaName);
} else {
//暂不支持的excel格式后缀
return Lists.newArrayListWithCapacity(0);
}
2、在得到API调用结果之后返回值,需要进行判断,否则会导致后面获取结果报错,使用方法 isNullObject进行校验
//进行转化获取值
JSONObject addressList = JSONObject.fromObject(address);
//次处需要判断转化之后类型是否是Object 否则会报错
if (addressList != null && !addressList.isNullObject()){
}
3、获取 属性 addrList字段时候需要进行判断 是否存在当前属性,否则会报错,因为返回值里面不一定包含字段addr
if (addressObject.containsKey("addr")){
addr = addressObject.getString("addr");
}
4、数据截取时需要进行校验,否则可能出现下标越出错误
if (values.split(",").length >= 3) {
addressAndTime.add(arr[0] + "," + values.split(",")[2]);
}