有没有办法分享重叠地图的元素?

时间:2016-08-25 23:32:44

标签: java enumeration

这是我在编程时偶然发现的一些东西,我想知道是否有人可以在这里为我提供一些见解。

想象一下,你有一些enum类似的类,即具有定义为类常量的实例的类。举个例子来考虑像

这样的东西
public class ChildName {

    private static final Map<String, ChildName> LUT = new TreeMap<>();

    private final String name;

    private ChildName(String name) {
        this.name = name.toLowerCase();
        LUT.put(name, this);
    }

    public static Collection<ChildName> getNames() {
       return LUT.values();
    }

    public static ChildName fromValue(String name) {
        return LUT.get(name);
    }

    public static final ChildName SARAH = new ChildName("Sarah");
    public static final ChildName MEGAN = new ChildName("Megan");
    public static final ChildName SANDY = new ChildName("Sandy");
    public static final ChildName JOHN = new ChildName("John");
    public static final ChildName BORIS = new ChildName("Boris");
    // etc...
}

现在,人们可能会争辩说,可能有必要在男孩的名字和女孩的名字之间分开(或考虑来自不同国家的名字或其他什么,你明白了)。这个想法是你仍然可以列出所有可能的名字,还有男孩的所有名字或女孩的所有名字。这可以通过

之类的东西来完成
public class ChildName {

    private static final Map<String, ChildName> LUT = new TreeMap<>();

    private final String name;

    protected ChildName(String name) {
        this.name = name.toLowerCase();
        LUT.put(name, this);
    }

    public static Collection<ChildName> getNames() {
        return LUT.values();
    }

    public static ChildName fromValue(String name) {
        return LUT.get(name);
    }

    // maybe here there are some gender-neutral names as constants left
    public static final ChildName ALEX = new ChildName("Alex");
}

public class GirlsName {

    private static final Map<String, ChildName> LUT = new TreeMap<>();

    private GirlsName(String name) {
        super(name);
        LUT.put(name, this);
    }

    public static Collection<ChildName> getNames() {
        return LUT.values();
    }

    public static final ChildName SARAH = new ChildName("Sarah");
    public static final ChildName MEGAN = new ChildName("Megan");
    public static final ChildName SANDY = new ChildName("Sandy");
    // etc...
}

public class BoysName {

    private static final Map<String, ChildName> LUT = new TreeMap<>();

    private BoysName(String name) {
        super(name);
        LUT.put(name, this);
    }

    public static Collection<ChildName> getNames() {
        return LUT.values();
    }

    public static final ChildName JOHN = new ChildName("John");
    public static final ChildName BORIS = new ChildName("Boris");
    // etc...
}

这可能导致每个类中存在大量重叠的Map个。{/ p>

在这种情况下,效率或内存可能没有那么大的问题,但尽管如此,它仍然是多余的,并且感觉不太好。

可以说,上层的Map可以省略(假设性别中立的名称只是在子类中重复),并且可以通过组合集合来检索所有结果的集合。的子类。但是,我想从设计的角度来避免这种方法(想象一下这个星球上每个国家的子类可能会有多乱)。

一个更优雅的解决方案(在我看来)是在每个班级中保留Map,但这样他们可以共享条目。现在我想知道如果使用基本的Map实现可以实现这一点,是否会有人。当然也欢迎解决此类问题的其他建议。

PS:我知道我提出的优雅解决方案实际上并没有那么好,但我无法提出更好的想法,我不禁想知道如何实现这种地图

2 个答案:

答案 0 :(得分:0)

enum更进一步 - 比如,enums

interface ChildName {}

enum GirlsName implements ChildName  {
    Sarah, Megan, Sandy
}

enum BoysName implements ChildName  {
    John, Boris
}

现在不需要查找地图:

ChildName name = BoysName.valueOf("Boris");

我会让你写代码来找到男孩或女孩的名字。

答案 1 :(得分:0)

我建议使用实际的enum,而不是将它们分组到不同的类中,在ChildName类上存储国家和性别等属性,然后根据需要进行过滤和分组。

public enum Gender {
    MALE, FEMALE
}

public enum Country {
    USA, CA, UK
}

public enum ChildName {
    SARAH(FEMALE, USA),
    MEGAN(FEMALE, CA),
    SANDY(FEMALE, UK),
    JOHN(MALE, USA),
    BORIS(MALE, UK);

    private static final Map<String, ChildName> LUT;
    static {
        LUT = Array.stream(values())
                .collect(Collectors.groupingBy(c -> c.name().toLowerCase()));
    }

    public static Collection<ChildName> getNames() {
       return Arrays.asList(values());
    }

    public static ChildName fromValue(String name) {
        return LUT.get(name.toLowerCase());
    }

    // some examples of filtering and grouping
    // if necessary, they can be cached statically (like LUT)
    public static List<String> getMaleNames() {
        return Arrays.stream(values())
                .filter(c -> c.getGender() == MALE)
                .map(ChildName::name)
                .collect(Collectors.toList());
    }

    public static Map<Gender, List<ChildName>> getGenderMapForCountry(Country country) {
        return Arrays.stream(values())
                .filter(c -> c.getCountry() == country)
                .collect(Collectors.groupingBy(ChildName::getGender));
    }


    private final Gender gender;
    private final Country country;

    ChildName(Gender gender, Country country) {
        this.gender = gender;
        this.country = country;
    }

    public Gender getGender() {
        return gender;
    }

    public Country getCountry() {
        return country;
    }
}