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

什么样的Java数据结构最适合双向多值映射,java,dictionary,data-structures,bidirectional,multivalue,Java,Dictionary,Data Structures,Bidirectional,Multivalue,我对Java比较陌生,我有一个问题,那就是什么类型的数据结构最适合我的情况。我有一组基本上是键值对的数据,但是每个值可能对应多个键,每个键可能对应多个值。一个简化的例子是: 红苹果 青苹果 红草莓 绿葡萄 紫葡萄 考虑到上面的例子,我需要能够返回我有什么颜色的苹果和/或我有什么红色的水果。实际数据将根据一个输入文件动态生成,其中每一组值将在100-100000之间,每个值可能对应于另一组中的数百个值 存储和解析这些数据最有效的方法是什么?我更喜欢一个尽可能与java原生的解决方案,而不是像外

我对Java比较陌生,我有一个问题,那就是什么类型的数据结构最适合我的情况。我有一组基本上是键值对的数据,但是每个值可能对应多个键,每个键可能对应多个值。一个简化的例子是:

  • 红苹果
  • 青苹果
  • 红草莓
  • 绿葡萄
  • 紫葡萄
考虑到上面的例子,我需要能够返回我有什么颜色的苹果和/或我有什么红色的水果。实际数据将根据一个输入文件动态生成,其中每一组值将在100-100000之间,每个值可能对应于另一组中的数百个值

存储和解析这些数据最有效的方法是什么?我更喜欢一个尽可能与java原生的解决方案,而不是像外部数据库这样的解决方案


是相关的,但我不确定如何在我的情况下应用该解决方案,因为我需要在两个方向上为每个键分配多个值。

由于在
映射中不能有重复的键,您可以创建一个
映射,或者如果可以,使用

Multimap Multimap=ArrayListMultimap.create();
多重映射。放置(“红色”、“苹果”);
多重映射。放置(“红色”、“草莓”);
System.out.println(multimap.get(“红色”));//印刷品-[苹果、草莓]
但问题是你不能要求一个给定对象的密钥,如果我找到其他东西,我会继续查找、制作和编辑,希望能有所帮助


不过,您可以通过迭代映射并找到对象的键来实现相反的效果。

您可以创建自己的自定义数据结构

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);
    }
}
公共类多值hashmap{
私有HashMap multivalueHashMap=新HashMap();
公共静态void main(字符串[]args){
MultiValueHashMap multivaluemap=新的MultiValueHashMap();
多值映射。放置(“红色”、“苹果”);
多值映射。放置(“绿色”、“苹果”);
多值映射。放置(“红色”、“草莓”);
多值映射。放置(“绿色”、“葡萄”);
多值映射。放置(“紫色”、“葡萄”);
for(字符串k:multivaluemap.keySet()){
System.out.println(k+”:“+multivaluemap.get(k.toString());
}
}
公开作废认沽权(K键,V值){
if(多值hashmap.containsKey(键)){
ArrayList值=多值HashMap.get(键);
增加(价值);
}否则{
ArrayList值=新的ArrayList();
增加(价值);
多值hashmap.put(键、值);
}
}
公共集密钥集(){
返回多值hashmap.keySet();
}
公共ArrayList get(K键){
返回多值hashmap.get(key);
}
}
输出应该是

红色:[苹果,草莓]

紫色:[葡萄]

格林:[苹果,葡萄]

我建议你使用结构。使用颜色作为行键,使用水果作为列键,反之亦然。具体来说,
HashBasedTable
非常适合您的情况

根据您的用例,您不需要为这些值存储任何内容。但是,这些
表不允许
null
值。您可以使用虚拟
布尔值
或任何其他统计有用值,即插入日期和时间、用户、颜色/水果对数等


Table
具有您需要的方法,例如
column()
row()
。请记住,文档中说这些结构针对行访问进行了优化。如果您计划通过一个键访问而不是通过另一个键访问,这对您来说可能没问题。

地图怎么样?还有一个问题:@Josh-谢谢,我在搜索中没有找到这个问题。我将仔细查看这些解决方案,看看是否可以成功地为我的数据实现它们。如果您可以使用外部库(jar),我建议您使用Guava的表,特别是HashBasedTable。Guava是一组来自Google的实用程序类(不是数据库)。我将创建一个包含值a、值b对象和方法列表的类,以获取值a和值b的值。也许不是最有效的,但却是最直接的。“但问题是你不能要求一个给定对象的键。”听起来好像这可以通过一个双多重映射来解决。不确定这是否存在,但这就是它的名称。或者在节点名上建立索引的有向图。不能将其中两个封装在自定义对象中以实现此目的吗
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);
    }
}