سؤال

كنت تريد أن يكون لها خريطة مع مفاتيح مكررة.

أعرف أن هناك العديد من خريطة تطبيقات (الكسوف يظهر لي 50) لذا الرهان يجب أن يكون هناك واحد الذي يسمح بذلك.أعلم أنه من السهل الكتابة الخريطة الخاصة بك أن يفعل هذا, ولكن أود أن بدلا من استخدام بعض الحل الموجود.

ربما شيء في العموم مجموعات جوجل أو مجموعات ؟

هل كانت مفيدة؟

المحلول

أنت تبحث عن multimap، والواقع على حد سواء المشاعات-مجموعات والجوافة لديهم عدة تطبيقات لذلك. Multimaps تسمح مفاتيح متعددة من خلال الحفاظ على مجموعة من القيم في مفتاح، أي يمكنك وضع كائن واحد في الخريطة، ولكن يمكنك استرجاع مجموعة.

إذا يمكنك استخدام جافا 5، وأود أن تفضل الجوافة و<لأ href = "https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/Multimap.html "يختلط =" noreferrer "> Multimap كما هو الوراثة علم.

نصائح أخرى

ونحن لسنا بحاجة إلى الاعتماد على مجموعات جوجل مكتبة خارجية. يمكنك ببساطة تطبيق خارطة التالية:

Map<String, ArrayList<String>> hashMap = new HashMap<String, ArrayList>();

public static void main(String... arg) {
   // Add data with duplicate keys
   addValues("A", "a1");
   addValues("A", "a2");
   addValues("B", "b");
   // View data.
   Iterator it = hashMap.keySet().iterator();
   ArrayList tempList = null;

   while (it.hasNext()) {
      String key = it.next().toString();             
      tempList = hashMap.get(key);
      if (tempList != null) {
         for (String value: tempList) {
            System.out.println("Key : "+key+ " , Value : "+value);
         }
      }
   }
}

private void addValues(String key, String value) {
   ArrayList tempList = null;
   if (hashMap.containsKey(key)) {
      tempList = hashMap.get(key);
      if(tempList == null)
         tempList = new ArrayList();
      tempList.add(value);  
   } else {
      tempList = new ArrayList();
      tempList.add(value);               
   }
   hashMap.put(key,tempList);
}

يرجى التأكد من ضبط رمز.

Multimap<Integer, String> multimap = ArrayListMultimap.create();

multimap.put(1, "A");
multimap.put(1, "B");
multimap.put(1, "C");
multimap.put(1, "A");

multimap.put(2, "A");
multimap.put(2, "B");
multimap.put(2, "C");

multimap.put(3, "A");

System.out.println(multimap.get(1));
System.out.println(multimap.get(2));       
System.out.println(multimap.get(3));

الناتج هو:

[A,B,C,A]
[A,B,C]
[A]

ملاحظة: نحن بحاجة إلى استيراد ملفات المكتبة.

http://www.java2s.com/Code/Jar/g/Downloadgooglecollectionsjar.htm

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

أو https://commons.apache.org/proper/commons-collections/download_collections.cgi

import org.apache.commons.collections.MultiMap;
import org.apache.commons.collections.map.MultiValueMap;

هل يمكن ببساطة تمرير مجموعة من القيم لقيمة في HashMap العادية، وبالتالي محاكاة مفاتيح مكررة، وسيكون متروك لكم لتقرر ما هي البيانات للاستخدام.

ويمكنك أيضا مجرد استخدام MultiMap ، على الرغم من أنني لا أحب فكرة مفاتيح مكررة نفسي.

إذا كنت تريد تكرار حول قائمة رئيسية ذات قيمة أزواج (كما كتب في التعليق)، ثم قائمة أو صفيف يجب أن يكون أفضل. الجمع بين أول المفاتيح والقيم الخاصة بك:

public class Pair
{
   public Class1 key;
   public Class2 value;

   public Pair(Class1 key, Class2 value)
   {
      this.key = key;
      this.value = value;
   }

}

واستبدال CLASS1 وCLASS2 مع الأنواع التي تريد استخدامها للمفاتيح والقيم.

والآن يمكنك وضعها في صفيف أو قائمة وتكرار فوقها:

Pair[] pairs = new Pair[10];
...
for (Pair pair : pairs)
{
   ...
}
commons.apache.org

MultiValueMap class

ويمكن حل هذه المشكلة مع قائمة خريطة دخول List<Map.Entry<K,V>>. نحن لسنا بحاجة إلى استخدام المكتبات الخارجية لا ولا تطبيق جديد من الخريطة. يمكن إنشاء إدخال تعيين مثل هذا:     Map.Entry<String, Integer> entry = new AbstractMap.SimpleEntry<String, Integer>("key", 1);

والتعلم من أخطائي ... من فضلك لا تنفيذ هذا بنفسك. الجوافة multimap هو الطريق للذهاب.

ووتعزيز المشترك المطلوبة في multimaps هو عدم السماح أزواج مكررة مفاتيح ذات قيمة.

وتنفيذ / تغيير هذا في التطبيق الخاص بك يمكن أن تكون مزعجة.

في الجوافة لها بسيطة مثل:

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

ArrayListMultimap<String, Integer> allow_dupe_key_plus_val = ArrayListMultimap.create();

وكان البديل يختلف قليلا من هذه المشكلة: كان مطلوبا لربط اثنين من قيم مختلفة مع نفس المفتاح. مجرد نشرها هنا في حال يساعد الآخرين، ولقد قدم HashMap كقيمة:

/* @param frameTypeHash: Key -> Integer (frameID), Value -> HashMap (innerMap)
   @param innerMap: Key -> String (extIP), Value -> String
   If the key exists, retrieve the stored HashMap innerMap 
   and put the constructed key, value pair
*/
  if (frameTypeHash.containsKey(frameID)){
            //Key exists, add the key/value to innerHashMap
            HashMap innerMap = (HashMap)frameTypeHash.get(frameID);
            innerMap.put(extIP, connName+":"+frameType+":"+interfaceName);

        } else {
            HashMap<String, String> innerMap = new HashMap<String, String>();
            innerMap.put(extIP, connName+":"+frameType+":"+interfaceName);
            // This means the key doesn't exists, adding it for the first time
            frameTypeHash.put(frameID, innerMap );
        }
}

في رمز أعلاه تتم قراءة frameID المفتاح من السلسلة الأولى من ملف الإدخال في كل سطر، هي التي شيدت قيمة frameTypeHash عن طريق تقسيم خط المتبقية وتخزينها وجوه سلسلة أصلا، على مدى فترة من الزمن بدأ الملف بعد خطوط متعددة (مع قيم مختلفة) مرتبطة مع مفتاح frameID نفسه، لذلك تم الكتابة frameTypeHash مع السطر الأخير كقيمة. أنا محل كائن سلسلة مع الكائن HashMap آخر كحقل قيمة، وهذا ساعد في الحفاظ على مفتاح واحد لرسم الخرائط قيمة مختلفة.

class  DuplicateMap<K, V> 
{
    enum MapType
    {
        Hash,LinkedHash
    }

    int HashCode = 0;
    Map<Key<K>,V> map = null;

    DuplicateMap()
    {
        map = new HashMap<Key<K>,V>();
    }

    DuplicateMap( MapType maptype )
    {
        if ( maptype == MapType.Hash ) {
            map = new HashMap<Key<K>,V>();
        }
        else if ( maptype == MapType.LinkedHash ) {
            map = new LinkedHashMap<Key<K>,V>();
        }
        else
            map = new HashMap<Key<K>,V>();
    }

    V put( K key, V value  )
    {

        return map.put( new Key<K>( key , HashCode++ ), value );
    }

    void putAll( Map<K, V> map1 )
    {
        Map<Key<K>,V> map2 = new LinkedHashMap<Key<K>,V>();

        for ( Entry<K, V> entry : map1.entrySet() ) {
            map2.put( new Key<K>( entry.getKey() , HashCode++ ), entry.getValue());
        }
        map.putAll(map2);
    }

    Set<Entry<K, V>> entrySet()
    {
        Set<Entry<K, V>> entry = new LinkedHashSet<Map.Entry<K,V>>();
        for ( final Entry<Key<K>, V> entry1 : map.entrySet() ) {
            entry.add( new Entry<K, V>(){
                private K Key = entry1.getKey().Key();
                private V Value = entry1.getValue();

                @Override
                public K getKey() {
                    return Key;
                }

                @Override
                public V getValue() {
                    return Value;
                }

                @Override
                public V setValue(V value) {
                    return null;
                }});
        }

        return entry;
    }

    @Override
    public String toString() {
        StringBuilder builder = new  StringBuilder();
        builder.append("{");
        boolean FirstIteration = true;
        for ( Entry<K, V> entry : entrySet() ) {
            builder.append( ( (FirstIteration)? "" : "," ) + ((entry.getKey()==null) ? null :entry.getKey().toString() ) + "=" + ((entry.getValue()==null) ? null :entry.getValue().toString() )  );
            FirstIteration = false;
        }
        builder.append("}");
        return builder.toString();
    }

    class Key<K1>
    {
        K1 Key;
        int HashCode;

        public Key(K1 key, int hashCode) {
            super();
            Key = key;
            HashCode = hashCode;
        }

        public K1 Key() {
            return Key;
        }

        @Override
        public String toString() {
            return  Key.toString() ;
        }

        @Override
        public int hashCode() {

            return HashCode;
        }
    }

هل يمكن أن يفسر أيضا السياق الذي تحاول تنفيذ خريطة مع مفاتيح مكررة؟ وأنا واثق يمكن أن يكون هناك حل أفضل. وتهدف خرائط للحفاظ على مفاتيح فريدة من نوعها لسبب وجيه. على الرغم من إذا كنت تريد حقا أن تفعل ذلك. يمكنك توسيع دائما الطبقة إرسال بريد مخصصة بسيطة خريطة الطبقة التي لديه وظيفة تخفيف الاصطدام وسوف تمكنك من الحفاظ مداخل متعددة مع نفس المفاتيح.

ملحوظة: يجب تنفيذ وظيفة تخفيف الاصطدام مثل ذلك، مفاتيح الاصطدام يتم تحويلها إلى مجموعة فريدة من نوعها "دائما". شيء بسيط مثل المفتاح مع شفرة التجزئة كائن أو شيء إلحاق؟

ولمجرد أن يكون كاملة، لديها أباتشي العموم مجموعات أيضا <لأ href = "http://commons.apache.org/collections/api-release/org/apache/commons/collections/MultiMap.html" يختلط = " نوفولو noreferrer "> MultiMap . الجانب السلبي بالطبع هو أن أباتشي العموم لا تستخدم الوراثة.

ومع قليل الإختراق التي يمكنك استخدامها HashSet مع مفاتيح مكررة. تحذير: هذا هو بشدة HashSet التنفيذ التابعة.

class MultiKeyPair {
    Object key;
    Object value;

    public MultiKeyPair(Object key, Object value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public int hashCode() {
        return key.hashCode();
    }
}

class MultiKeyList extends MultiKeyPair {
    ArrayList<MultiKeyPair> list = new ArrayList<MultiKeyPair>();

    public MultiKeyList(Object key) {
        super(key, null);
    }

    @Override
    public boolean equals(Object obj) {
        list.add((MultiKeyPair) obj);
        return false;
    }
}

public static void main(String[] args) {
    HashSet<MultiKeyPair> set = new HashSet<MultiKeyPair>();
    set.add(new MultiKeyPair("A","a1"));
    set.add(new MultiKeyPair("A","a2"));
    set.add(new MultiKeyPair("B","b1"));
    set.add(new MultiKeyPair("A","a3"));

    MultiKeyList o = new MultiKeyList("A");
    set.contains(o);

    for (MultiKeyPair pair : o.list) {
        System.out.println(pair.value);
    }
}

وإذا كان هناك مفاتيح مكررة ثم مفتاح قد تتوافق مع أكثر من قيمة واحدة. الحل واضح هو لتعيين مفتاح قائمة من هذه القيم.

وعلى سبيل المثال في بيثون:

map = dict()
map["driver"] = list()
map["driver"].append("john")
map["driver"].append("mike")
print map["driver"]          # It shows john and mike
print map["driver"][0]       # It shows john
print map["driver"][1]       # It shows mike

وأنا استخدم هذا:

وjava.util.List<java.util.Map.Entry<String,Integer>> pairList= new java.util.ArrayList<>();

 1, Map<String, List<String>> map = new HashMap<>();
<اقتباس فقرة>   

وهذا الحل مطول له عيوب متعددة ومعرضة للأخطاء. هذا       يعني أننا في حاجة إلى مثيل كوكتيل لكل قيمة، وتحقق لل       وجودها قبل إضافة أو إزالة قيمة، حذفه يدويا عندما لا       يتم ترك القيم، إلى آخره.

2, org.apache.commons.collections4.MultiMap interface
3, com.google.common.collect.Multimap interface 

جافا خريطة مكررة مفاتيح

وماذا عن مثل هذا impl MultiMap؟

public class MultiMap<K, V> extends HashMap<K, Set<V>> {
  private static final long serialVersionUID = 1L;
  private Map<K, Set<V>> innerMap = new HashMap<>();

  public Set<V> put(K key, V value) {
    Set<V> valuesOld = this.innerMap.get(key);
    HashSet<V> valuesNewTotal = new HashSet<>();
    if (valuesOld != null) {
      valuesNewTotal.addAll(valuesOld);
    }
    valuesNewTotal.add(value);
    this.innerMap.put(key, valuesNewTotal);
    return valuesOld;
  }

  public void putAll(K key, Set<V> values) {
    for (V value : values) {
      put(key, value);
    }
  }

  @Override
  public Set<V> put(K key, Set<V> value) {
    Set<V> valuesOld = this.innerMap.get(key);
    putAll(key, value);
    return valuesOld;
  }

  @Override
  public void putAll(Map<? extends K, ? extends Set<V>> mapOfValues) {
    for (Map.Entry<? extends K, ? extends Set<V>> valueEntry : mapOfValues.entrySet()) {
      K key = valueEntry.getKey();
      Set<V> value = valueEntry.getValue();
      putAll(key, value);
    }
  }

  @Override
  public Set<V> putIfAbsent(K key, Set<V> value) {
    Set<V> valueOld = this.innerMap.get(key);
    if (valueOld == null) {
      putAll(key, value);
    }
    return valueOld;
  }

  @Override
  public Set<V> get(Object key) {
    return this.innerMap.get(key);
  }

  @Override
  etc. etc. override all public methods size(), clear() .....

}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top