HashMap с несколькими значениями под одним и тем же ключом

Возможно ли реализовать HashMap с одним ключом и двумя значениями. Как HashMap?

Пожалуйста, помогите мне, также, сообщив (если нет способа) каким-либо другим способом реализовать хранение трех значений с одним ключом?

Ответ 1

Вы можете:

  • Используйте карту, которая имеет список в качестве значения. Map<KeyType, List<ValueType>>.
  • Создайте новый класс-оболочку и поместите экземпляры этой оболочки на карту. Map<KeyType, WrapperType>.
  • Используйте кортеж типа class (сохраняет создание большого количества оберток). Map<KeyType, Tuple<Value1Type, Value2Type>>.
  • Использовать карты mulitple бок о бок.

Примеры

1. Карта со списком как значение

// create our map
Map<string, List<Person>> peopleByForename = new HashMap<string, List<Person>>();    

// populate it
List<Person> people = new ArrayList<Person>();
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<string, Wrapper>();

// 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["Bob"];
Person bob1 = bobs.Person1;
Person bob2 = bobs.Person2;

Недостатком такого подхода является то, что вам нужно написать много кода котельной для всех этих очень простых классов контейнеров.

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<string, Tuple2<Person, Person>>();

// 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<string, Person>();
Map<string, Person> secondPersonByForename = new HashMap<string, Person>();

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

Недостатком этого решения является то, что не очевидно, что две карты связаны, программная ошибка может видеть, что две карты выходят из синхронизации.

Ответ 2

Нет, не только как HashMap. Вам в основном понадобится HashMap от ключа до коллекции значений.

Если вы счастливы использовать внешние библиотеки, Guava имеет именно эту концепцию в Multimap с такими реализациями, как ArrayListMultimap и HashMultimap.

Ответ 3

Еще один приятный выбор - использовать MultiValuedMap от Apache Commons. Взгляните на Все известные классы реализации в верхней части страницы для специализированных реализаций.

Пример:

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".

Ответ 4

Взгляните на Multimap из guava-библиотек и его реализацию - HashMultimap

Коллекция, похожая на карту, но которая может связывать несколько значений с одним ключом. Если вы дважды вызываете put (K, V) с одним и тем же ключом, но с разными значениями, мультимап содержит сопоставления из ключа для обоих значений.

Ответ 5

Я использую Map<KeyType, Object[]> для связывания нескольких значений с ключом на карте. Таким образом, я могу хранить несколько значений различных типов, связанных с ключом. Вы должны заботиться, поддерживая правильный порядок вставки и извлечения из 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];

Ответ 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);

Ответ 7

Только для записи чистым решением 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

Обратите внимание, что для обеспечения согласованности в случае, когда несколько потоков обращаются к этой структуре данных, например, необходимо использовать ConcurrentHashMap и CopyOnWriteArrayList.

Ответ 8

Да и нет. Решение состоит в создании кластера Wrapper для ваших значений, содержащих 2 (3 или более) значения, соответствующие вашему ключу.

Ответ 10

Если вы используете Spring Framework. Существует: org.springframework.util.MultiValueMap.

Чтобы создать немодифицируемую карту с несколькими значениями:

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

Или используйте org.springframework.util.LinkedMultiValueMap

Ответ 11

Я не могу опубликовать ответ на комментарий Paul, поэтому я создаю новый комментарий для Vidhya здесь:

Wrapper будет SuperClass для двух классов, которые мы хотим сохранить как значение.

и внутри класса оболочки, мы можем поместить ассоциации как объекты переменных экземпляра для двух объектов класса.

например.

class MyWrapper {

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

и в HashMap, мы можем сделать это,

Map<KeyObject, WrapperObject> 

WrapperObj будет иметь переменные класса: class1Obj, class2Obj

Ответ 12

Вы можете сделать это неявно.

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

Ответ 13

Может быть выполнено с использованием идентификатораHashMap, подвергнутого условию, что сравнение ключей будет выполняться оператором ==, а не равно().

Ответ 14

Я предпочитаю следующее хранить любое количество переменных без создания отдельного класса.

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

Ответ 15

Вот ОТВЕТ:):)

Строковый ключ = "services_servicename"

Данные ArrayList;

for (int я = 0; я lessthen data.size(); я ++) {

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

У меня есть лучшие результаты.

Вам просто нужно создать новый HashMap Like

HashMap servicesNameHashmap = new HashMap();

в вашей петле. Он будет иметь тот же эффект, что и тот же ключ и несколько значений.

Счастливое кодирование:)

Ответ 16

Я так привык делать это с помощью Словаря данных в Objective C. Сложнее было получить аналогичный результат в Java для Android. Я закончил создание пользовательского класса, а затем просто сделал хэш файл моего пользовательского класса.

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;
    }

}

Ответ 17

Мы можем создать класс, чтобы иметь несколько ключей или значений, и объект этого класса можно использовать в качестве параметра на карте. Вы можете обратиться к fooobar.com/questions/31376/...

Ответ 18

Самый простой способ - использовать библиотеку коллекций google:

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

Открытый класс 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 link: https://mvnrepository.com/artifact/com.google.collections/google-collections/1.0-rc2

подробнее об этом: http://tomjefferys.blogspot.be/2011/09/multimaps-google-guava.html

Ответ 19

Попробуйте 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