BinaryMap class implements a map from objects to integer objects where the only value is the integer with value 1. : Map « Collections Data Structure « Java






BinaryMap class implements a map from objects to integer objects where the only value is the integer with value 1.

      
/*
 * LingPipe v. 3.9
 * Copyright (C) 2003-2010 Alias-i
 *
 * This program is licensed under the Alias-i Royalty Free License
 * Version 1 WITHOUT ANY WARRANTY, without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the Alias-i
 * Royalty Free License Version 1 for more details.
 *
 * You should have received a copy of the Alias-i Royalty Free License
 * Version 1 along with this program; if not, visit
 * http://alias-i.com/lingpipe/licenses/lingpipe-license-1.txt or contact
 * Alias-i, Inc. at 181 North 11th Street, Suite 401, Brooklyn, NY 11211,
 * +1 (718) 290-9170.
ectends */

//package com.aliasi.util;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;

import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

/**
 * The <code>BinaryMap</code> class implements a map from objects to
 * integer objects where the only value is the integer with value 1.
 * Instances of this class are typically returned by boolean feature
 * extractors, who return a map with only 1 values, because the 0
 * values are implicit.
 *
 * <p>Binary maps are based on a set of keys that map to 1.  Thus
 * they are more space efficient than Java's utility maps such
 * as tree maps or hash maps.  The underlying set implementation is
 * pluggable, but must be mutable if the resulting binary map
 * is to be mutable.
 *
 * <p>Modifiability through the entry set, key set, and values
 * collection is fully supported through their respective iterators
 * and through the collections themselves.  The map entries making
 * up the entry set may not have their values modified.
 *
 * <h3>Equality and Hash Codes</h3>
 *
 * Binary maps satisfy the requirements laid out for hash codes
 * and object equality specified in {@link Map}.
 * 
 * <h3>Thread Safety</h3>
 *
 * Binary maps have the same thread safety as their underlying
 * sets.  
 *
 * <h3>Serialization</h3>
 *
 * A binary map may be serialized if its underlying positive
 * set is serializable.
 *
 * @author  Bob Carpenter
 * @version 3.9.1
 * @since   LingPipe3.9.1
 * @param <E> the type of keys in the map
 */
public class BinaryMap<E> 
    extends AbstractMap<E,Integer> 
    implements Serializable {

    static final long serialVersionUID = -6965494782866980478L;

    private final Set<E> mPositiveSet;


    /**
     * Construct a binary map based on the specified set of positive
     * values.  The set is stored as is rather than copied.  The
     * set must be mutable if the constructed map is to be mutable.
     *
     * @param positiveSet
     */
    public BinaryMap(Set<E> positiveSet) {
        mPositiveSet = positiveSet;
    }

    /**
     * Adds the specified element to the map with value 1.
     *
     * <p>Note that this method is not part of the {@link Map}
     * interface.
     *
     * @param e Element added to the map with value 1.
     * @return {@code true} if the map didn't already contain the
     * element.
     * @throws UnsupportedOperationException If the underlying set of
     * positive elements does not support {@code Collection.add}.
     */
    public boolean add(E e) {
        return mPositiveSet.add(e);
    }

    /**
     * Returns the set of keys mapping to 1.  This set is backed by
     * this map, so changes to the set are reflected in the map and
     * vice-versa.  
     *
     * <p>If the underlying set is not modifiable, attempts to
     * modify the key set will raise unsupported operation exceptions.
     *
     * <p>Note that results are undefined in the middle of an
     * iterator, which will likely throw concurrent modification, null
     * pointer, or array index out of bounds exceptions.  Therefore,
     * access to the key set must be synchronized in the same way
     * access to the underlying set.
     *
     * <p>Further note that unlike the specification in {@link Map},
     * the returned keyset supports the {@link Collection#add(Object)} and
     * {@link Collection#addAll(Collection)}.  Adding elements to the key set
     * is the same as adding them through the {@link #add(Object)}
     * method of this class.
     *
     * @return The set of keys mapping to one.
     */
    public Set<E> keySet() {
        return mPositiveSet;
    }

    /**
     * Return a set view of the mappings in this map.  This set is
     * backed by this map, so changes to the return set affect
     * this set and vice-versa.  The resulting set supports deletions
     * through {@code Iterator.remove}, {@code Collection.remove},
     * {@code Collection.removeAll}, {@code Collection.retainAll},
     * and {@code Collection.clear} operations, but does not support
     * the add operations.
     *
     * <p>If the underlying set of positive elements does not
     * support these modification operations, they will throw an
     * unsupported operation exception.
     *
     * <p><i>Implementation Note:</i> The {@code Map.Entry} elements
     * are created as necessary by the entry set using a relatively
     * efficient implementation of entries that only stores the key.
     * Accessing the key set is more efficient.
     *
     * @return The set of mappings for this map. 
     */
    @Override
    public Set<Map.Entry<E,Integer>> entrySet() {
        return new EntrySet();
    }

    /**
     * Returns the {@code Integer} with value 1 if the specified
     * argument is mapped to 1 by this map, and returns null
     * otherwise.
     *
     * <p>The constant {@link #ONE} is used for the return
     * value.
     *
     * @param key The element whose value is returned.
     * @return 1 if the element is mapped to 1, and {@code null}
     * otherwise.
     */
    @Override
    public Integer get(Object key) {
        return mPositiveSet.contains(key)
            ? ONE
            : null;
    }

    /**
     * Remove the mapping with the specified key if it is present, returning
     * the previous value, or {@code null} if it was previously undefined.
     *
     * @param key Key of mapping to remove.
     * @return The value 1 if the key is already present, and {@code
     * null} otherwise.
     * @throws UnsupportedOperationException If the underlying set for
     * this map does not support the {@link Set#remove(Object)} operation.
     */
    @Override
    public Integer remove(Object key) {
        return mPositiveSet.remove(key)
            ? ONE
            : null;
    }

    /**
     * Returns the size of this mapping.
     *
     * @return Size of this mapping.
     */
    @Override
    public int size() {
        return mPositiveSet.size();
    }

    /**
     * Returns an immutable collection view of the values for this
     * map.  The resulting collecton will be empty if the map is
     * entry, or contain the single value {@link #ONE} if the map is
     * not empty.
     */
    @Override
    public Collection<Integer> values() {
        return new Values();
    }

    /**
     * Removes all of the mappings from this map.
     *
     * <p>The implementation just delegates the clear operation to the
     * contained set.
     *
     * @throws UnsupportedOperationException If the clear operation
     * is not supported by the contained set.
     */
    @Override
    public void clear() {
        mPositiveSet.clear();
    }

    /**
     * Returns {@code true} if this mapping contains a mapping
     * for the specified object.
     *
     * <p>This method delegates to the underlying positive set's
     * {@code Collection.contains} method.
     *
     * @param o Object to teset.
     * @return {@code true} if it is mapped by this mapping.
     * @throws ClassCastException If the underlying set throws
     * a class cast when checking the specified object for
     * membership.
     */
    @Override
    public boolean containsKey(Object o) {
        return mPositiveSet.contains(o);
    }

    /**
     * Returns {@code true} if this map contains a mapping
     * from some key to the specified value.  
     *
     * <p>Note that the only object for which this map may
     * return true is the {@code Integer} with value 1.
     *
     * @param o Object to test.
     * @return {@code true} if this map contains a mapping
     * from some object to this value.
     */
    @Override
    public boolean containsValue(Object o) {
        return ONE.equals(o) && !isEmpty();
    }

    /**
     * Returns {@code true} if this mapping is empty.
     *
     * @return {@code true} if this mapping is empty.
     */
    @Override
    public boolean isEmpty() {
        return mPositiveSet.isEmpty();
    }

    /**
     * Adds the mapping of the specified object to the specified
     * value if the specified number is the {@code Integer} with
     * value 1.
     *
     * @param e Key for the mapping.
     * @param n Value for the mapping.
     * @throws IllegalArgumentException If the specified integer
     * does not have value 1.
     */
    @Override
    public Integer put(E e, Integer n) {
        if (!ONE.equals(n))
            throw new IllegalArgumentException();
        return  mPositiveSet.add(e) ? null : ONE;
    }


    class Values extends AbstractCollection<Integer> {
        @Override
        public Iterator<Integer> iterator() {
            return new ValuesIterator();
        }
        @Override
        public int size() {
            return isEmpty() ? 0 : 1;
        }
        @Override
        public void clear() {
            mPositiveSet.clear();
        }
        @Override
        public boolean contains(Object o) {
            return ONE.equals(o) && !isEmpty();
        }
        @Override
        public boolean isEmpty() {
            return mPositiveSet.isEmpty();
        }
        @Override
        public boolean remove(Object o) {
            if (!ONE.equals(o))
                return false;
            boolean removedSomething = !isEmpty();
            mPositiveSet.clear();
            return removedSomething;
        }
        @Override
        public boolean removeAll(Collection<?> c) {
            if (!c.contains(ONE))
                return false;
            boolean removedSomething = !isEmpty();
            mPositiveSet.clear();
            return removedSomething;
        }
        @Override
        public boolean retainAll(Collection<?> c) {
            if (isEmpty()) return false;
            if (c.contains(ONE)) return false;
            mPositiveSet.clear();
            return true;
        }
        @Override
        public Object[] toArray() {
            return isEmpty() 
                ? EMPTY_OBJECT_ARRAY 
                : new Object[] { ONE };
        }
    }

    class ValuesIterator implements Iterator<Integer> {
        boolean finished = mPositiveSet.isEmpty();
        boolean mayRemove = false;
        public boolean hasNext() {
            return !finished;
        }
        public Integer next() {
            if (!hasNext())
                throw new NoSuchElementException();
            finished = true;
            mayRemove = true;
            return ONE;
        }
        public void remove() {
            if (!mayRemove)
                throw new IllegalStateException();
            mayRemove = false;
            mPositiveSet.clear();
        }
    }


    class EntrySet extends AbstractSet<Map.Entry<E,Integer>> {
        @Override
        public int size() {
            return mPositiveSet.size();
        }
        @Override
        public Iterator<Map.Entry<E,Integer>> iterator() {
            return new EntrySetIterator();
        }
        @Override
        public void clear() {
            mPositiveSet.clear();
        }
        @Override
        public boolean contains(Object o) {
            if (!(o instanceof Map.Entry<?,?>))
                return false;
            @SuppressWarnings("unchecked") // checked above
            Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
            return ONE.equals(entry.getValue())
                && mPositiveSet.contains(entry.getKey());
        }
        @Override
        public boolean isEmpty() {
            return mPositiveSet.isEmpty();
        }
        @Override
        public boolean remove(Object o) {
            if (!(o instanceof Map.Entry<?,?>))
                return false;
            @SuppressWarnings("unchecked") // checked above
            Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
            return ONE.equals(entry.getValue())
                && mPositiveSet.remove(entry.getKey());
        }
    }

    class EntrySetIterator implements Iterator<Map.Entry<E,Integer>> {
        private final Iterator<E> mIterator = mPositiveSet.iterator();;
        public boolean hasNext() {
            return mIterator.hasNext();
        }
        public Map.Entry<E,Integer> next() {
            return new PositiveMapEntry();
        }
        public void remove() {
            mIterator.remove();
        }

        class PositiveMapEntry implements Map.Entry<E,Integer> {
            private final E mE = mIterator.next();
            public E getKey() {
                return mE;
            }
            public Integer getValue() {
                return ONE;
            }
            public Integer setValue(Integer value) {
                throw new UnsupportedOperationException();
            }
            public boolean equals(Object that) {
                if (!(that instanceof Map.Entry<?,?>))
                    return false;
                @SuppressWarnings("unchecked") // checked above
                    Map.Entry<?,?> e1 = (Map.Entry<?,?>) that;
                Map.Entry<?,?> e2 = this;
                return
                    (e1.getKey()==null
                     ? e2.getKey()==null
                     : e1.getKey().equals(e2.getKey()))
                    &&
                    (e1.getValue()==null
                     ? e2.getValue()==null
                     : e1.getValue().equals(e2.getValue()));
            }
            public int hashCode() {
                return (getKey()==null ? 0 : getKey().hashCode())
                    ^ (getValue()==null ? 0 : getValue().hashCode());
            }
        }
    }

    /**
     * The constant used for the {@code Integer} with value 1.  The
     * value is defined by {@code Integer.valueOf(1)}, so may be the
     * same object as returned by other calls to {@code valueOf()}.
     */
    public static final Integer ONE = Integer.valueOf(1);

    static final Object[] EMPTY_OBJECT_ARRAY
        = new Object[0];

 
}

   
    
    
    
    
    
  








Related examples in the same category

1.Creating and storing arrays in a map
2.Sort based on the values
3.Get a key from value with an HashMap
4.Retrieve environment variables (JDK1.5)
5.Creating a Type-Specific Map: creates a map whose keys are Integer objects and values are String objects.
6.A map declared to hold objects of a type T can also hold objects that extend from T
7.A value retrieved from a type-specific collection does not need to be casted
8.Map techniques.
9.Create an array containing the keys in a map
10.Create an array containing the values in a map
11.Creating a Hash Table
12.Creating a Map That Retains Order-of-Insertion
13.Automatically Removing an Unreferenced Element from a Hash Table
14.Creating a Type-Specific Map [5.0]
15.Use Iterator to loop through the HashMap class
16.Create type specific collections
17.Convert Properties into Map
18.A java.util.Map implementation using reference values
19.Utility method that return a String representation of a map. The elements will be represented as "key = value"
20.Utility method that return a String representation of a map. The elements will be represented as "key = value" (tab)
21.This program demonstrates the use of a map with key type String and value type Employee
22.Format a Map
23.A Map implementation that dumps its content when memory runs low.
24.A Map that stores the values in files within a directory.
25.Map List
26.Multi Value Map Array List
27.Multi Value Map Linked HashSet
28.An object that maps keys to values, and values back to keys.
29.LRU Map
30.A map acts like array.
31.Order Retaining Map
32.A space-optimized map for associating char keys with values.
33.A Map implementation that grows to a fixed size and then retains only a fixed number of the highest (largest) keys.
34.Class which creates mapping between keys and a list of values.
35.A map of values by class.
36.History Map
37.Sorts map by values in ascending order.
38.Map from a given key to a list of values
39.Map from a given key to a set of values
40.Class which keeps a set of values and assigns each value a unique positive index.
41.Array Map
42.Array map
43.An ArrayMap is a very inefficient map type that is more robust in dealing with changes to its keys than other maps.
44.This Map stores it's keys as strings in upper case, null and duplicate keys are not allowed
45.Map to string
46.A simple class that stores key Strings as char[]'s in a hash table.