문제

중복 키가있는지도를 원합니다.

나는 많은지도 구현이 있다는 것을 알고 있습니다 (Eclipse는 약 50 명을 보여줍니다). 이 작업을 수행하는 자신의지도를 쉽게 작성하는 것이 쉽지만 기존 솔루션을 사용하고 싶습니다.

아마도 공통점 수집이나 Google 수집에 있을까요?

도움이 되었습니까?

해결책

당신은 멀티 맵을 찾고 있으며, 실제로 커먼즈 컬렉션과 구아바에는 몇 가지 구현이 있습니다. 멀티 맵은 키 당 값 모음을 유지하여 여러 키를 허용합니다. 즉, 단일 객체를 맵에 넣을 수는 있지만 컬렉션을 검색합니다.

Java 5를 사용할 수 있다면 Guava를 선호합니다. Multimap 제네릭 인식이므로.

다른 팁

Google Collections 외부 라이브러리에 의존 할 필요가 없습니다. 다음 맵을 간단히 구현할 수 있습니다.

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;

일반 해시 맵에서 값에 대한 값 배열을 전달할 수 있으므로 중복 키를 시뮬레이션 할 수 있으며 사용할 데이터를 결정하는 것은 귀하에게 달려 있습니다.

당신은 또한 a를 사용할 수도 있습니다 멀티 맵, 나는 중복 키의 아이디어를 직접 좋아하지는 않지만.

키 값 쌍 목록에 대해 반복하려면 (주석에 쓴대로) 목록이나 배열이 더 좋을 것입니다. 먼저 키와 값을 결합합니다.

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 구현을 사용할 필요가 없습니다. 맵 항목은 다음과 같이 만들 수 있습니다. Map.Entry<String, Integer> entry = new AbstractMap.SimpleEntry<String, Integer>("key", 1);

내 실수로부터 배우십시오 ... 제발 직접 구현하지 마십시오. Guava Multimap은 갈 길입니다.

멀티 맵에 필요한 일반적인 향상은 중복 키 값 쌍을 허용하는 것입니다.

구현에서이를 구현/변경하는 것은 성가신 일 수 있습니다.

Guava에서는 간단합니다.

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

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

이 문제의 변형이 약간 다릅니다. 두 가지 다른 값을 동일한 키와 연결해야했습니다. 다른 사람들을 돕는 경우에 여기에 게시하면 해시 맵을 값으로 소개했습니다.

/* @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 );
        }
}

위의 코드에서 Key FrameID는 각 줄의 입력 파일의 첫 번째 문자열에서 읽습니다. FrametypeHash의 값은 나머지 라인을 분할하여 구성되며 원래 문자열 객체로 저장되었으며, 일정 기간 동안 파일에 여러 줄을 갖기 시작했습니다 (). 동일한 frameid 키와 관련된 값이 다른 값으로, Frametypehash는 마지막 줄로 값으로 덮어 썼습니다. 문자열 객체를 다른 해시 맵 객체로 값 필드로 바꾸어 다른 값 매핑에 대한 단일 키를 유지하는 데 도움이되었습니다.

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

중복 키가있는 맵을 구현하려는 맥락을 설명해 주시겠습니까? 더 나은 솔루션이있을 수 있다고 확신합니다. 지도는 정당한 이유로 고유 한 키를 유지하기위한 것입니다. 당신이 정말로하고 싶었다면; 충돌 완화 기능이있는 간단한 사용자 정의 맵 클래스를 작성하고 동일한 키로 여러 항목을 유지할 수 있습니다.

참고 : 충돌 키가 고유 한 세트 "항상"로 변환되도록 충돌 완화 함수를 구현해야합니다. 객체 해시 코드 등으로 키를 추가하는 것과 같은 단순한 것?

완전하기 위해 Apache Commons 컬렉션은 또한 멀티 맵. 물론 단점은 Apache Commons가 제네릭을 사용하지 않는다는 것입니다.

비트 핵을 사용하면 중복 키로 해시셋을 사용할 수 있습니다. 경고 : 이것은 큰 해시 세트 구현에 따라 다릅니다.

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 

Java-Map-Duplice-Keys

이러한 멀티 맵 명실은 어떻습니까?

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