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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/713671/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:29:06  来源:igfitidea点击:

Best way to store Country codes, names, and Continent in Java

javaarrayslinked-listhashmaptreemap

提问by Click Upvote

I want to have a Listor Arrayof some sort, storing this information about each country:

我想要一个ListArray某种类型的,存储有关每个国家/地区的这些信息:

  • 2 letter code
  • Country name such as Brazil
  • Continent/region of the world such as Eastern Europe, North America, etc.
  • 2 个字母的代码
  • 巴西等国名
  • 世界大陆/地区,如东欧、北美等。

I will classify each country into the region/continent manually (but if there exists a way to do this automatically, do let me know). This question is about how to store and access the countries. For example, I want to be able to retrieve all the countries in North America.

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

I don't want to use local text files or such because this project will be converted to javascript using Google Web Toolkit. But storing in an Enum or another resource file of some sort, keeping it separate from the rest of the code, is what I'm really after.

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

采纳答案by Konrad

There is 246 countries in ISO 3166, you might get a relay big enum on back of this. I prefer to use XML file with list of countries, you can download one from http://www.iso.org/and load them (e.g. when app is starting). Than, as you need them in GWT load them in back as RPC call, but remember to cache those (some kind of lazy loading) so you wont finish with loading them each time. I think this would be anyway better than holding them in code, as you will finish with loading full list each time module is accessed, even if user will not need to use this list.

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

So you need something which will hold country:

所以你需要一些可以容纳国家的东西:

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();
    }
}

For GWT this class would need to implement IsSerializable. And you can load those, on server side using:

对于 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);
    }
}

Of course, if you need to find country by ISO 2 letter code you might wont to change List to Map probably. If, as you mentioned, you need separate countries by continent, you might extend XML from ISO 3166 and add your own elements. Just check their (ISO website) license.

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

回答by Michael Borgwardt

Just make an enum called Country. Java enums can have properties, so there's your country code and name. For the continent, you pobably want another enum.

只需创建一个名为 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;
    }
}

As for storing and access, one Map for each of the fields you'll be searching for, keyed on that that field, would be the standard solution. Since you have multiple values for the continent, you'll either have to use a Map<?, List<Country>>, or a Multimap implementation e.g. from Apache commons.

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

回答by John Feminella

If you frequently need to do a lookup by continent, I'd simply make a series of immutable lists, one for each continent, and populate them accordingly. The list of country-data for a continent is probably not going to change frequently enough for the cost of rebuilding such an array to be rebuilt when something needs to be altered.

如果您经常需要按大洲进行查找,我会简单地制作一系列不可变列表,每个大洲一个,并相应地填充它们。一个大陆的国家/地区数据列表可能不会经常更改,以至于在需要更改某些内容时重建此类阵列的成本。

Also, if you're willing to do the country-continent classification manually, the rest is automatic and can be done programmatically.

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

回答by Brian Agnew

The easiest way to do this is to create the country/continent structure in Java using a map (or whatever collection) and then persist it using XStream

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

This will create an XML representation of the collection, and you can read than into your process very easily and convert it back to the same collection type that you initially created. Furthermore, because it's XML, you can easily edit it outside of code. i.e. just in a text editor.

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

See the XStream tutorialfor more info.

有关更多信息,请参阅XStream 教程

回答by zeacuss

using the Locale object is the best solution I can think of, you wouldn't need to store anything. But if you are using GWT try to do that on the server side, as some say you won't get it working correctly on the client side (as it gets translated to javascript) you can send them to the client in an RPC as stated before.

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