View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections.set;
18  
19  import java.io.Serializable;
20  import java.util.Collection;
21  import java.util.Iterator;
22  import java.util.Map;
23  import java.util.Set;
24  
25  /**
26   * Decorates a <code>Map</code> to obtain <code>Set</code> behaviour.
27   * <p>
28   * This class is used to create a <code>Set</code> with the same properties as
29   * the key set of any map. Thus, a ReferenceSet can be created by wrapping a
30   * <code>ReferenceMap</code> in an instance of this class.
31   * <p>
32   * Most map implementation can be used to create a set by passing in dummy values.
33   * Exceptions include <code>BidiMap</code> implementations, as they require unique values.
34   *
35   * @since 3.1
36   * @version $Id: MapBackedSet.java 1429905 2013-01-07 17:15:14Z ggregory $
37   */
38  public final class MapBackedSet<E, V> implements Set<E>, Serializable {
39  
40      /** Serialization version */
41      private static final long serialVersionUID = 6723912213766056587L;
42  
43      /** The map being used as the backing store */
44      protected final Map<E, ? super V> map;
45  
46      /** The dummyValue to use */
47      protected final V dummyValue;
48  
49      /**
50       * Factory method to create a set from a map.
51       * 
52       * @param <E> the element type
53       * @param <V> the dummy value type in the map
54       * @param map  the map to decorate, must not be null
55       * @return a new map backed set
56       * @throws IllegalArgumentException if set is null
57       */
58      public static <E, V> MapBackedSet<E, V> mapBackedSet(final Map<E, ? super V> map) {
59          return mapBackedSet(map, null);
60      }
61  
62      /**
63       * Factory method to create a set from a map.
64       * 
65       * @param <E> the element type
66       * @param <V> the dummy value type in the map
67       * @param map  the map to decorate, must not be null
68       * @param dummyValue  the dummy value to use
69       * @return a new map backed set
70       * @throws IllegalArgumentException if map is null
71       */
72      public static <E, V> MapBackedSet<E, V> mapBackedSet(final Map<E, ? super V> map, final V dummyValue) {
73          if (map == null) {
74              throw new IllegalArgumentException("The map must not be null");
75          }
76          return new MapBackedSet<E, V>(map, dummyValue);
77      }
78  
79      //-----------------------------------------------------------------------
80      /**
81       * Constructor that wraps (not copies).
82       * 
83       * @param map  the map to decorate, must not be null
84       * @param dummyValue  the dummy value to use
85       * @throws IllegalArgumentException if map is null
86       */
87      private MapBackedSet(final Map<E, ? super V> map, final V dummyValue) {
88          super();
89          this.map = map;
90          this.dummyValue = dummyValue;
91      }
92  
93      //-----------------------------------------------------------------------
94      public int size() {
95          return map.size();
96      }
97  
98      public boolean isEmpty() {
99          return map.isEmpty();
100     }
101 
102     public Iterator<E> iterator() {
103         return map.keySet().iterator();
104     }
105 
106     public boolean contains(final Object obj) {
107         return map.containsKey(obj);
108     }
109 
110     public boolean containsAll(final Collection<?> coll) {
111         return map.keySet().containsAll(coll);
112     }
113 
114     public boolean add(final E obj) {
115         final int size = map.size();
116         map.put(obj, dummyValue);
117         return map.size() != size;
118     }
119 
120     public boolean addAll(final Collection<? extends E> coll) {
121         final int size = map.size();
122         for (final E e : coll) {
123             map.put(e, dummyValue);
124         }
125         return map.size() != size;
126     }
127 
128     public boolean remove(final Object obj) {
129         final int size = map.size();
130         map.remove(obj);
131         return map.size() != size;
132     }
133 
134     public boolean removeAll(final Collection<?> coll) {
135         return map.keySet().removeAll(coll);
136     }
137 
138     public boolean retainAll(final Collection<?> coll) {
139         return map.keySet().retainAll(coll);
140     }
141 
142     public void clear() {
143         map.clear();
144     }
145 
146     public Object[] toArray() {
147         return map.keySet().toArray();
148     }
149 
150     public <T> T[] toArray(final T[] array) {
151         return map.keySet().toArray(array);
152     }
153 
154     @Override
155     public boolean equals(final Object obj) {
156         return map.keySet().equals(obj);
157     }
158 
159     @Override
160     public int hashCode() {
161         return map.keySet().hashCode();
162     }
163 
164 }