在Java中存储国家/地区代码,名称和Continent的最佳方式

我想要一个List或某种类型的Array ,存储有关每个国家的信息:

  • 2个字母代码
  • 国家名称,如巴西
  • 世界大陆/地区,如东欧,北美等。

我会手动将每个国家分类到地区/大陆(但如果有办法自动执行此操作,请告诉我)。 这个问题是关于如何存储和访问这些国家。 例如,我希望能够检索北美的所有国家/地区。

我不想使用本地文本文件等,因为这个项目将使用Google Web Toolkit转换为javascript。 但是存储在Enum或某种类型的其他资源文件中,将其与其余代码分开,就是我真正想要的。

在ISO 3166中有246个国家,你可能会在此背后得到一个继电器大枚举。 我更喜欢使用包含国家/地区列表的XML文件,您可以从http://www.iso.org/下载并加载它们(例如,当应用程序启动时)。 然后,因为你需要它们在GWT中作为RPC调用加载它们,但记得缓存那些(某种延迟加载),所以你不会每次都加载它们。 我认为这比在代码中保存它们更好,因为每次访问模块时你都会完成加载完整列表,即使用户不需要使用这个列表。

所以你需要一些能保住国家的东西:

 public class Country { private final String name; private final String code; public Country(String name, String code) { this.name = name; this.code = code; } public String getName() { return name; } public String getCode() { return code; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } Country country = (Country) obj; return code.equals(country.code); } public int hashCode() { return code.hashCode(); } } 

对于GWT,这个类需要实现IsSerializable。 您可以使用以下命令在服务器端加载:

 import java.util.ArrayList; import java.util.List; import java.io.InputStream; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class CountriesService { private static final String EL_COUNTRY = "ISO_3166-1_Entry"; private static final String EL_COUNTRY_NAME = "ISO_3166-1_Country_name"; private static final String EL_COUNTRY_CODE = "ISO_3166-1_Alpha-2_Code_element"; private List countries = new ArrayList(); public CountriesService(InputStream countriesList) { parseCountriesList(countriesList); } public List getCountries() { return countries; } private void parseCountriesList(InputStream countriesList) { countries.clear(); try { Document document = parse(countriesList); Element root = document.getRootElement(); //noinspection unchecked Iterator i = root.elementIterator(EL_COUNTRY); while (i.hasNext()) { Element countryElement = i.next(); Element countryName = countryElement.element(EL_COUNTRY_NAME); Element countryCode = countryElement.element(EL_COUNTRY_CODE); String countryname = countryName.getText(); countries.add(new Country(countryname, countryCode.getText())); } } catch (DocumentException e) { log.error(e, "Cannot read countries list"); } catch (IOException e) { log.error(e, "Cannot read countries list"); } } public static Document parse(InputStream inputStream) throws DocumentException { SAXReader reader = new SAXReader(); return reader.read(inputStream); } } 

当然,如果您需要通过ISO 2字母代码查找国家/地区,您可能不会将List更改为Map。 如果您按照提到的那样,按大陆需要单独的国家/地区,则可以从ISO 3166扩展XML并添加自己的元素。 只需检查他们的(ISO网站)许可证。

只需制作一个名为Country的枚举。 Java枚举可以有属性,因此有您的国家/地区代码和名称。 对于非洲大陆,你可能想要另一个枚举。

 public enum Continent { AFRICA, ANTARCTICA, ASIA, AUSTRALIA, EUROPE, NORTH_AMERICA, SOUTH_AMERICA } public enum Country { ALBANIA("AL", "Albania", Continent.EUROPE), ANDORRA("AN", "Andorra", Continent.EUROPE), ... private String code; private String name; private Continent continent; // get methods go here private Country(String code, String name, Continent continent) { this.code = code; this.name = name; this.continent = continent; } } 

至于存储和访问,您将要搜索的每个字段的一个Map,键入该字段,将是标准解决方案。 由于您拥有该大陆的多个值,因此您必须使用Map>或Multimap实现,例如来自Apache commons。

如果你经常需要按大陆进行查找,我只需要创建一系列不可变列表,每个大陆一个,并相应地填充它们。 一个大陆的国家数据列表可能不会经常变化,因为当需要改变某些东西时,重建这样一个arrays的成本会被重建。

此外,如果您愿意手动进行country-continent分类,则其余分类是自动的,可以通过编程方式完成。

  • 使用Locale.getISOCountries()获取国家/地区代码列表。
  • 使用Locale.getDisplayCountry()获取每个国家/地区的显示名称。

最简单的方法是使用map(或任何集合)在Java中创建country / continent结构,然后使用XStream将其保留

这将创建集合的XML表示,您可以非常轻松地读取进程并将其转换回最初创建的相同集合类型。 此外,因为它是XML,您可以在代码之外轻松编辑它。 即只是在文本编辑器中。

有关详细信息,请参阅XStream教程 。

使用Locale对象是我能想到的最佳解决方案,您不需要存储任何东西。 但是,如果您正在使用GWT尝试在服务器端执行此操作,因为有人说您无法在客户端上正常工作(因为它被转换为javascript),您可以在RPC中将它们发送到客户端之前。