同じキーの下に複数の値を持つHas​​hMap


199

1つのキーと2つの値を持つHas​​hMapを実装することは可能ですか?HashMapと同じですか?

1つをキーとして3つの値のストレージを実装する他の方法を(方法がない場合)伝えることによって、私を助けてください。



友人に感謝します...しかしMultiHashMapの使用にはいくつか制限があります
vidhya

回答:


266

あなたは出来る:

  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つの値にバインドされないことです。

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

このソリューションの欠点は、2つのマップが関連していることが明らかではないことです。プログラムのエラーにより、2つのマップが同期していない可能性があります。


こんにちはポール...それをもう少し明確にすることができます...?例によって...?
vidhya

@vidhya:特に問題に当てはまるものはどれですか。複数のオブジェクトは同じタイプですか、それとも異なりますか?
Paul Ruane、2011

実例は素晴らしいでしょう。
Xonatron、2012

@ Paul、#3の簡単なサンプルコード Map<KeyType, Tuple<Value1Type, Value2Type>>
Joarder Kamal 2013

@CoolMind私は人々が間違いを回避することができると確信しています:またはあなたはそれらを修正することができますか?
Paul Ruane

61

いいえ、だけではありませんHashMap。基本的にHashMapは、キーから値のコレクションまでを必要とします。

あなたが外部のライブラリを使用して満足している場合は、グアバは内まさにこのコンセプトがあるMultimapような実装とArrayListMultimapしてをHashMultimap


@ジョン、OPによって質問された上記の質問に対してJavaでの実用的な例を提供できますか。投稿できれば非常に高く評価されます
Deepak

2
@Deepak:グアバマルチマップの例を検索すると、サンプルコードが見つかります。
Jon Skeet

1
@Deepak:基本的には、ArrayListMultimap自分のようなものを構築するか、単にa HashMap<String, List<Integer>>か何かを使用します。基本的に、値が初めて追加されるときは常に空のリストを作成する必要があります。
Jon Skeet、2011

1
あなたがのために働い例を持っているかHashMap<String, List<Integer>>
ディーパック・

9
@Deepak:自分で例を作成してみることをお勧めします。行き詰まった場合は、可能な限りコードを含めて質問してください。そうすれば、もっと多くを学ぶことができます。
Jon Skeet、2011

23

別の良い選択は、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」を含むコレクションになります。


13

Multimapguavaライブラリとその実装から見てみましょう-HashMultimap

Mapに似たコレクションですが、複数の値を単一のキーに関連付ける場合があります。同じキーで値が異なるput(K、V)を2回呼び出すと、マルチマップにはキーから両方の値へのマッピングが含まれます。


7

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

1
私にはこれが最良の答えです。それはよりシンプルで、より簡潔で、抽象的なものではありません。
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

参考までに、純粋な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インスタンス必要に使用されます。


使用することをお勧めしますcomputeIfAbsentmap.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
saka1029 2016

3

Spring Frameworkを使用する場合。あります:org.springframework.util.MultiValueMap

変更不可能な複数値マップを作成するには:

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

または使用 org.springframework.util.LinkedMultiValueMap


2

はいといいえ。解決策は、キーに対応する2つ(3つ以上)の値を含む値のWrapperクラスを構築することです。



2

最も簡単な方法は、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
    }

}

mavenリンク:https : //mvnrepository.com/artifact/com.google.collections/google-collections/1.0-rc2

詳細: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);
}

私は最高の結果を得ました。

あなただけのHashMapような新しいを作成する必要があります

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

あなたのforループで。同じキーと複数の値のように同じ効果があります。


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ライブラリです。これは必要なソリューションです。


これは有効なソリューションであり、私はこのアプローチを何度か使用しました。
letowianka

はいそれは機能しますが、[]フォルマートでデータを表示しています私はそれらのアイテムを1つずつここにスタックさせる方法をそれらに1つずつ欲しい
Sunil Chaudhary

0

Paulのコメントに返信を投稿できなかったため、Vidhyaの新しいコメントをここに作成します。

ラッパーはSuperClass、値として格納する2つのクラスのになります。

ラッパークラスの内部では、2つのクラスオブジェクトのインスタンス変数オブジェクトとして関連付けを配置できます。

例えば

class MyWrapper {

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

そしてHashMapでは、このように置くことができます、

Map<KeyObject, WrapperObject> 

WrapperObjにはクラス変数があります:class1Obj, class2Obj


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

0

キーの比較がequals()ではなく==演算子によって行われるという条件に従って、identityHashMapを使用して行うことができます。


0

個別のクラスを作成せずに、任意の数の変数を格納するには、次のようにします。

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

0

私はObjective CのData Dictionaryでこれを行うのに慣れています。Javafor 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;
    }

}


0

Javaコレクターの使用

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

部門はあなたの鍵です


-9

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

値:linked、hash、map、java


7
それはうまくいきません。 linkedで置き換えたため、マップにはもう存在しませんhash
ジェフメルカド2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.