简体   繁体   English

什么Java数据结构最适合双向多值映射

[英]What Java data structure is best for two-way multi-value mapping

I'm relatively new to Java and I have a question about what type of data structure would be best for my case. 我对Java比较陌生,我对哪种类型的数据结构最适合我的情况有疑问。 I have a set of data which are essentially key-value pairs, however each value may correspond to multiple keys and each key may correspond to multiple values. 我有一组基本上是键值对的数据,但是每个值可以对应于多个键,并且每个键可以对应于多个值。 A simplified example would be: 一个简化的例子是:

  • Red-Apple 红苹果
  • Green-Apple 青苹果
  • Red-Strawberry 红草莓
  • Green-Grapes 绿葡萄
  • Purple-Grapes 紫色葡萄

Considering the above example, I need to be able to return what color apples I have and/or what red fruits I have. 考虑到上面的例子,我需要能够返回我拥有的颜色苹果和/或我拥有的红色水果。 The actual data will generated dynamically based upon an input file where each set will be anywhere from 100-100,000 values and each value may correspond to hundreds of values in the other set. 实际数据将基于输入文件动态生成,其中每个集合将是100-100,000个值,并且每个值可以对应于另一个集合中的数百个值。

What would be the most efficient way to store and parse this data? 存储和解析这些数据的最有效方法是什么? I would prefer a solution as native to java as possible rather than something such as an external database. 我希望尽可能使用java本机的解决方案,而不是像外部数据库那样的东西。

This question is related, but I'm not sure how to apply the solution in my case given that I would need to assign multiple values to each key in both directions. 这个问题是相关的,但我不确定如何在我的情况下应用解决方案,因为我需要在两个方向上为每个键分配多个值。

As you can't have duplicate keys in a Map , you can rather create a Map<Key, List<Value>> , or if you can, use Guava's Multimap . 由于Map没有重复键,您可以创建Map<Key, List<Value>> ,或者如果可以,可以使用Guava的Multimap

Multimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("Red", "Apple");
multimap.put("Red", "Strawberry");

System.out.println(multimap.get("Red"));  // Prints - [Apple, Strawberry]

But the problem is you can't ask for the keys of a given object, I'll keep looking and make and edit if I find something else, hope it helps. 但问题是你不能要求给定对象的键,如果我找到别的东西,我会继续寻找,制作和编辑,希望它有所帮助。

Still, you can make the reverse yourself by iterating the map and finding the keys for the object. 不过,您可以通过迭代地图并找到对象的键来自行反转。

I suggest you use Guava's Table structure. 我建议你使用Guava的桌面结构。 Use color as your row keys and fruit as your column key or the other way round. 使用颜色作为行键和水果作为列键,反之亦然。 Specifically, HashBasedTable is well suited for your case. 具体来说, HashBasedTable非常适合您的情况。

As per your use case, you wouldn't need to store anything for the values. 根据您的用例,您不需要为值存储任何内容。 However, these Table s don't allow null values. 但是,这些Table不允许null值。 You could use a dummy Boolean or any other statistical useful value, ie date and time of insertion, user, number of color/fruit pairs, etc. 您可以使用虚拟Boolean或任何其他统计有用值,即插入的日期和时间,用户,颜色/水果对的数量等。

Table has the methods you need, such as column() and row() . Table具有您需要的方法,例如column()row() Bear in mind that the docs say that these structures are optimized for row access . 请记住,文档说这些结构针对行访问进行了优化。 This might be OK for you if you plan to access by one key more than by the other. 如果您计划通过一个键而不是另一个键访问,这可能对您没有用。

You can create your own custom data structure 您可以创建自己的自定义数据结构

public class MultiValueHashMap<K, V> {
     private HashMap<K, ArrayList<V>> multivalueHashMap = new HashMap<K, ArrayList<V>>();

    public static void main(String[] args) {
        MultiValueHashMap<String, String> multivaluemap = new MultiValueHashMap<String, String>();
        multivaluemap.put("Red", "Apple");
        multivaluemap.put("Green", "Apple");
        multivaluemap.put("Red", "Strawberry");
        multivaluemap.put("Green", "Grapes");
        multivaluemap.put("Purple", "Grapes");

        for(String k : multivaluemap.keySet()){
            System.out.println(k + " : " + multivaluemap.get(k).toString());
        }
    }

    public void put(K key, V value){
        if (multivalueHashMap.containsKey(key)){
            ArrayList<V> values = multivalueHashMap.get(key);
            values.add(value);
        }else{
            ArrayList<V> values  = new ArrayList<V>();
            values.add(value);
            multivalueHashMap.put(key, values);
        }
    }

    public Set<K> keySet(){
        return multivalueHashMap.keySet();
    }

    public ArrayList<V> get(K key){
        return multivalueHashMap.get(key);
    }
}

The output should be 输出应该是

Red : [Apple, Strawberry] 红色:[苹果,草莓]

Purple : [Grapes] 紫色:[葡萄]

Green : [Apple, Grapes] 绿色:[苹果,葡萄]

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

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