
com.tangosol.util.MapSet Maven / Gradle / Ivy
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.util;
import com.tangosol.io.ExternalizableLite;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.Externalizable;
import java.io.IOException;
import java.io.NotActiveException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* An ExternalizableLite implementation of java.util.Set that uses an
* underlying Map object to store its data in, just as the Java HashSet
* implementation uses an underlying HashMap for its element storage.
*
* @author cp 09/16/05 Originally SafeHashSet (gg)
* @since Coherence 3.2
*/
public class MapSet
extends AbstractSet
implements Cloneable, Externalizable, ExternalizableLite
{
// ----- constructors ---------------------------------------------------
/**
* Default constructor. By default, HashMap is the underlying Map. If that
* is not the desired behavior, then pass an explicit Map to the
* {@link #MapSet(java.util.Map) MapSet(Map)} constructor.
* To change the default Map implementation, sub-class the MapSet
* and override the {@link #instantiateMap() instantiateMap()} method.
*/
public MapSet()
{
m_map = instantiateMap();
}
/**
* Construct a MapSet that uses the given Map for its underlying storage.
*
* @param map the underlying Map object
*/
public MapSet(Map map)
{
Base.azzert(map != null);
m_map = map;
}
// ----- Set interface --------------------------------------------------
/**
* Returns the number of elements in this Set.
*
* @return the number of elements in this Set.
*/
public int size()
{
return m_map.size();
}
/**
* Returns true if this Set contains the specified element.
*
* @return true if this Set contains the specified element
*/
public boolean contains(Object o)
{
return m_map.containsKey(o);
}
/**
* Returns an iterator over the elements in this Set.
* The elements are returned in no particular order.
*
* @return an iterator over the elements in this Set
*/
public Iterator iterator()
{
return m_map.keySet().iterator();
}
/**
* Returns an array containing all of the elements in this Set.
* Obeys the general contract of the {@link java.util.Collection#toArray}
* method.
*
* @return an array containing all of the elements in this Set
*/
public Object[] toArray()
{
return m_map.keySet().toArray();
}
/**
* Returns an array containing all of the elements in this set whose
* runtime type is that of the specified array. Obeys the general
* contract of the {@link java.util.Collection#toArray(Object[])} method.
*
* @param ao the array into which the elements of this Set are to
* be stored, if it is big enough; otherwise, a new array of the
* same runtime type is allocated for this purpose
*
* @return an array containing the elements of this Set
*
* @throws ArrayStoreException the runtime type of a is not a supertype
* of the runtime type of every element in this Set
*/
public Object[] toArray(Object[] ao)
{
return m_map.keySet().toArray(ao);
}
/**
* Ensures that this Set contains the specified element.
* Returns true if the Set changed as a result of the call.
* Returns false if this Set already contains the specified
* element.
*
* @param o element to be added to this Set
*
* @return true if this Set did not already contain the specified
* element
*/
public boolean add(Object o)
{
return m_map.put(o, MapSet.NO_VALUE) == null;
}
/**
* Removes the specified element from this Set if it is present.
* Returns true if the Set contained the specified element
* (or equivalently, if the Set changed as a result of the call).
* The Set will not contain the specified element once the call returns.
*
* @param o object to be removed from this Set, if present
*
* @return true if the Set contained the specified element
*/
public boolean remove(Object o)
{
return m_map.remove(o) != null;
}
/**
* Returns true if this Set contains all of the elements
* in the specified Collection.
*
* @param coll Collection to be checked for containment in this Set
*
* @return true if this Set contains all of the elements
* in the specified Collection
*
* @see #contains(Object)
*/
public boolean containsAll(Collection coll)
{
return m_map.keySet().containsAll(coll);
}
/**
* Adds all of the elements in the specified Collection to this Set if
* they're not already present.
*
* @param coll Collection whose elements are to be added to this Set
*
* @return true if this Set changed as a result of the call
*
* @see #add(Object)
*/
public boolean addAll(Collection coll)
{
Map map = m_map;
boolean fChanged = false;
for (Iterator iter = coll.iterator(); iter.hasNext();)
{
Object o = iter.next();
if (map.put(o, MapSet.NO_VALUE) == null)
{
fChanged = true;
}
}
return fChanged;
}
/**
* Retains only the elements in this Set that are contained in the
* specified Collection.
*
* @param coll Collection that defines which elements this Set will retain
*
* @return true if this Set changed as a result of the call
*/
public boolean retainAll(Collection coll)
{
return m_map.keySet().retainAll(coll);
}
/**
* Removes from this Set all of its elements that are contained in the
* specified Collection.
*
* @param coll Collection that defines which elements will be removed
* from this Set
*
* @return true if this Set changed as a result of the call
*
* @see #remove(Object)
*/
public boolean removeAll(Collection coll)
{
return m_map.keySet().removeAll(coll);
}
/**
* Removes all of the elements from this Set.
*/
public void clear()
{
m_map.clear();
}
// ----- accessors ------------------------------------------------------
/**
* Obtain the underlying Map for purposes of synchronization or read-only
* access; the caller must never directly modify the returned Map.
*
* @return the underlying Map
*/
public Map getMap()
{
return m_map;
}
// ----- Cloneable interface --------------------------------------------
/**
* Create a clone of this MapSet.
*
* @return a clone of this MapSet
*/
public Object clone()
{
// shallow clone
MapSet that;
try
{
that = (MapSet) super.clone();
}
catch (CloneNotSupportedException e)
{
throw Base.ensureRuntimeException(e);
}
// clone the underlying map
Map mapThat = that.instantiateMap();
mapThat.putAll(this.m_map);
that.m_map = mapThat;
return that;
}
// ----- Externalizable interface ---------------------------------------
/**
* Initialize this object from the contents of the passed object stream.
*
* @param in the stream to read data from in order to restore the object
*
* @exception IOException if an I/O exception occurs
*/
public void readExternal(ObjectInput in)
throws IOException, ClassNotFoundException
{
Map map = m_map;
if (!map.isEmpty())
{
throw new NotActiveException();
}
int c = in.readInt();
for (int i = 0; i < c; ++i)
{
map.put(in.readObject(), NO_VALUE);
}
}
/**
* Write the contents of this object into the passed object stream.
*
* @param out the stream to write the object to
*
* @exception IOException if an I/O exception occurs
*/
public void writeExternal(ObjectOutput out)
throws IOException
{
Map map = m_map;
int c = map.size();
out.writeInt(c);
for (Iterator iter = map.keySet().iterator(); iter.hasNext(); )
{
out.writeObject(iter.next());
--c;
}
if (c != 0)
{
throw new IOException("wrote " + Math.abs(c) + " too " +
(c > 0 ? "few" : "many") + " elements");
}
}
// ----- ExternalizableLite interface -----------------------------------
/**
* {@inheritDoc}
*/
public void readExternal(DataInput in)
throws IOException
{
Map map = m_map;
if (!map.isEmpty())
{
throw new NotActiveException();
}
final Object NO_VALUE = MapSet.NO_VALUE;
boolean fLite = in.readBoolean();
if (fLite)
{
int c = ExternalizableHelper.readInt(in);
for (int i = 0; i < c; ++i)
{
map.put(ExternalizableHelper.readObject(in), NO_VALUE);
}
}
else
{
Object[] ao = (Object[]) ExternalizableHelper.readObject(in);
for (int i = 0, c = ao.length; i < c; ++i)
{
map.put(ao[i], NO_VALUE);
}
}
}
/**
* {@inheritDoc}
*/
public void writeExternal(DataOutput out)
throws IOException
{
// scan through the contents searching for anything that cannot be
// streamed to a DataOutput (i.e. anything that requires Java Object
// serialization); note that the toArray() also resolves concerns
// related to the synchronization of the data structure itself during
// serialization
boolean fLite = true;
Object[] ao = m_map.keySet().toArray();
int c = ao.length;
final int FMT_OBJ_SER = ExternalizableHelper.FMT_OBJ_SER;
for (int i = 0; i < c; ++i)
{
if (ExternalizableHelper.getStreamFormat(ao[i]) == FMT_OBJ_SER)
{
fLite = false;
break;
}
}
out.writeBoolean(fLite);
if (fLite)
{
ExternalizableHelper.writeInt(out, c);
for (int i = 0; i < c; ++i)
{
ExternalizableHelper.writeObject(out, ao[i]);
}
}
else
{
ExternalizableHelper.writeObject(out, ao);
}
}
// ----- internal -------------------------------------------------------
/**
* Factory pattern: Provide an underlying Map for this Set implementation
* to store its contents in.
*
* @return a new Map instance
*/
protected Map instantiateMap()
{
Map map = m_map;
if (map == null)
{
// default Map implementation
return new HashMap();
}
try
{
return (Map) m_map.getClass().newInstance();
}
catch (Exception e)
{
throw Base.ensureRuntimeException(e);
}
}
// ----- constants ------------------------------------------------------
/**
* A no-value object.
*/
protected static final Object NO_VALUE = new byte[0];
// ----- data members ---------------------------------------------------
/**
* The underlying Map.
*/
protected transient Map m_map;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy