HashMap dengan beberapa nilai di bawah kunci yang sama


199

Apakah mungkin bagi kami untuk mengimplementasikan HashMap dengan satu kunci dan dua nilai. Sama seperti HashMap?

Tolong bantu saya, juga dengan mengatakan (jika tidak ada cara) cara lain untuk menerapkan penyimpanan tiga nilai dengan satu sebagai kuncinya?



Terima kasih teman-teman ... tetapi saya memiliki beberapa batasan dalam menggunakan MultiHashMap
vidhya

Jawaban:


266

Anda bisa:

  1. Gunakan peta yang memiliki daftar sebagai nilainya. Map<KeyType, List<ValueType>>.
  2. Buat kelas pembungkus baru dan tempatkan instance pembungkus ini di peta. Map<KeyType, WrapperType>.
  3. Gunakan kelas tuple like (menghemat membuat banyak pembungkus). Map<KeyType, Tuple<Value1Type, Value2Type>>.
  4. Gunakan peta mulitple berdampingan.

Contohnya

1. Peta dengan daftar sebagai nilainya

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

Kerugian dengan pendekatan ini adalah bahwa daftar tidak terikat tepat pada dua nilai.

2. Menggunakan kelas wrapper

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

Kerugian dari pendekatan ini adalah Anda harus menulis banyak kode boiler-plate untuk semua kelas kontainer yang sangat sederhana ini.

3. Menggunakan tuple

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

Ini adalah solusi terbaik menurut saya.

4. Beberapa peta

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

Kerugian dari solusi ini adalah tidak jelas bahwa kedua peta terkait, kesalahan terprogram dapat melihat dua peta keluar dari sinkronisasi.


Hai Paul ... bisakah kamu membuatnya lebih jelas ...? Dengan contoh ...?
vidhya

@vidhya: mana yang cocok dengan masalah Anda? Apakah objek mulitple Anda memiliki tipe yang sama atau berbeda?
Paul Ruane

Contoh akan sangat bagus.
Xonatron

@ Paul, kode contoh sederhana apa pun untuk # 3 Map<KeyType, Tuple<Value1Type, Value2Type>>
Joarder Kamal

@ CoolMind Saya yakin orang bisa mengatasi kesalahan: atau Anda bisa memperbaikinya?
Paul Ruane

61

Tidak, tidak hanya sebagai a HashMap. Anda pada dasarnya akan membutuhkanHashMap dari kunci ke kumpulan nilai.

Jika Anda senang menggunakan perpustakaan eksternal, Guava memiliki konsep ini persis Multimapdengan implementasi seperti ArrayListMultimapdan HashMultimap.


@ Jon, dapatkah Anda memberikan contoh kerja di Jawa untuk pertanyaan di atas yang ditanyakan oleh OP. Sangat menghargai jika Anda dapat mempostingnya
Deepak

2
@Deepak: Cari contoh multimap jambu dan Anda akan menemukan kode sampel.
Jon Skeet

1
@Deepak: Pada dasarnya kamu akan membangun sesuatu seperti ArrayListMultimapdirimu ... atau hanya menggunakan HashMap<String, List<Integer>>atau apa pun. Anda harus membuat daftar kosong kapan saja nilai ditambahkan untuk pertama kalinya.
Jon Skeet

1
apakah Anda memiliki contoh kerja untukHashMap<String, List<Integer>>
Deepak

9
@Deepak: Saya sarankan Anda mencoba membuat contoh sendiri, dan jika Anda buntu, ajukan pertanyaan termasuk kode sejauh yang Anda punya. Anda akan belajar lebih banyak dengan cara itu.
Jon Skeet

23

Pilihan bagus lainnya adalah menggunakan MultiValuedMap dari Apache Commons. Lihatlah Semua Kelas Pelaksana yang Dikenal di bagian atas halaman untuk implementasi khusus.

Contoh:

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

bisa diganti dengan

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

Begitu,

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

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

akan menghasilkan koleksi yang collmengandung "A", "B", dan "C".


13

Lihatlah Multimapdari perpustakaan jambu biji dan implementasinya -HashMultimap

Koleksi yang mirip dengan Peta, tetapi dapat mengaitkan beberapa nilai dengan satu kunci. Jika Anda memanggil put (K, V) dua kali, dengan kunci yang sama tetapi nilai yang berbeda, multimap berisi pemetaan dari kunci ke kedua nilai.


7

Saya gunakan Map<KeyType, Object[]>untuk mengaitkan beberapa nilai dengan kunci di Peta. Dengan cara ini, saya dapat menyimpan beberapa nilai dari berbagai jenis yang terkait dengan kunci. Anda harus berhati-hati dengan mempertahankan urutan penyisipan dan pengambilan yang tepat dari Obyek [].

Contoh: Pertimbangkan, kami ingin menyimpan informasi Siswa. Kuncinya adalah id, sementara kami ingin menyimpan nama, alamat, dan email yang terkait dengan siswa.

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

1
Bagi saya ini adalah jawaban terbaik. Ini lebih sederhana, lebih ringkas, dan kurang abstrak.
Morey

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

4

Sekadar catatan, solusi JDK8 murni akan menggunakan Map::computemetode:

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

Seperti

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

dengan output:

bar: foo
first: hello, foo, hello

Perhatikan bahwa untuk memastikan konsistensi jika beberapa utas mengakses struktur data ini, ConcurrentHashMapdan CopyOnWriteArrayListmisalnya perlu digunakan.


Lebih baik digunakan computeIfAbsent. map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
saka1029

3

Jika Anda menggunakan Spring Framework . Ada:org.springframework.util.MultiValueMap .

Untuk membuat peta multi nilai yang tidak dapat diverifikasi:

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

Atau gunakan org.springframework.util.LinkedMultiValueMap


2

Iya dan tidak. Solusinya adalah membangun clas Wrapper untuk nilai Anda yang berisi 2 (3, atau lebih) nilai yang sesuai dengan kunci Anda.



2

Cara termudah adalah dengan menggunakan perpustakaan koleksi google:

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
    }

}

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

lebih lanjut tentang ini: http://tomjefferys.blogspot.be/2011/09/multimaps-google-guava.html


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

Saya sudah mendapat Hasil Terbaik.

Anda hanya perlu membuat HashMaplike baru

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

di forlingkaran Anda . Ini akan memiliki efek yang sama seperti kunci yang sama dan beberapa nilai.


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

Keluaran:

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

      ["111"]

Ini adalah perpustakaan Google-Guava untuk fungsi utilitas. Ini adalah solusi yang diperlukan.


Ini adalah solusi yang valid dan saya telah menggunakan pendekatan ini pada beberapa kesempatan.
letowianka

ya itu berfungsi tetapi ini menunjukkan data dalam format [] saya ingin item-item itu satu per satu cara agar pls saya macet di sini
Sunil Chaudhary

0

Saya tidak dapat mengirim balasan atas komentar Paul, jadi saya membuat komentar baru untuk Vidhya di sini:

Wrapper akan menjadi SuperClassuntuk dua kelas yang ingin kita simpan sebagai nilai.

dan di dalam kelas wrapper, kita bisa meletakkan asosiasi sebagai objek variabel instan untuk dua objek kelas.

misalnya

class MyWrapper {

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

dan di HashMap kita bisa menggunakan cara ini,

Map<KeyObject, WrapperObject> 

WrapperObj akan memiliki variabel kelas:class1Obj, class2Obj


0

Anda dapat melakukannya secara implisit.

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

Ini sangat sederhana dan efektif. Jika Anda menginginkan nilai kelas yang berbeda, Anda dapat melakukan hal berikut:

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

0

Dapat dilakukan dengan menggunakan identityHashMap, dengan syarat bahwa perbandingan kunci akan dilakukan oleh operator == dan tidak sama dengan ().


0

Saya lebih suka yang berikut ini untuk menyimpan sejumlah variabel tanpa harus membuat kelas yang terpisah.

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

0

Saya sangat terbiasa melakukan ini dengan Kamus Data di Objective C. Lebih sulit untuk mendapatkan hasil yang serupa di Java untuk Android. Saya akhirnya menciptakan kelas kustom, dan kemudian hanya melakukan hashmap kelas kustom saya.

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

}


0

Menggunakan Java Collectors

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

di mana departemen adalah kunci Anda


-9

Coba LinkedHashMap , contoh:

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

keluaran:

kunci: 1,1,2,3

nilai: ditautkan, hash, peta, java


7
Itu tidak akan berhasil. linkedtidak akan ada di peta lagi karena Anda menggantinya dengan hash.
Jeff Mercado
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.