2 way associative datatype?

Discussion in 'Plugin Development' started by MDCreator, Dec 17, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    MDCreator

    I'm used to using HashMaps as a datatype with a key and a value, but is there any kind of datatype that has 2 key/values that when "getted" return the other one?
     
  2. Offline

    wwsean08

    no, however you could use custom classes for the key and value which would allow you to have the data holder hold multiple values
     
  3. Offline

    halley

    Code:
    package cc.halley.java.util;
    
    
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    
    public class ReciprocalMap<K>
        implements Map<K,K>
    {
        private Map<K,K> forward = null;
        private Map<K,K> backward = null;
    
        public ReciprocalMap() { this(10, 0.75f); }
        public ReciprocalMap(int initialCapacity) { this(initialCapacity, 0.75f); }
        public ReciprocalMap(int initialCapacity, float loadFactor)
        {
            forward = new HashMap<K,K>(initialCapacity, loadFactor);
            backward = new HashMap<K,K>(initialCapacity, loadFactor);
        }
        public int size() { return Math.max(forward.size(), backward.size()); }
        public void clear() { forward.clear(); backward.clear(); }
        public Collection<K> values() { return keySet(); }
    
        public boolean containsKey(Object key)
            { return forward.containsKey(key) || backward.containsKey(key); }
    
        public boolean containsValue(Object value)
            { return forward.containsKey(value) || backward.containsKey(value); }
    
        public Set<java.util.Map.Entry<K,K>> entrySet()
            { throw new IllegalArgumentException("entrySet() not implemented"); }
    
        public K get(Object key)
        {
            if (forward.containsKey(key)) return forward.get(key);
            if (backward.containsKey(key)) return backward.get(key);
            return null;
        }
    
        public boolean isEmpty() { return forward.isEmpty(); }
    
        public Set<K> keySet()
        {
            Set<K> set = new HashSet<K>(size());
            set.addAll(forward.keySet());
            set.addAll(backward.keySet());
            return set;
        }
    
        public K put(K key, K value)
        {
            backward.put(value, key);
            return forward.put(key, value);
        }
    
        public void putAll(Map<? extends K,? extends K> source)
        {
            for (K key : source.keySet())
                put(key, source.get(key));
        }
    
        public K remove(Object key)
        {
            if (forward.containsKey(key)) forward.remove(key);
            if (backward.containsKey(key)) backward.remove(key);
            return null;
        }
    }
    
    I have not tested it. Give it a shot.
     
  4. Offline

    nickrak

    Here's a thread-safe implementation using only one Map internally

    Code:java
    1. import java.util.Collection;
    2. import java.util.Map;
    3. import java.util.Set;
    4. import java.util.concurrent.ConcurrentHashMap;
    5.  
    6. public class BidirectionHashMap<T> implements Map<T, T>
    7. {
    8. private final ConcurrentHashMap<T, T> internal;
    9.  
    10. public BidirectionHashMap()
    11. {
    12. this(16);
    13. }
    14.  
    15. public BidirectionHashMap(final int initialCapacity)
    16. {
    17. this.internal = new ConcurrentHashMap<T, T>(initialCapacity);
    18. }
    19.  
    20. @Override
    21. public void clear()
    22. {
    23. this.internal.clear();
    24. }
    25.  
    26. @Override
    27. public boolean containsKey(Object key)
    28. {
    29. return this.internal.containsKey(key);
    30. }
    31.  
    32. @Override
    33. public boolean containsValue(Object value)
    34. {
    35. return this.containsKey(value);
    36. }
    37.  
    38. @Override
    39. public Set<java.util.Map.Entry<T, T>> entrySet()
    40. {
    41. return this.internal.entrySet();
    42. }
    43.  
    44. @Override
    45. public T get(Object key)
    46. {
    47. return this.internal.get(key);
    48. }
    49.  
    50. @Override
    51. public boolean isEmpty()
    52. {
    53. return this.internal.isEmpty();
    54. }
    55.  
    56. @Override
    57. public Set<T> keySet()
    58. {
    59. return this.internal.keySet();
    60. }
    61.  
    62. @Override
    63. public T put(T key, T value)
    64. {
    65. this.internal.put(value, key);
    66. return this.internal.put(key, value);
    67. }
    68.  
    69. @Override
    70. public void putAll(Map<? extends T, ? extends T> m)
    71. {
    72. for (final T key : m.keySet())
    73. {
    74. this.put(key, m.get(key));
    75. }
    76. }
    77.  
    78. @Override
    79. public T remove(Object key)
    80. {
    81. final T value = this.internal.remove(key);
    82. this.internal.remove(value);
    83.  
    84. return value;
    85. }
    86.  
    87. @Override
    88. public int size()
    89. {
    90. return this.internal.size() / 2;
    91. }
    92.  
    93. @Override
    94. public Collection<T> values()
    95. {
    96. return this.internal.values();
    97. }
    98. }
     
  5. Offline

    halley

    Nice, nickrak. Won't it throw an exception on the second remove if you do bidi.add(X, X) and then bidi.remove(X)?
     
  6. Offline

    nickrak

    Code:
    bidi.put(x,y) will add x=>y AND y=>x
    bidi.remove(x) will return y.
    bidi.remove(y) will return null. (should not throw an exception)
    Code:
    bidi.put(x,y) will add x=>y AND y=>x
    bidi.remove(y) will return x.
    bidi.remove(x) will return null. (should not throw an exception)
    Code:
    bidi.put(x, x) will add x=>x, AND x=>x (which is only one record total)
    bidi.remove(x) will return x.
    Remove should always return the other side of the matched pair, or null if there is no matched item. http://docs.oracle.com/javase/6/doc...ncurrentHashMap.html#remove(java.lang.Object)
     
  7. Offline

    halley

    For whatever brain-fart I had, I forgot that maps are sloppy unlike other collections. You can remove keys that aren't there without an exception.
     
Thread Status:
Not open for further replies.

Share This Page