首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将多个决定因素映射为Java值的最佳方法

将多个决定因素映射为Java值的最佳方法
EN

Stack Overflow用户
提问于 2015-10-02 19:03:04
回答 1查看 94关注 0票数 0

我有一个要求,我需要把多个决定因素映射到价值观上。

  • 给定作业执行中的每一组决定因素都保证是唯一的。要确定的值不一定是唯一的,但它可能是唯一的。
  • 根据作业执行的输入,可以是一个键,也可以是两个键的组合,也可以是将映射到单个值的n键的组合。在实践中,这个n可能会被限制在不超过5,尽管它有可能超过这一点。
  • 每个作业执行对于所有输入都有一定数量的决定因素(即,所有输入都有两个决定因素、三个决定因素或n个决定因素,而不是混合因素)。

一个关键的例子:foo --> bar

两个键:foo, bar --> baz

三个键:foo, bar, baz --> hai

在此之前,要求我只将两个值映射到另一个值。我创建了一个不可变的密钥类,其中包含两个成员变量以及equalshashCode的适当覆盖。

代码语言:javascript
复制
public class Key {
    String determinant0;
    String determinant1;
    public Key(String d0, d1) {
        determinant0 = d0;
        determinant1 = d1;
    }
    // ..
} 

但是,现在我可能要处理n个值,我想看看如何使用list作为键。

代码语言:javascript
复制
Map<List, String> map = new HashMap<List, String>();
map.put(Arrays.asList("foo", "bar", "baz"), "hai");
String determined = map.get(Arrays.AsList("foo","bar","baz"));
assert (determined.equals("hai"));

这个question提醒我,在地图中使用可变对象(如列表)作为键是不好的。但是,在我的应用程序中,密钥只设置一次,并且从不更改。下面是此question的另一种选择,它强制它不可变:

代码语言:javascript
复制
HashMap<List<String>, String> map;

map.put(
    // unmodifiable so key cannot change hash code
    Collections.unmodifiableList(Arrays.asList("foo", "bar", "baz")),
    "hai"
);

此外,为了防止列表中的突变,我可以做一个类似以下的类:

代码语言:javascript
复制
public class Key {
    List<String> determinants;
    public Key(List<String> determinants) {
        this.determinants = determinants
    }
    @Override
    public boolean equals(Object obj) {
        //...
    }
    @Override
    public int hashCode() {
        //...
    }
}

Key key = new Key(Arrays.asList("foo","bar","baz"));

使用普通数组作为键是行不通的,因为数组的等效方法只检查标识:

代码语言:javascript
复制
Map<String[], String> map = new HashMap<String[], String>();
String[] key = new String[]{"foo", "bar", "baz"}
map.put(key, "hai");
System.out.println(map.get(key)); // null

这可以通过以下办法加以解决:

代码语言:javascript
复制
public class Key {
    String[] determinants;
    public Key(String... determinants) {
        this.determinants = determinants;
    }
    @Override
    public boolean equals(Object obj) {
        //...
    }
    @Override
    public int hashCode() {
        //...
    }
}

把所有的决定因素串联在一个字符串中怎么样?

代码语言:javascript
复制
public class Key {
    String hash = "";
    public Key(String... determinants) {
        for (String determinant : determinants) {
            hash += determinant + "_";
        }

    }
    @Override
    public boolean equals(Object obj) {
        //...
    }
    @Override
    public int hashCode() {
        //...
    }
}

这些解决方案中的哪一个(或者另一个我没有提出)最适合这些需求?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-02 19:37:57

作为一个评论,你的问题包含了太多的细节,可能要短得多。现在我的答案来了。

我更喜欢使用一个完全隐藏类表示的包装类。作为一个小的优化,您可以做的一件事是存储密钥的hashCode,以防止每次计算。equals方法将被调用得更少(映射中的每一次碰撞),并且您不能对它做太多事情:

代码语言:javascript
复制
public class Key {
    private String[] determinants;
    private int hashCode;

    public Key(String... determinants) {
        if (determinants == null || determinants.length == 0) {
            throw new IllegalArgumentException("Please provide at least one value");
        }
        this.determinants = determinants;
        this.hashCode = Objects.hash(determinants);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Key)) return false;
        Key that = (Key) o;
        return Arrays.equals(determinants, that.determinants);
    }

    @Override
    public int hashCode() {
        return hashCode;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32914118

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档