001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.collections4.set; 018 019import java.io.Serializable; 020import java.util.Collection; 021import java.util.Iterator; 022import java.util.Map; 023import java.util.Set; 024 025/** 026 * Decorates a <code>Map</code> to obtain <code>Set</code> behaviour. 027 * <p> 028 * This class is used to create a <code>Set</code> with the same properties as 029 * the key set of any map. Thus, a ReferenceSet can be created by wrapping a 030 * <code>ReferenceMap</code> in an instance of this class. 031 * <p> 032 * Most map implementation can be used to create a set by passing in dummy values. 033 * Exceptions include <code>BidiMap</code> implementations, as they require unique values. 034 * 035 * @param <E> the type of the elements in this set 036 * @param <V> the dummy value type in this map 037 * @since 3.1 038 */ 039public final class MapBackedSet<E, V> implements Set<E>, Serializable { 040 041 /** Serialization version */ 042 private static final long serialVersionUID = 6723912213766056587L; 043 044 /** The map being used as the backing store */ 045 private final Map<E, ? super V> map; 046 047 /** The dummyValue to use */ 048 private final V dummyValue; 049 050 /** 051 * Factory method to create a set from a map. 052 * 053 * @param <E> the element type 054 * @param <V> the dummy value type in the map 055 * @param map the map to decorate, must not be null 056 * @return a new map backed set 057 * @throws NullPointerException if map is null 058 * @since 4.0 059 */ 060 public static <E, V> MapBackedSet<E, V> mapBackedSet(final Map<E, ? super V> map) { 061 return mapBackedSet(map, null); 062 } 063 064 /** 065 * Factory method to create a set from a map. 066 * 067 * @param <E> the element type 068 * @param <V> the dummy value type in the map 069 * @param map the map to decorate, must not be null 070 * @param dummyValue the dummy value to use 071 * @return a new map backed set 072 * @throws NullPointerException if map is null 073 * @since 4.0 074 */ 075 public static <E, V> MapBackedSet<E, V> mapBackedSet(final Map<E, ? super V> map, final V dummyValue) { 076 return new MapBackedSet<>(map, dummyValue); 077 } 078 079 //----------------------------------------------------------------------- 080 /** 081 * Constructor that wraps (not copies). 082 * 083 * @param map the map to decorate, must not be null 084 * @param dummyValue the dummy value to use 085 * @throws NullPointerException if map is null 086 */ 087 private MapBackedSet(final Map<E, ? super V> map, final V dummyValue) { 088 super(); 089 if (map == null) { 090 throw new NullPointerException("The map must not be null"); 091 } 092 this.map = map; 093 this.dummyValue = dummyValue; 094 } 095 096 //----------------------------------------------------------------------- 097 @Override 098 public int size() { 099 return map.size(); 100 } 101 102 @Override 103 public boolean isEmpty() { 104 return map.isEmpty(); 105 } 106 107 @Override 108 public Iterator<E> iterator() { 109 return map.keySet().iterator(); 110 } 111 112 @Override 113 public boolean contains(final Object obj) { 114 return map.containsKey(obj); 115 } 116 117 @Override 118 public boolean containsAll(final Collection<?> coll) { 119 return map.keySet().containsAll(coll); 120 } 121 122 @Override 123 public boolean add(final E obj) { 124 final int size = map.size(); 125 map.put(obj, dummyValue); 126 return map.size() != size; 127 } 128 129 @Override 130 public boolean addAll(final Collection<? extends E> coll) { 131 final int size = map.size(); 132 for (final E e : coll) { 133 map.put(e, dummyValue); 134 } 135 return map.size() != size; 136 } 137 138 @Override 139 public boolean remove(final Object obj) { 140 final int size = map.size(); 141 map.remove(obj); 142 return map.size() != size; 143 } 144 145 @Override 146 public boolean removeAll(final Collection<?> coll) { 147 return map.keySet().removeAll(coll); 148 } 149 150 @Override 151 public boolean retainAll(final Collection<?> coll) { 152 return map.keySet().retainAll(coll); 153 } 154 155 @Override 156 public void clear() { 157 map.clear(); 158 } 159 160 @Override 161 public Object[] toArray() { 162 return map.keySet().toArray(); 163 } 164 165 @Override 166 public <T> T[] toArray(final T[] array) { 167 return map.keySet().toArray(array); 168 } 169 170 @Override 171 public boolean equals(final Object obj) { 172 return map.keySet().equals(obj); 173 } 174 175 @Override 176 public int hashCode() { 177 return map.keySet().hashCode(); 178 } 179 180}