有个朋友需要实现一个功能,数据库查出经销商信息,并根据省,市排序,并提供首个省市的首字母,鉴于他觉得代码实现实在太长,想要优化下,于是我闪亮登场。
首先,有个问题是要提一下的,PinYinHelper对于城市的多音字支持不友好,更换了TinyPinyin,然后有个拿空间换时间的想法,逻辑上看起来O(n)
主逻辑代码如下:
List<Dealer> dealerList = 根据条件查询数据库拿到经销商信息
//数据展示,后面提供代码
TreeSet<CityDealerResp.Province> parent = new TreeSet<>();
if (CollectionUtils.isNotEmpty(dealerList)){
Map<Long, CityDealerResp.Province> provinceMap = new HashMap<>(26/3*4+1);
Map<String,CityDealerResp.CityDealer> cityDealerMap = new HashMap<>(dealerList.size()/3*4+1);
dealerList.forEach(e->{
if (StringUtils.isNotBlank(e.getDealerPrvnceNm()) && StringUtils.isNotBlank(e.getDealerLandCityNm()) && StringUtils.isNotBlank(e.getSaleCode())){
CityDealerResp.Province province = provinceMap.get(e.getDealerPrvnceId());
if (Objects.nonNull(province)){
TreeSet<CityDealerResp.CityDealer> cityDealers = province.getCities();
if (CollectionUtils.isNotEmpty(cityDealers)){
CityDealerResp.CityDealer cityDealer = cityDealerMap.get(String.valueOf(e.getDealerPrvnceId())+e.getDealerLandCityId());
if (Objects.nonNull(cityDealer)) {
cityDealer.getDealers().add(new CityDealerResp.Dealer(e.getSaleCode(), e.getName()));
}else {
cityDealer = CityDealerResp.buildCityDealerFromDealerBo(e);
cityDealers.add(cityDealer);
cityDealerMap.put(String.valueOf(e.getDealerPrvnceId())+e.getDealerLandCityId(),cityDealer);
}
}else {
CityDealerResp.CityDealer cityDealer = CityDealerResp.buildCityDealerFromDealerBo(e);
cityDealerMap.put(String.valueOf(e.getDealerPrvnceId())+e.getDealerLandCityId(),cityDealer);
province.setCities(new TreeSet<CityDealerResp.CityDealer>(){{
add(cityDealer);}});
}
}else{
CityDealerResp.CityDealer cityDealer = CityDealerResp.buildCityDealerFromDealerBo(e);
cityDealerMap.put(String.valueOf(e.getDealerPrvnceId())+e.getDealerLandCityId(),cityDealer);
province = new CityDealerResp.Province(){{
setName(e.getDealerPrvnceNm());
Pinyin.init(Pinyin.newConfig().with(CnCityDict.getInstance()));
setPinYin(Pinyin.toPinyin(e.getDealerPrvnceNm(),""));
setInitial(getPinYin().substring(0,1).toUpperCase());
setCities(new TreeSet<CityDealerResp.CityDealer>(){{
add(cityDealer); }});
}};
parent.add(province);
provinceMap.put(e.getDealerPrvnceId(),province);
}
}
});}
public class CityDealerResp {
TreeSet<Province> cityDealers;
@Data
public static class Province implements Comparable<Province> {
private String name;
private String pinYin;
private String initial;
private TreeSet<CityDealer> cities;
@Override
public int compareTo(Province o) {
int i = Optional.ofNullable(pinYin).orElse("Z").compareTo(Optional.ofNullable(o.getPinYin()).orElse("Z"));
if (this != o && i==0){
i = Collator.getInstance(Locale.CHINA).compare(name, o.getName());
if (i==0){
i = -1;
}
}
//在比较的同时,确定首字母赋值
if (this != o && Optional.ofNullable(initial).orElse("Z").equalsIgnoreCase(Optional.ofNullable(o.getPinYin()).orElse("Z").substring(0,1))) {
if (i < 0) {
o.setInitial(null);
} else {
initial = null;
}
}
return i;
}
@Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Province province = (Province) o; return Objects.equals(name, province.name) && Objects.equals(pinYin, province.pinYin) && Objects.equals(initial, province.initial); } @Override public int hashCode() { return Objects.hash(name, pinYin, initial); } } @Data public static class CityDealer implements Comparable<CityDealer> { private String cityCode; private String cityName; private String pinYin; private String initial; private TreeSet<Dealer> dealers; @Override public int compareTo(CityDealer o) { int i = Optional.ofNullable(pinYin).orElse("Z").compareTo(Optional.ofNullable(o.getPinYin()).orElse("Z")); if (this != o && i==0){ i = Collator.getInstance(Locale.CHINA).compare(cityName, o.getCityName()); if (i==0){ i = -1; } } if (this != o && Optional.ofNullable(initial).orElse("Z").equalsIgnoreCase(Optional.ofNullable(o.getPinYin()).orElse("Z").substring(0,1))) { if (i < 0) { o.setInitial(null); } else { initial = null; } } return i; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } CityDealer that = (CityDealer) o; return Objects.equals(cityCode, that.cityCode) && Objects.equals(cityName, that.cityName); } @Override public int hashCode() { return Objects.hash(cityCode, cityName); } } public static CityDealer buildCityDealerFromDealerBo(com.sgm.ossp.dealer.mapper.db1.entity.Dealer dealer) { return new CityDealer() {{ setCityCode(String.valueOf(dealer.getDealerLandCityId())); setCityName(dealer.getDealerLandCityNm()); Pinyin.init(Pinyin.newConfig().with(CnCityDict.getInstance())); setPinYin(Pinyin.toPinyin(dealer.getDealerLandCityNm(),"")); setInitial(getPinYin().substring(0,1).toUpperCase()); setDealers(new TreeSet<Dealer>() {{ add(new Dealer(dealer.getSaleCode(), dealer.getName())); }}); }}; } @Data @NoArgsConstructor @AllArgsConstructor public static class Dealer implements Comparable<Dealer> { private String dealerCode; private String dealerName; @Override public int compareTo(Dealer o) { return Collator.getInstance(Locale.CHINA).compare(dealerName, o.getDealerName()); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Dealer dealer = (Dealer) o; return dealerCode.equals(dealer.dealerCode) && dealerName.equals(dealer.dealerName); } @Override public int hashCode() { return Objects.hash(dealerCode, dealerName); } }}