【问题标题】:Best way to store Country codes, names, and Continent in Java在 Java 中存储国家代码、名称和大陆的最佳方式
【发布时间】:2010-10-17 08:28:50
【问题描述】:

我想要ListArray 之类的,用于存储有关每个国家/地区的信息:

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

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

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

【问题讨论】:

  • 一些国家属于两大洲(欧洲土耳其、俄罗斯和哈萨克斯坦),M:N 关系
  • 这是他们的问题:)。无论如何,没有人会想要使用这 3 个特定的国家,如果他们愿意,他们可以按字母顺序而不是按地区查找它们
  • 那么您知道哪些国家不会被“使用”吗?你一定是个真正的专家......

标签: java arrays linked-list hashmap treemap


【解决方案1】:

只需创建一个名为 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<?, List<Country>>,要么使用 Multimap 实现,例如来自 Apache commons。

【讨论】:

  • 您应该清楚您存储的是“名称”的“en-US”版本;)
  • 一个问题,我如何将 North_america 转换为 North america?枚举有 tostring() 方法吗?
  • @mjustin:糟糕... @ClickUpvot:所有类都有一个继承自 Object 的 toString() 方法。只需覆盖它即可返回名称。当然你也有一个 getName() 访问器,为了简洁我省略了它。
  • 当有一个新的国家..紧急部署?
  • 注意属于俄罗斯和土耳其等两大洲的国家/地区。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    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<Country> countries = new ArrayList<Country>();
    
        public CountriesService(InputStream countriesList)
        {
            parseCountriesList(countriesList);
        }
    
        public List<Country> getCountries()
        {
            return countries;
        }
    
        private void parseCountriesList(InputStream countriesList)
        {
            countries.clear();
            try
            {
                Document document = parse(countriesList);
                Element root = document.getRootElement();
                //noinspection unchecked
                Iterator<Element> 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 网站)许可证即可。

    【讨论】:

      【解决方案4】:

      最简单的方法是使用地图(或任何集合)在 Java 中创建国家/大陆结构,然后使用 XStream 将其持久化

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

      请参阅XStream tutorial 了解更多信息。

      【讨论】:

        【解决方案5】:

        如果您经常需要按大陆进行查找,我只需制作一系列不可变列表,每个大陆都有一个,并相应地填充它们。一个大陆的国家/地区数据列表可能不会频繁地更改,以支付在需要更改某些内容时重建这样一个数组的成本。

        此外,如果您愿意手动进行国家/大陆分类,其余的都是自动的,可以通过编程方式完成。

        【讨论】:

        • 不可变列表是什么意思?你能分享一些代码吗?抱歉,我是java新手
        • 不可变列表只是其内容无法更改的列表(请参阅 ReadOnlyCollection)。不过,我更喜欢迈克尔的方法,我认为你应该采用那个方法而不是我的方法。
        • 好吧,它们可以结合起来: enum Country { ... static { for(Continent c : Continent.values()) for(Country cc : Country.values()) if(cc.getContinent () == c) byContinent.get(c).add(cc) } /* 用 Collections.immutableList() 和 immutableMap() 转换 */ ... }
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-11
        • 1970-01-01
        • 1970-01-01
        • 2018-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多