超简单方法实现省/市/地区级联查询

本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/48829517 未经博主允许不得转载。
博主地址是:http://blog.csdn.net/freewebsys

1,关于中国地址

开发业务的时候遇到一个问题

需要弄一个省、市,地区的级联查询。
页面好做,但是数据不太好弄,不好组织。
开始考虑抓一个现成的数据库,存储成表机构,然后查询。
发现这个是一个效率比较低的方案,但维护起来比较好。
直接对数据库进行操作行了。

2,一个简单的方案

首先要招到数据源:
从中国统计局页面拷贝数据:
http://www.stats.gov.cn
http://www.stats.gov.cn/was5/web/search?channelid=288041&andsen=行政区划
结果页面
http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201504/t20150415_712722.html

将数据拷贝到一个district.data.dic文本里面。
邮政编码一共6位,1-2位代表省,3-4位代表市,5-6位代表区/县。
所以,可以直接将这个数据存储成一个3级树形结构。

3,代码实现

首先判断 1-2位,找到1级省。
然后找到3-4位,判断市,最后5-6位是区/县。


import com.google.common.base.Strings;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DistrictUtils {

    static class Tree {
        private String code;
        private String name;
        private Map<String, Tree> children = new HashMap<String, Tree>();

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Map<String, Tree> getChildren() {
            return children;
        }

        public void addChildrenTree(String childrenCode, Tree childrenTree) {
            this.children.put(childrenCode, childrenTree);
        }

    }

    private static Map<String, Tree> addressTreeMap = new HashMap<String, Tree>();

    static {
        try {
            // 取得运行时路径
            String basePath = DistrictUtils.class.getResource("/")
                    .toString().replace("file:", "");
            System.out.println(basePath);
            List<String> lines = Files.readAllLines(new File(basePath + "district.data.dic").toPath(), Charset.forName("utf-8"));
            //循环数据。
            for (String line : lines) {
                if (!Strings.isNullOrEmpty(line) && line.length() > 7) {
                    String code = line.substring(0, 6);
                    String name = line.substring(7);
                    //里面包括了1种特殊的空格(\u3000特殊的中文空格!!!)。
                    name = name.replaceAll("\t", "").replaceAll("\\u3000", "").replaceAll(" ", "");
                    String codeTmp1 = code.substring(0, 2);
                    String codeTmp2 = code.substring(2, 4);
                    String codeTmp3 = code.substring(4, 6);
                    //找到根节点。
                    if (codeTmp2.equals("00") && codeTmp3.equals("00")) {
                        Tree baseTree = new Tree();
                        baseTree.setCode(code);
                        baseTree.setName(name);
                        addressTreeMap.put(code, baseTree);
                    } else if (codeTmp3.equals("00")) {//找到二级节点
                        Tree secondTree = new Tree();
                        secondTree.setCode(code);
                        secondTree.setName(name);
                        //找到根节点,然后增加子树。
                        Tree baseTree = addressTreeMap.get(codeTmp1 + "0000");
                        if (baseTree != null) {
                            baseTree.addChildrenTree(code, secondTree);
                        } else {
                            System.err.println("no tree " + codeTmp1 + "0000");
                        }
                    } else {//剩下是3级节点。
                        Tree thirdTree = new Tree();
                        thirdTree.setCode(code);
                        thirdTree.setName(name);
                        //找到根节点。
                        Tree baseTree = addressTreeMap.get(codeTmp1 + "0000");
                        //然后找到二级节点,再增加子树。
                        Tree secondTree = baseTree.getChildren().get(codeTmp1 + codeTmp2 + "00");
                        if (secondTree != null) {
                            secondTree.addChildrenTree(code, thirdTree);
                        } else {
                            System.err.println("no tree " + codeTmp1 + codeTmp2 + "00");
                        }
                    }
                }

            }
        } catch (Exception e) {

        }
    }

    public static void loopTree(Tree addressTree, int level) {
        for (int i = 0; i < level; i++) {
            System.out.print("├─");
        }
        System.out.printf("[%s][%s]\n", addressTree.getCode(), addressTree.getName());
        int nextLevel = level + 1;
        for (Tree addressTreeTemp : addressTree.getChildren().values()) {
            loopTree(addressTreeTemp, nextLevel);
        }
    }

    public static void main(String[] args) {
        System.out.println();
        System.out.println();
        for (Tree addressTree : addressTreeMap.values()) {
            loopTree(addressTree, 1);
        }
    }
}

运行结果:

├─[120000][天津市]
├─├─[120100][市辖区]
├─├─├─[120102][河东区]
├─├─├─[120103][河西区]
├─├─├─[120104][南开区]
├─├─├─[120105][河北区]
├─├─├─[120101][和平区]
├─├─├─[120112][津南区]
├─├─├─[120111][西青区]
├─├─├─[120110][东丽区]
├─├─├─[120116][滨海新区]
├─├─├─[120106][红桥区]
├─├─├─[120115][宝坻区]
├─├─├─[120114][武清区]
├─├─├─[120113][北辰区]
├─├─[120200][县]
├─├─├─[120225][蓟县]
├─├─├─[120223][静海县]
├─├─├─[120221][宁河县]
├─[110000][北京市]
├─├─[110200][县]
├─├─├─[110229][延庆县]
├─├─├─[110228][密云县]
├─├─[110100][市辖区]
├─├─├─[110114][昌平区]
├─├─├─[110115][大兴区]
├─├─├─[110116][怀柔区]
├─├─├─[110117][平谷区]
├─├─├─[110108][海淀区]
├─├─├─[110111][房山区]
├─├─├─[110107][石景山区]
├─├─├─[110112][通州区]
├─├─├─[110113][顺义区]
├─├─├─[110109][门头沟区]
├─├─├─[110106][丰台区]
├─├─├─[110105][朝阳区]
├─├─├─[110102][西城区]
├─├─├─[110101][东城区]
......

这里面有个坑,找了半天才发现,国家统计局里面使用了一个非常特殊的中文空格,咋进行字符串过滤都去不掉。
就是字符 \u3000 ,这个也是一个空字符串。直接晕死!!!
转码才发现的:
http://tool.oschina.net/encode?type=3

4,总结

本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/48829517 未经博主允许不得转载。
博主地址是:http://blog.csdn.net/freewebsys

思路还是对的,中间遇到一个特殊空格的问题。
直接把这个树存储到内存,第一次加载使用,不用查询数据库了。
而且统计局这个数据更新的也比较慢,也就几年一次,够用了。
对于查询,同样的按照 1-2 , 3-4, 5-6 3级数据查询即可。

时间: 2024-10-13 16:15:49

超简单方法实现省/市/地区级联查询的相关文章

javascript之IE版本检测超简单方法_javascript技巧

近年来随着操作系统的升级以及各种新技术的开发普及,抛弃低版本IE已经是大势所趋,这对于前端人员来时是个好消息,可以不用花费太多的时间来做低版本的兼容,很多站点采用给予低版本IE以提示的方式(恩,很友好很人道)给游客,一般是在header上给一个提示,脚本检测如下: function getIEVersion() { var rv = -1; // Return value assumes failure. if(navigator.appName == 'Microsoft Internet E

PHP实现页面静态化的超简单方法_php实例

为什么要页面静态化? 1.动态文件执行过程:语法分析-编译-运行 2.静态文件,不需要编译,减少了服务器脚本运行的时间,降低了服务器的响应时间,直接运行,响应速度快:如果页面中一些内容不经常改动,动态页面静态化是非常有效的加速方法.(纯静态,伪静态还是需要PHP解释器的) 3.生成静态URL利于SEO,利于蜘蛛抓取和收录,有利于提升排名 优化页面响应时间方法 1.动态页面静态化 2.优化数据库 3.负载均衡 4.使用缓存等等 //动态页面静态化一般用于不经常改动的地方,频繁改动的地方一般不适用静

PHP实现页面静态化的超简单方法

为什么要页面静态化? 1.动态文件执行过程:语法分析-编译-运行 2.静态文件,不需要编译,减少了服务器脚本运行的时间,降低了服务器的响应时间,直接运行,响应速度快:如果页面中一些内容不经常改动,动态页面静态化是非常有效的加速方法.(纯静态,伪静态还是需要PHP解释器的) 3.生成静态URL利于SEO,利于蜘蛛抓取和收录,有利于提升排名 优化页面响应时间方法 1.动态页面静态化 2.优化数据库 3.负载均衡 4.使用缓存等等 //动态页面静态化一般用于不经常改动的地方,频繁改动的地方一般不适用静

QQ登录窗口里粘贴QQ密码的超简单方法

QQ为了保护用户密码的安全,不允许在登录窗口中粘贴QQ密码.不管是用Ctrl+V,还是点右键粘贴都不行. 可有时我们还是有在QQ登录窗口粘贴密码的需要.那么就告诉你一种在QQ登录窗口粘贴密码的超级简单方法吧: 1.复制QQ密码,让它在内存里存着 2.在QQ登录窗口的密码输入框中点一下 3.按下Shift+F10 4.松开F10(Shift按住不放),再按下P键(或者用鼠标点"粘贴") 成功!密码粘贴进去了.哈哈!简单吧

Android中引用其他程序的文本资源超简单方法

在Android中引用其他程序的文本资源并不是很常见,但是有时候还是很是有需要的,通常引用的多半是系统的程序的文本资源. 下面以一个超简单的例子,来展示以下如何实现. 复制代码 代码如下: public void testUseAndroidString() { Context context = getContext();     Resources res = null;     try {         //I want to use the clear_activities strin

php下实现伪 url 的超简单方法[转]_php实例

就像我的日志中的地址路径一样,让 index.php?action=one&do=two  变成: ?index/action/one/do/two 复制代码 代码如下: index.php -------------- <?php // PARSING QUERY STRING $QS=explode("&",$_SERVER['QUERY_STRING']); $QS=explode('/',$QS[0]); // IF Modul is Undefined 

使用纯JS代码判断字符串中有多少汉字的实现方法(超简单实用)_javascript技巧

在网站开发中,经常会简单使用js代码来判断字符串中有多少汉字的功能.今天小编抽时间给大家分享实现代码.废话不多说了,直接给大家贴代码了. $("form").submit(function () { var content = editor.getContentTxt(); var sum = 0; re = /[\u4E00-\u9FA5]/g; //测试中文字符的正则 if (content) { if (re.test(content)) //使用正则判断是否存在中文 { if

python实现超简单端口转发的方法_python

本文实例讲述了python实现超简单端口转发的方法.分享给大家供大家参考.具体如下: 代码非常简单,实现了简单的端口数据转发功能,用于真实环境还需要再修改一下. 复制代码 代码如下: #tcp server import socket host = '127.0.0.1'          #Local Server IP host2 = '127.0.0.1'   #Real Server IP port = 6001 #Local Server Port port2 = 7001 #Real

jquery超简单实现手风琴效果的方法_jquery

本文实例讲述了jquery超简单实现手风琴效果的方法.分享给大家供大家参考.核心代码如下: $("#accordion .expanded").hide(); $("a.opening").click(function(){ $(this).next().slideToggle('fast', function(){ $(this).prev("a.opening").toggleClass("active"); }); re