简体   繁体   English

使用双键创建hashmap

[英]Creating a hashmap with a double key

I am looking for an appropriate data structure for my problem. 我正在为我的问题寻找合适的数据结构。 I would like to be able to select node objects as efficiently as possible using two keys. 我希望能够使用两个键尽可能高效地选择节点对象。 Insertion and deletion also needs to be efficient. 插入和删除也需要有效。 Basically every node object has a pair of two keys. 基本上每个节点对象都有一对两个键。 The pairs are unique but the individual keys are not. 这些对是唯一的,但个别键不是。 I need to be able to select a group of nodes that have a particular value for one of the two keys. 我需要能够为两个键中的一个选择一组具有特定值的节点。

Example: 例:

Node1 has keys a1 and b1 Node1具有键a1和b1

Node2 has keys a1 and b2 Node2具有密钥a1和b2

Node3 has keys a2 and b2 Node3具有密钥a2和b2

I would like to for example be able to select the node with the key a1,b1 but also all nodes that have b2 as key2. 我想例如能够选择具有密钥a1,b1的节点以及具有b2作为key2的所有节点。

I could of course make two HashMaps (one for each key) but this is kind of an ugly solution because when I add or remove something I would have to do it in both maps. 我当然可以制作两个HashMaps(每个键一个),但这是一种丑陋的解决方案,因为当我添加或删除某些东西时,我必须在两个映射中都这样做。 Since there will be a lot of adding and removing going on I would prefer to do this in one go. 由于会有很多添加和删除,我宁愿一次性完成。 Does anyone have any ideas about how to do this? 有没有人对如何做到这一点有任何想法?

Obviously having a single key that merges the two keys together does not solve the problem because I also need to be able to search for a single key without having to search through the whole map. 显然,将两个密钥合并在一起的单个密钥并不能解决问题,因为我还需要能够搜索单个密钥而无需搜索整个映射。 That wouldn't be very efficient. 那不会很有效率。 The problem is an efficiency problem. 问题是效率问题。 I could just search every entry in the map for a particular key but instead I would like to use a hash so that I can select multiple node objects using either one of the two keys instantly. 我可以在地图中搜索特定键的每个条目,但我想使用哈希,以便我可以立即使用两个键中的任何一个选择多个节点对象。

I am not looking for something like the MultiKeyMap because in this data-structure the first key always stays the same, you can only add keys instead of replacing the first key with a different key. 我不是在寻找类似MultiKeyMap的东西,因为在这个数据结构中第一个键总是保持不变,你只能添加键而不是用不同的键替换第一个键。 I want to be able to switch between the first and the second key. 我希望能够在第一个和第二个键之间切换。

I do and do not want to store multiple objects with the same key. 我喜欢并且不想使用相同的密钥存储多个对象。 If you look at the example you can see that the two keys together are always unique. 如果您查看示例,您可以看到两个键一起始终是唯一的。 This can be seen as a single key therefore I would not store multiple objects under the same key. 这可以看作是单个键,因此我不会在同一个键下存储多个对象。 But if you look at the individual keys, these are not unique therefore I do want to store multiple objects referenced by the individual keys. 但是如果你看一下各个键,它们并不是唯一的,因此我想存储各个键所引用的多个对象。

If you can use a library, take a look at the Table interface of Guava. 如果您可以使用库,请查看Guava的Table界面。 It associates a row and a column with a value. 它将行和列与值相关联。 The row and columns may be your first and second keys. 行和列可能是您的第一个和第二个键。 Also you can have searches by row or by column. 您也可以按行或按列进行搜索。

One of the implementations of this interface is hash based . 该接口的一个实现是基于散列的

You have to create a key class (equality is treated as Point ): 您必须创建一个密钥类(相等性被视为Point ):

public class Key {

    int field1;
    int field2;

    public boolean equals(Object o) {
        if (o == null || !(o instanceof Key)) return false;
        Key other = (Key) o;
        return field1 == other.field1 && field2 == other.field2;
    }

    public int hashCode() {
        return field1*field2; // doesn't matter if some keys have same hash code
    }

}

For selecting keys with one specific value in the first field: 要在第一个字段中选择具有一个特定值的键:

public List<Key> getKeysWithField1EqualsTo(int value) {
    List<Key> result = new ArrayList<>();
    for (Key k: map.keySet()) {
        if (k.field1 == value) result.add(k);
    }
    return result;
}

Since this is rather specific to your problem at hand, you will very likely need to develop your own collection. 由于这对您手头的问题非常具体,因此您很可能需要开发自己的集合。 I would wrap two MultiMap s from Apache Commons into my own collection class that deals with updates of both multi-maps at the same time, and use my class to perform inserts and queries. 我将两个MultiMap从Apache Commons包装到我自己的集合类中,同时处理两个多映射的更新,并使用我的类来执行插入和查询。

Write a simple class that is able to contain two values (the keys) and override equals(..) and hashCode() for equality checks used by the map. 编写一个简单的类,它能够包含两个值(键)并覆盖equals(..)和hashCode(),用于映射使用的相等性检查。 Use this simple class as the key for the map. 使用这个简单的类作为地图的关键。

Here you can find a hashmap compatible pair class (2nd answer): 在这里你可以找到一个兼容的hashmap类(第二个答案):

What is the equivalent of the C++ Pair<L,R> in Java? Java中C ++ Pair <L,R>的等价物是什么?

Since a HashMap can only sort on one hash for every object, you will never be able to select the distinct lists 'out of the box'. 由于HashMap只能为每个对象排序一个哈希值,因此您永远无法选择开箱即用的不同列表。 What I would suggest is using a Tuple with two keys, and then iterate over the HashMap and select only those elements that have tuple.key1=X. 我建议使用带有两个键的元组,然后遍历HashMap并仅选择那些具有tuple.key1 = X的元素。

HashMaps can have any object as Key so why not create a class with 2 fields and consider this class as your key. HashMaps可以将任何对象作为Key,因此为什么不创建一个包含2个字段的类,并将此类视为您的密钥。 you can also Override the Equals method to tell it how the keys are equals 您还可以覆盖Equals方法,告诉它键是如何等于的

I think we can do it in this way: For each key, we can compute the corresponding hashcode. 我认为我们可以这样做:对于每个键,我们可以计算相应的哈希码。

key1 -> hashcode1
key2 -> hashcode2

Then we have a 2-d array, with N columns and N rows. 然后我们有一个2维数组,N列和N行。

key1 -> rowIndex: hashcode1 MOD N
key2 -> columnIndex: hashcode2 MOD N

Then we store the item in array[rowIndex][columnIndex] . 然后我们将项存储在array[rowIndex][columnIndex]

In this implementation, you can get all the entries with a target key1, and any key2. 在此实现中,您可以使用目标key1和任何key2获取所有条目。 You can also get all the entries with a target key2, and any key1. 您还可以使用目标key2和任何key1获取所有条目。

This array may expand when there are a lot of collisions, just like what you do with the ordinary hashmap. 当存在大量冲突时,此数组可能会扩展,就像您使用普通hashmap一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM