HashMap在同一个键下有多个值

时间:2011-02-10 12:06:12

标签: java

我们是否可以使用一个键和两个值来实现HashMap。就像HashMap一样?

请帮助我,还告诉(如果没有办法)任何其他方法来实现三个值的存储,其中一个作为密钥?

22 个答案:

答案 0 :(得分:242)

你可以:

  1. 使用包含列表作为值的地图。 Map<KeyType, List<ValueType>>
  2. 创建一个新的包装器类,并将此包装器的实例放在地图中。 Map<KeyType, WrapperType>
  3. 使用类似的元组(保存创建大量包装器)。 Map<KeyType, Tuple<Value1Type, Value2Type>>
  4. 并排使用多个地图。

  5. 实施例

    <强> 1。使用列表作为值

    进行映射
    // create our map
    Map<String, List<Person>> peopleByForename = new HashMap<>();    
    
    // populate it
    List<Person> people = new ArrayList<>();
    people.add(new Person("Bob Smith"));
    people.add(new Person("Bob Jones"));
    peopleByForename.put("Bob", people);
    
    // read from it
    List<Person> bobs = peopleByForename["Bob"];
    Person bob1 = bobs[0];
    Person bob2 = bobs[1];
    

    这种方法的缺点是列表没有绑定到两个值。

    <强> 2。使用包装类

    // define our wrapper
    class Wrapper {
        public Wrapper(Person person1, Person person2) {
           this.person1 = person1;
           this.person2 = person2;
        }
    
        public Person getPerson1 { return this.person1; }
        public Person getPerson2 { return this.person2; }
    
        private Person person1;
        private Person person2;
    }
    
    // create our map
    Map<String, Wrapper> peopleByForename = new HashMap<>();
    
    // populate it
    Wrapper people = new Wrapper();
    peopleByForename.put("Bob", new Wrapper(new Person("Bob Smith"),
                                            new Person("Bob Jones"));
    
    // read from it
    Wrapper bobs = peopleByForename.get("Bob");
    Person bob1 = bobs.getPerson1;
    Person bob2 = bobs.getPerson2;
    

    这种方法的缺点是你必须为所有这些非常简单的容器类编写大量的样板代码。

    第3。使用元组

    // you'll have to write or download a Tuple class in Java, (.NET ships with one)
    
    // create our map
    Map<String, Tuple2<Person, Person> peopleByForename = new HashMap<>();
    
    // populate it
    peopleByForename.put("Bob", new Tuple2(new Person("Bob Smith",
                                           new Person("Bob Jones"));
    
    // read from it
    Tuple<Person, Person> bobs = peopleByForename["Bob"];
    Person bob1 = bobs.Item1;
    Person bob2 = bobs.Item2;
    

    在我看来,这是最好的解决方案。

    <强> 4。多个地图

    // create our maps
    Map<String, Person> firstPersonByForename = new HashMap<>();
    Map<String, Person> secondPersonByForename = new HashMap<>();
    
    // populate them
    firstPersonByForename.put("Bob", new Person("Bob Smith"));
    secondPersonByForename.put("Bob", new Person("Bob Jones"));
    
    // read from them
    Person bob1 = firstPersonByForename["Bob"];
    Person bob2 = secondPersonByForename["Bob"];
    

    这个解决方案的缺点是两个地图相关并不明显,编程错误可能会导致两个地图不同步。

答案 1 :(得分:56)

不,不仅仅是HashMap。您基本上需要从密钥到值集合的HashMap

如果您愿意使用外部库,GuavaMultimap中具有ArrayListMultimapHashMultimap等实现的完全概念。

答案 2 :(得分:21)

另一个不错的选择是使用Apache Commons的MultiValuedMap。请查看页面顶部的所有已知实施类以获取专门的实施。

示例:

HashMap<K, ArrayList<String>> map = new HashMap<K, ArrayList<String>>()

可以替换为

MultiValuedMap<K, String> map = new MultiValuedHashMap<K, String>();

所以,

map.put(key, "A");
map.put(key, "B");
map.put(key, "C");

Collection<String> coll = map.get(key);

会导致集合coll包含&#34; A&#34;,&#34; B&#34;和&#34; C&#34;。

答案 3 :(得分:13)

从guava库中查看Multimap及其实现 - HashMultimap

  

类似于Map的集合,但可以将多个值与单个键相关联。如果使用相同的键但不同的值调用put(K,V)两次,则multimap包含从键到两个值的映射。

答案 4 :(得分:7)

我使用Map<KeyType, Object[]>将多个值与Map中的键相关联。这样,我可以存储与密钥关联的多个不同类型的值。您必须保持从Object []中插入和检索的正确顺序。

实施例: 考虑一下,我们想存储学生信息。密钥是id,而我们希望存储与学生相关的姓名,地址和电子邮件。

       //To make entry into Map
        Map<Integer, String[]> studenMap = new HashMap<Integer, String[]>();
        String[] studentInformationArray = new String[]{"name", "address", "email"};
        int studenId = 1;
        studenMap.put(studenId, studentInformationArray);

        //To retrieve values from Map
        String name = studenMap.get(studenId)[1];
        String address = studenMap.get(studenId)[2];
        String email = studenMap.get(studenId)[3];

答案 5 :(得分:6)

HashMap<Integer,ArrayList<String>> map = new    HashMap<Integer,ArrayList<String>>();

ArrayList<String> list = new ArrayList<String>();
list.add("abc");
list.add("xyz");
map.put(100,list);

答案 6 :(得分:4)

仅供记录,纯JDK8解决方案是使用Map::compute方法:

map.compute(key, (s, strings) -> strings == null ? new ArrayList<>() : strings).add(value);

public static void main(String[] args) {
    Map<String, List<String>> map = new HashMap<>();

    put(map, "first", "hello");
    put(map, "first", "foo");
    put(map, "bar", "foo");
    put(map, "first", "hello");

    map.forEach((s, strings) -> {
        System.out.print(s + ": ");
        System.out.println(strings.stream().collect(Collectors.joining(", ")));
    });
}

private static <KEY, VALUE> void put(Map<KEY, List<VALUE>> map, KEY key, VALUE value) {
    map.compute(key, (s, strings) -> strings == null ? new ArrayList<>() : strings).add(value);
}

带输出:

bar: foo
first: hello, foo, hello

请注意,为确保多个线程访问此数据结构时的一致性,例如需要使用ConcurrentHashMapCopyOnWriteArrayList

答案 7 :(得分:3)

如果您使用 Spring Framework 。有:org.springframework.util.MultiValueMap

创建不可修改的多值地图:

Map<String,List<String>> map = ...
MultiValueMap<String, String> multiValueMap = CollectionUtils.toMultiValueMap(map);

或使用org.springframework.util.LinkedMultiValueMap

答案 8 :(得分:2)

是和否。解决方案是为您的值构建一个Wrapper类,其中包含与您的密钥对应的2(3个或更多)值。

答案 9 :(得分:2)

答案 10 :(得分:1)

最简单的方法是使用谷歌收藏库:

import com.google.common.collect.ArrayListMultimap; 导入com.google.common.collect.Multimap;

公共课测试{

public static void main(final String[] args) {

    // multimap can handle one key with a list of values
    final Multimap<String, String> cars = ArrayListMultimap.create();
    cars.put("Nissan", "Qashqai");
    cars.put("Nissan", "Juke");
    cars.put("Bmw", "M3");
    cars.put("Bmw", "330E");
    cars.put("Bmw", "X6");
    cars.put("Bmw", "X5");

    cars.get("Bmw").forEach(System.out::println);

    // It will print the:
    // M3
    // 330E
    // X6
    // X5
}

}

maven链接:https://mvnrepository.com/artifact/com.google.collections/google-collections/1.0-rc2

更多内容:http://tomjefferys.blogspot.be/2011/09/multimaps-google-guava.html

答案 11 :(得分:1)

 import java.io.*;
 import java.util.*;

 import com.google.common.collect.*;

 class finTech{
public static void main(String args[]){
       Multimap<String, String> multimap = ArrayListMultimap.create();
       multimap.put("1","11");
       multimap.put("1","14");
       multimap.put("1","12");
       multimap.put("1","13");
       multimap.put("11","111");
       multimap.put("12","121");
        System.out.println(multimap);
        System.out.println(multimap.get("11"));
   }                                                                                            
 }                                                                    

输出:

     {"1"=["11","12","13","14"],"11"=["111"],"12"=["121"]}

      ["111"]

这是实用程序功能的Google-Guava库。这是必需的解决方案。

答案 12 :(得分:0)

我无法对Paul的评论发表回复,所以我在这里为Vidhya创建新评论:

Wrapper将是我们想要存储为值的两个类的SuperClass

和内部包装类,我们可以将关联作为两个类对象的实例变量对象。

e.g。

class MyWrapper {

 Class1 class1obj = new Class1();
 Class2 class2obj = new Class2();
...
}

HashMap 中我们可以这样做,

Map<KeyObject, WrapperObject> 

WrapperObj 会有类变量:class1Obj, class2Obj

答案 13 :(得分:0)

你可以隐含地这样做。

// Create the map. There is no restriction to the size that the array String can have
HashMap<Integer, String[]> map = new HashMap<Integer, String[]>();

//initialize a key chosing the array of String you want for your values
map.put(1, new String[] { "name1", "name2" });

//edit value of a key
map.get(1)[0] = "othername";

这非常简单有效。 如果您想要不同类的值,则可以执行以下操作:

HashMap<Integer, Object[]> map = new HashMap<Integer, Object[]>();

答案 14 :(得分:0)

可以使用identityHashMap完成,条件是键比较将由==运算符完成,而不是等于()。

答案 15 :(得分:0)

我更喜欢以下内容来存储任意数量的变量,而无需创建单独的类。

final public static Map<String, Map<String, Float>> myMap    = new HashMap<String, Map<String, Float>>();

答案 16 :(得分:0)

以下是答案:):))

String key =“services_servicename”

ArrayList数据;

for(int i = 0; i lesssthen data.size(); i ++){

        HashMap<String, String> servicesNameHashmap = new HashMap<String, String>();
        servicesNameHashmap.put(key,data.get(i).getServiceName());
        mServiceNameArray.add(i,servicesNameHashmap);   }

我获得了最佳成绩。

你只需要像

一样创建新的HashMap

HashMap servicesNameHashmap = new HashMap();

在你的For循环中

。它将具有相同的效果,如相同的键和多个值。

快乐编码:)

答案 17 :(得分:0)

我习惯于在Objective C中使用数据字典这样做。在Android for Java中获取类似结果更难。我最终创建了一个自定义类,然后只是做了我的自定义类的哈希映射。

iOS

答案 18 :(得分:0)

我们可以创建一个具有多个键或值的类,并且该类的对象可以用作map中的参数。 您可以参考https://stackoverflow.com/a/44181931/8065321

答案 19 :(得分:0)

使用Java收集器

// Group employees by department
Map<Department, List<Employee>> byDept = employees.stream()
                    .collect(Collectors.groupingBy(Employee::getDepartment));

部门是您的关键

答案 20 :(得分:0)

Apache Commons集合类可以在同一键下实现多个值。

UIElement

Maven依赖

GroupItem

答案 21 :(得分:-8)

尝试 LinkedHashMap ,示例:

Map<String,String> map = new LinkedHashMap<String,String>();    
map.put('1','linked');map.put('1','hash');    
map.put('2','map');map.put('3','java');.. 

输出:

  

键:1,1,2,3

     

值:链接,哈希,地图,java