下面我将提供一个完整的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;
}
}