Java实现省份城市列表的排序、存储与展示

下面我将提供一个完整的Java实现方案,包括数据结构设计、排序算法、数据存储和展示功能。

1. 数据结构设计

首先定义一个省份(Province)和城市(City)的类结构:

java

复制

public class Province implements Comparable<Province> {
    private String code; // 省份编码
    private String name; // 省份名称
    private List<City> cities; // 城市列表
    
    // 构造方法、getter和setter省略
    
    @Override
    public int compareTo(Province o) {
        return this.name.compareTo(o.getName());
    }
}

public class City implements Comparable<City> {
    private String code; // 城市编码
    private String name; // 城市名称
    private String provinceCode; // 所属省份编码
    
    // 构造方法、getter和setter省略
    
    @Override
    public int compareTo(City o) {
        return this.name.compareTo(o.getName());
    }
}

2. 数据存储实现

2.1 内存存储方案

java

复制

public class ProvinceCityStorage {
    private Map<String, Province> provinceMap = new HashMap<>();
    private Map<String, City> cityMap = new HashMap<>();
    
    // 添加省份
    public void addProvince(Province province) {
        provinceMap.put(province.getCode(), province);
    }
    
    // 添加城市
    public void addCity(City city) {
        cityMap.put(city.getCode(), city);
        Province province = provinceMap.get(city.getProvinceCode());
        if (province != null) {
            province.getCities().add(city);
        }
    }
    
    // 获取所有省份(已排序)
    public List<Province> getAllProvinces() {
        List<Province> provinces = new ArrayList<>(provinceMap.values());
        Collections.sort(provinces);
        return provinces;
    }
    
    // 获取某省份下的所有城市(已排序)
    public List<City> getCitiesByProvince(String provinceCode) {
        Province province = provinceMap.get(provinceCode);
        if (province != null) {
            List<City> cities = new ArrayList<>(province.getCities());
            Collections.sort(cities);
            return cities;
        }
        return Collections.emptyList();
    }
}

2.2 数据库存储方案(使用JDBC)

java

复制

public class ProvinceCityDBStorage {
    private Connection connection;
    
    public ProvinceCityDBStorage(String dbUrl, String user, String password) throws SQLException {
        this.connection = DriverManager.getConnection(dbUrl, user, password);
    }
    
    // 初始化表结构
    public void initTables() throws SQLException {
        try (Statement stmt = connection.createStatement()) {
            stmt.execute("CREATE TABLE IF NOT EXISTS provinces (" +
                         "code VARCHAR(10) PRIMARY KEY, " +
                         "name VARCHAR(50) NOT NULL)");
            
            stmt.execute("CREATE TABLE IF NOT EXISTS cities (" +
                         "code VARCHAR(10) PRIMARY KEY, " +
                         "name VARCHAR(50) NOT NULL, " +
                         "province_code VARCHAR(10) NOT NULL, " +
                         "FOREIGN KEY (province_code) REFERENCES provinces(code))");
        }
    }
    
    // 添加省份
    public void addProvince(Province province) throws SQLException {
        String sql = "INSERT INTO provinces (code, name) VALUES (?, ?)";
        try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
            pstmt.setString(1, province.getCode());
            pstmt.setString(2, province.getName());
            pstmt.executeUpdate();
        }
    }
    
    // 添加城市
    public void addCity(City city) throws SQLException {
        String sql = "INSERT INTO cities (code, name, province_code) VALUES (?, ?, ?)";
        try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
            pstmt.setString(1, city.getCode());
            pstmt.setString(2, city.getName());
            pstmt.setString(3, city.getProvinceCode());
            pstmt.executeUpdate();
        }
    }
    
    // 获取所有省份(已排序)
    public List<Province> getAllProvinces() throws SQLException {
        String sql = "SELECT code, name FROM provinces ORDER BY name";
        List<Province> provinces = new ArrayList<>();
        
        try (Statement stmt = connection.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            while (rs.next()) {
                Province province = new Province();
                province.setCode(rs.getString("code"));
                province.setName(rs.getString("name"));
                provinces.add(province);
            }
        }
        return provinces;
    }
    
    // 获取某省份下的所有城市(已排序)
    public List<City> getCitiesByProvince(String provinceCode) throws SQLException {
        String sql = "SELECT code, name FROM cities WHERE province_code = ? ORDER BY name";
        List<City> cities = new ArrayList<>();
        
        try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
            pstmt.setString(1, provinceCode);
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    City city = new City();
                    city.setCode(rs.getString("code"));
                    city.setName(rs.getString("name"));
                    city.setProvinceCode(provinceCode);
                    cities.add(city);
                }
            }
        }
        return cities;
    }
}

3. 排序功能实现

3.1 基础排序(按名称)

java

复制

// 在Province和City类中已经实现了Comparable接口
// 可以直接使用Collections.sort()方法排序
List<Province> provinces = storage.getAllProvinces(); // 已排序
List<City> cities = storage.getCitiesByProvince("BJ"); // 已排序

3.2 自定义排序(按编码)

java

复制

// 按编码排序的比较器
public class CodeComparator implements Comparator<Province> {
    @Override
    public int compare(Province p1, Province p2) {
        return p1.getCode().compareTo(p2.getCode());
    }
}

// 使用方式
List<Province> provinces = storage.getAllProvinces();
provinces.sort(new CodeComparator());

3.3 多条件排序(先按省份再按城市)

java

复制

public class ProvinceCityComparator implements Comparator<City> {
    private Map<String, Province> provinceMap;
    
    public ProvinceCityComparator(Map<String, Province> provinceMap) {
        this.provinceMap = provinceMap;
    }
    
    @Override
    public int compare(City c1, City c2) {
        // 先按省份名称排序
        int provinceCompare = provinceMap.get(c1.getProvinceCode()).getName()
                            .compareTo(provinceMap.get(c2.getProvinceCode()).getName());
        if (provinceCompare != 0) {
            return provinceCompare;
        }
        // 省份相同再按城市名称排序
        return c1.getName().compareTo(c2.getName());
    }
}

// 使用方式
List<City> allCities = getAllCitiesFromStorage(); // 获取所有城市
allCities.sort(new ProvinceCityComparator(provinceMap));

4. 数据展示实现

4.1 控制台展示

java

复制

public class ConsoleDisplay {
    public static void displayProvinces(List<Province> provinces) {
        System.out.println("=== 省份列表 ===");
        for (Province province : provinces) {
            System.out.printf("%s (%s)%n", province.getName(), province.getCode());
        }
    }
    
    public static void displayCities(List<City> cities) {
        System.out.println("=== 城市列表 ===");
        for (City city : cities) {
            System.out.printf("%s (%s)%n", city.getName(), city.getCode());
        }
    }
    
    public static void displayProvinceWithCities(Province province) {
        System.out.printf("=== %s (%s) 的城市列表 ===%n", 
                         province.getName(), province.getCode());
        for (City city : province.getCities()) {
            System.out.printf("  - %s (%s)%n", city.getName(), city.getCode());
        }
    }
}

4.2 HTML展示(使用JSP)

jsp

复制

<%@ page import="java.util.List" %>
<%@ page import="com.example.Province" %>
<%@ page import="com.example.City" %>

<!DOCTYPE html>
<html>
<head>
    <title>省份城市列表</title>
    <style>
        .province { margin-bottom: 20px; border: 1px solid #ccc; padding: 10px; }
        .city { margin-left: 20px; }
    </style>
</head>
<body>
    <h1>中国省份城市列表</h1>
    
    <% List<Province> provinces = (List<Province>) request.getAttribute("provinces"); %>
    
    <% for (Province province : provinces) { %>
        <div class="province">
            <h2><%= province.getName() %> (<%= province.getCode() %>)</h2>
            <div class="city-list">
                <% List<City> cities = province.getCities(); %>
                <% for (City city : cities) { %>
                    <div class="city">
                        <%= city.getName() %> (<%= city.getCode() %>)
                    </div>
                <% } %>
            </div>
        </div>
    <% } %>
</body>
</html>

5. 完整示例应用

java

复制

public class ProvinceCityApp {
    public static void main(String[] args) {
        // 1. 初始化存储
        ProvinceCityStorage storage = new ProvinceCityStorage();
        
        // 2. 添加测试数据
        Province bj = new Province("BJ", "北京");
        Province sh = new Province("SH", "上海");
        Province gd = new Province("GD", "广东");
        
        storage.addProvince(bj);
        storage.addProvince(sh);
        storage.addProvince(gd);
        
        storage.addCity(new City("BJ01", "东城区", "BJ"));
        storage.addCity(new City("BJ02", "西城区", "BJ"));
        storage.addCity(new City("SH01", "黄浦区", "SH"));
        storage.addCity(new City("SH02", "徐汇区", "SH"));
        storage.addCity(new City("GD01", "广州市", "GD"));
        storage.addCity(new City("GD02", "深圳市", "GD"));
        
        // 3. 获取并展示数据
        List<Province> provinces = storage.getAllProvinces();
        ConsoleDisplay.displayProvinces(provinces);
        
        System.out.println();
        ConsoleDisplay.displayProvinceWithCities(bj);
        
        // 4. 自定义排序展示
        System.out.println("\n=== 按编码排序的省份 ===");
        provinces.sort(new CodeComparator());
        ConsoleDisplay.displayProvinces(provinces);
        
        // 5. 获取所有城市并按省份+城市名排序
        List<City> allCities = new ArrayList<>();
        for (Province p : provinces) {
            allCities.addAll(storage.getCitiesByProvince(p.getCode()));
        }
        
        System.out.println("\n=== 所有城市(按省份+城市名排序) ===");
        allCities.sort(new ProvinceCityComparator(storage.getProvinceMap()));
        for (City city : allCities) {
            Province p = storage.getProvinceMap().get(city.getProvinceCode());
            System.out.printf("%s - %s%n", p.getName(), city.getName());
        }
    }
}

6. 高级功能扩展

6.1 使用Java Stream API进行复杂查询

java

复制

// 查找名称包含"州"的城市
List<City> zhouCities = storage.getAllCities().stream()
    .filter(c -> c.getName().contains("州"))
    .sorted(Comparator.comparing(City::getName))
    .collect(Collectors.toList());

// 按省份分组统计城市数量
Map<String, Long> cityCountByProvince = storage.getAllCities().stream()
    .collect(Collectors.groupingBy(City::getProvinceCode, Collectors.counting()));

6.2 使用JSON格式输出

java

复制

public class JsonUtil {
    private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
    
    public static String toJson(List<?> list) {
        return gson.toJson(list);
    }
}

// 使用方式
String provincesJson = JsonUtil.toJson(storage.getAllProvinces());
System.out.println(provincesJson);

6.3 添加缓存机制

java

复制

public class CachedProvinceCityStorage extends ProvinceCityStorage {
    private List<Province> cachedProvinces;
    private Map<String, List<City>> cachedCities = new HashMap<>();
    
    @Override
    public List<Province> getAllProvinces() {
        if (cachedProvinces == null) {
            cachedProvinces = super.getAllProvinces();
        }
        return cachedProvinces;
    }
    
    @Override
    public List<City> getCitiesByProvince(String provinceCode) {
        if (!cachedCities.containsKey(provinceCode)) {
            cachedCities.put(provinceCode, super.getCitiesByProvince(provinceCode));
        }
        return cachedCities.get(provinceCode);
    }
    
    public void clearCache() {
        cachedProvinces = null;
        cachedCities.clear();
    }
}
/**
     * 根据省Id获取城市列表
     * @date 2015-4-3 下午3:45:21
     */
    private List<Map<String, Object>> getCitiesByProvinceId(String provinceId) {
        // 一个省的所有城市集合 List<市信息>
        List<Map<String, Object>> comCityResultList = new ArrayList<Map<String, Object>>();

        // 根据省ID查询该省的所有城市
        List<ComCity> comCityList = placeCityService.getCityListByProvinceId(provinceId);
        for (ComCity comCity : comCityList) {
            if(null == comCity || StringUtils.isBlank(comCity.getCityId())) {
                continue;
            }
            // 封装城市信息集合
            Map<String, Object> comCityMap = new HashMap<String, Object>();
            comCityResultList.add(comCityMap);
            comCityMap.put("key", comCity.getCityId());
            comCityMap.put("value", comCity.getCityName());
        }
        // 按城市拼音进行排序
        Collections.sort(comCityResultList, provinceComparator);
        // 排序完成后将【请选择】选项放入列表
        Map<String, Object> noneComCityMap = new HashMap<String, Object>();
        noneComCityMap.put("key", "");
        noneComCityMap.put("value", "请选择");
        comCityResultList.add(0, noneComCityMap);
        
        return comCityResultList;
    }



/**
     * 对省份按照拼音进行排序
     * @date 2015-5-11 下午6:11:50
     */
    private List<Map<String, Object>> sort(List<Map<String, Object>> provinceList) {
        Collections.sort(provinceList, provinceComparator);
        // 直辖市列表
        Map<String, Map<String, Object>> municipalityMap = new HashMap<String, Map<String, Object>>();
        // 特别行政区列表
        Map<String, Map<String, Object>> SARMap = new HashMap<String, Map<String, Object>>();
        
        List<String> municipalityList = new ArrayList<String>();
        municipalityList.add("110000");// 北京市
        municipalityList.add("310000");// 上海
        municipalityList.add("500000");// 重庆
        municipalityList.add("120000");// 天津
        
        List<String> SARList = new ArrayList<String>();
        SARList.add("F10000");// 香港
        SARList.add("F20000");// 澳门
        SARList.add("F30000");// 台湾
        
        // 该列表在循环完成后,将不包含直辖市、特别行政区
        List<Map<String, Object>> newProvinceList = new ArrayList<Map<String, Object>>();
        for (Map<String, Object> vo : provinceList) {
            String key = vo.get("key").toString();
            // 直辖市放到专门的直辖市集合中
            if(municipalityList.contains(key)) {
                municipalityMap.put(key, vo);
                continue;
            }
            // 特别行政区放到专门的特别行政区集合中
            if(SARList.contains(key)) {
                SARMap.put(key, vo);
                continue;
            }
            // 非特别行政区、直辖市
            newProvinceList.add(vo);
        }
        // 将直辖市按照北京>上海>天津>重庆的先后顺序放到列表中
        if(null != municipalityMap.get("500000")) {
            newProvinceList.add(0, municipalityMap.get("500000"));
        }
        if(null != municipalityMap.get("120000")) {
            newProvinceList.add(0, municipalityMap.get("120000"));
        }
        if(null != municipalityMap.get("310000")) {
            newProvinceList.add(0, municipalityMap.get("310000"));
        }
        if(null != municipalityMap.get("110000")) {
            newProvinceList.add(0, municipalityMap.get("110000"));
        }
        // 将特别行政区按照香港>澳门>台湾的先后顺序放到列表中
        if(null != SARMap.get("F10000")) {
            newProvinceList.add(newProvinceList.size(), SARMap.get("F10000"));
        }
        if(null != SARMap.get("F20000")) {
            newProvinceList.add(newProvinceList.size(), SARMap.get("F20000"));
        }
        if(null != SARMap.get("F30000")) {
            newProvinceList.add(newProvinceList.size(), SARMap.get("F30000"));
        }
        return newProvinceList;
    }





class ProvinceAndCityComparator implements Comparator<Map<String, Object>> {

        @Override
        public int compare(Map<String, Object> o1, Map<String, Object> o2) {
            String value1 = o1.get("value").toString().trim();
            String value2 = o2.get("value").toString().trim();
            if(StringUtils.isBlank(value1)) {
                return -1;
            }
            if(StringUtils.isBlank(value2)) {
                return 1;
            }
            return compare(value1, value2);
        }

        protected int compare(String value1, String value2) {
            if(StringUtils.isBlank(value1)) {
                return -1;
            }
            if(StringUtils.isBlank(value2)) {
                return 1;
            }
            // 将字符串转换成char数组
            char[] charAry1 = value1.toCharArray();
            char[] charAry2 = value2.toCharArray();
            // 取字符串中的第一个汉字
            char char1 = charAry1[0];
            char char2 = charAry2[0];
            // 将字符串的第一个汉字转换成拼音
            String pinyin1 = Pinyin4jUtils.getSingleWordPinYin(char1 + "");
            String pinyin2 = Pinyin4jUtils.getSingleWordPinYin(char2 + "");
            // 将转换后的拼音再次转换成char数组
            char[] charPinyinAry1 = pinyin1.toCharArray();
            char[] charPinyinAry2 = pinyin2.toCharArray();
            // 拼音按照a-z的顺序排序
            if(charPinyinAry1[0] < charPinyinAry2[0]) {
                return -1;
            }
            if(charPinyinAry1[0] > charPinyinAry2[0]) {
                return 1;
            }
            // 若是此汉字的首字母相同,则比较下一个汉字
            if(charPinyinAry1[0] == charPinyinAry2[0]) {
                String childValue1 = null;
                String childValue2 = null;
                // 剔除字符串的第一个汉字
                if(charAry1.length > 1) {
                    childValue1 = value1.substring(1);
                }
                if(charAry2.length > 1) {
                    childValue2 = value2.substring(1);
                }
                // 递归进行比较,直到最终结果
                return compare(childValue1, childValue2);
            }
            return 0;
        }

    }



package com.lvtu.csa.utils;

import org.apache.commons.lang3.StringUtils;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

/**
 * 汉字转换成拼音
 */
public class Pinyin4jUtils {
    /**
     * 获取单个汉字的拼音(该方法仅支持单个汉字转换)
     * @date 2015-5-11 下午4:14:13
     * @param 单个汉字
     */
    public static String getSingleWordPinYin(String single) {
        if (StringUtils.isEmpty(single)) {
            return "";
        }
        if (1 != single.length()) {
            return "";
        }
        // 设置汉字拼音输出的格式
        HanyuPinyinOutputFormat outputFormat = new HanyuPinyinOutputFormat();
        outputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        outputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        outputFormat.setVCharType(HanyuPinyinVCharType.WITH_V);
        char[] t1 = single.toCharArray();
        try {
            if (Character.toString(t1[0]).matches("[\\u4E00-\\u9FA5]+")) {
                // 将汉字的几种全拼都存到t2数组中
                String[] pinyin = PinyinHelper.toHanyuPinyinStringArray(t1[0], outputFormat);
                // 取出该汉字全拼的第一种读音
                return pinyin[0];
            }
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            e.printStackTrace();
        }
        // 若不是汉字,原样放回
        return single;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值