簡體   English   中英

同一個鍵下有多個值的HashMap

[英]HashMap with multiple values under the same key

我們是否可以實現一個鍵和兩個值的HashMap。 就像 HashMap 一樣?

請幫助我,也告訴(如果沒有辦法)任何其他方式來實現以一個為鍵的三個值的存儲?

你可以:

  1. 使用具有列表作為值的地圖。 Map<KeyType, List<ValueType>>
  2. 創建一個新的包裝器類並將此包裝器的實例放置在地圖中。 Map<KeyType, WrapperType>
  3. 使用類似類的元組(節省創建大量包裝器)。 Map<KeyType, Tuple<Value1Type, Value2Type>>
  4. 並排使用多個地圖。

例子

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"];

此解決方案的缺點是兩個地圖相關性並不明顯,編程錯誤可能會導致兩個地圖不同步。

不,不僅僅是作為HashMap 您基本上需要一個從鍵到值集合的HashMap

如果你樂於使用外部庫, GuavaMultimap有這個概念,有ArrayListMultimapHashMultimapLinkedHashMultimap等實現。

Multimap<String, Integer> nameToNumbers = HashMultimap.create();

System.out.println(nameToNumbers.put("Ann", 5)); // true
System.out.println(nameToNumbers.put("Ann", 5)); // false
nameToNumbers.put("Ann", 6);
nameToNumbers.put("Sam", 7);

System.out.println(nameToNumbers.size()); // 3
System.out.println(nameToNumbers.keySet().size()); // 2

另一個不錯的選擇是使用 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包含“A”、“B”和“C”。

從番石榴庫中查看Multimap及其實現 - HashMultimap

類似於 Map 的集合,但可以將多個值與單個鍵相關聯。 如果使用相同的鍵但不同的值調用 put(K, V) 兩次,則多重映射包含從鍵到兩個值的映射。

我使用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];
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);

如果您使用Spring 框架 有: org.springframework.util.MultiValueMap

創建不可修改的多值映射:

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

或者使用org.springframework.util.LinkedMultiValueMap

只是為了記錄,純 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

最簡單的方法是使用谷歌收藏庫:

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

public class Test {

    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

是和否。 解決方案是為您的值構建一個 Wrapper 類,其中包含與您的鍵對應的 2 個(3 個或更多)值。

String key= "services_servicename"

ArrayList<String> data;

for(int i = 0; i lessthen data.size(); i++) {
    HashMap<String, String> servicesNameHashmap = new HashMap<String, String>();
    servicesNameHashmap.put(key,data.get(i).getServiceName());
    mServiceNameArray.add(i,servicesNameHashmap);
}

我得到了最好的結果。

你只需要像這樣創建新的HashMap

HashMap<String, String> servicesNameHashmap = new HashMap<String, String>();

在你的for循環中。 它將具有相同的鍵和多個值的相同效果。

使用 Java 收集器

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

部門是你的關鍵

 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 庫。 這是必需的解決方案。

我無法對 Paul 的評論發表回復,所以我在這里為 Vidhya 創建新評論:

Wrapper 將是我們要存儲為值的兩個類的SuperClass

在包裝類中,我們可以將關聯作為兩個類對象的實例變量對象。

例如

class MyWrapper {

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

HashMap 中我們可以這樣放置

Map<KeyObject, WrapperObject> 

WrapperObj將有類變量: class1Obj, class2Obj

你可以隱式地做到這一點。

// 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[]>();

可以使用 identityHashMap 來完成,條件是鍵比較將由 == 運算符而不是 equals() 完成。

我更喜歡以下內容來存儲任意數量的變量,而不必創建單獨的類。

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

我已經習慣於在 Objective C 中使用數據字典來做這件事。在 Android 的 Java 中很難獲得類似的結果。 我最終創建了一個自定義類,然后只是對我的自定義類做了一個哈希圖。

public class Test1 {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.addview);

//create the datastring
    HashMap<Integer, myClass> hm = new HashMap<Integer, myClass>();
    hm.put(1, new myClass("Car", "Small", 3000));
    hm.put(2, new myClass("Truck", "Large", 4000));
    hm.put(3, new myClass("Motorcycle", "Small", 1000));

//pull the datastring back for a specific item.
//also can edit the data using the set methods.  this just shows getting it for display.
    myClass test1 = hm.get(1);
    String testitem = test1.getItem();
    int testprice = test1.getPrice();
    Log.i("Class Info Example",testitem+Integer.toString(testprice));
}
}

//custom class.  You could make it public to use on several activities, or just include in the activity if using only here
class myClass{
    private String item;
    private String type;
    private int price;

    public myClass(String itm, String ty, int pr){
        this.item = itm;
        this.price = pr;
        this.type = ty;
    }

    public String getItem() {
        return item;
    }

    public void setItem(String item) {
        this.item = item;
    }

    public String getType() {
        return item;
    }

    public void setType(String type) {
        this.type = type;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

}

我們可以創建一個具有多個鍵或值的類,這個類的對象可以用作映射中的參數。 可以參考https://stackoverflow.com/a/44181931/8065321

Apache Commons 集合類可以在同一個鍵下實現多個值。

MultiMap multiMapDemo = new MultiValueMap();

multiMapDemo .put("fruit", "Mango");
multiMapDemo .put("fruit", "Orange");
multiMapDemo.put("fruit", "Blueberry");

System.out.println(multiMapDemo.get("fruit"));

Maven 依賴

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-collections4</artifactId>
   <version>4.4</version>
</dependency>

我們是否可以用一個鍵和兩個值來實現HashMap。 就像HashMap一樣?

還請告訴我(如果沒有辦法)通過其他任何方法來實現三個值的存儲(以一個為鍵)的方法,對我有幫助嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM