/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.collections; import java.util.Map.Entry; import xxl.core.functions.AbstractFunction; import xxl.core.functions.Function; /** * This class provides a straightforward implementation of the * <code>Map.Entry</code> interface from <code>java.util</code>. A MapEntry is * a key-value pair. The <code>Map.entrySet</code> method returns a * collection-view of the map, whose elements are of this class. One way to * obtain a reference to a map entry is from the iterator of this * collection-view. These <code>Map.Entry</code> objects are valid only for the * duration of the iteration; more formally, the behavior of a map entry is * undefined if the backing map has been modified after the entry was returned * by the iterator, except through the iterator's own remove operation, or * through the <code>setValue</code> operation on a map entry returned by the * iterator. * * <p>Usage example (1). * <code><pre> * // create two MapEntry * * MapEntry<Integer, String> entry1 = new MapEntry<Integer, String>(5, "five"), * entry2 = new MapEntry<Integer, String>(2, "two"); * * // check if both entries are equal * * if (entry1.equals(entry2)) * System.out.println("the entries are equal"); * else * System.out.println("the entries are unqual"); * * // change the second entry * * entry2.setKey(5); * * // check if both entries are equal * * if (entry1.equals(entry2)) * System.out.println("the entries are equal"); * else * System.out.println("the entries are unqual"); * * // change the second entry * * entry2.setKey(2); * entry2.setValue("five"); * * // check if both entries are equal * * if (entry1.equals(entry2)) * System.out.println("the entries are equal"); * else * System.out.println("the entries are unqual"); * * // change the second entry * * entry2.setKey(5); * * // check if both entries are equal * * if (entry1.equals(entry2)) * System.out.println("the entries are equal"); * else * System.out.println("the entries are unqual"); * </pre></code></p> * * @param <K> the type of the map entry's key. * @param <V> the type of the map entry's value. * @see java.util.Map.Entry */ public class MapEntry<K, V> implements Entry<K, V> { /** * Factory method. To get an Object of the class MapEntry, use the invoke * method with two arguments: key and value. */ public static Function<Object, MapEntry<Object, Object>> FACTORY_METHOD = new AbstractFunction<Object, MapEntry<Object, Object>>() { @Override public MapEntry<Object, Object> invoke(Object key, Object value) { return new MapEntry<Object, Object>(key, value); } }; /** * Converts the MapEntry to an Object array. */ public static Function<Entry<?, ?>, Object[]> TO_OBJECT_ARRAY_FUNCTION = new AbstractFunction<Entry<?, ?>, Object[]>() { @Override public Object[] invoke(Entry<?, ?> mapEntry) { return new Object[] { mapEntry.getKey(), mapEntry.getValue() }; } }; /** * The key object of this MapEntry. */ protected K key; /** * The value object of this MapEntry. */ protected V value; /** * Returns a new function that returns the key of the entry submitted on * invocation. * * @param <K> the type of the entry's key. * @param <V> the type of the entry's value. * @return a new function that returns the key of the entry submitted on * invocation. */ public static <K, V> Function<Entry<K, V>, K> getKeyFunction() { return new AbstractFunction<Entry<K, V>, K>() { @Override public K invoke(Entry<K, V> entry) { return entry.getKey(); } }; } /** * Returns a new function that returns the value of the entry submitted on * invocation. * * @param <K> the type of the entry's key. * @param <V> the type of the entry's value. * @return a new function that returns the value of the entry submitted on * invocation. */ public static <K, V> Function<Entry<K, V>, V> getValueFunction() { return new AbstractFunction<Entry<K, V>, V>() { @Override public V invoke(Entry<K, V> entry) { return entry.getValue(); } }; } /** * Constructs a new MapEntry with the specified key and value object. * * @param key the key of the new MapEntry. * @param value the value of the new MapEntry. */ public MapEntry(K key, V value) { this.key = key; this.value = value; } /** * Compares the specified object with this entry for equality. Returns * <code>true</code> if the given object is also a map entry and the two * entries represent the same mapping. More formally, two entries * <code>e1</code> and <code>e2</code> represent the same mapping if * <code><pre> * (e1.getKey()==null ? e2.getKey()==null : e1.getKey().equals(e2.getKey())) && * (e1.getValue()==null ? e2.getValue()==null : e1.getValue().equals(e2.getValue())) * </pre></code> * * @param o object to be compared for equality with this map entry. * @return <code>true</code> if the specified object is equal to this map * entry. */ @Override public boolean equals(Object o) { if (!(o instanceof Entry)) return false; Entry<?, ?> mapEntry = (Entry<?, ?>)o; return ( getKey() == null ? mapEntry.getKey() == null : getKey().equals(mapEntry.getKey()) ) && ( getValue() == null ? mapEntry.getValue() == null : getValue().equals(mapEntry.getValue()) ); } /** * Returns the key corresponding to this entry. * * @return the key corresponding to this entry. */ public K getKey() { return key; } /** * Returns the value corresponding to this entry. * * @return the value corresponding to this entry. */ public V getValue() { return value; } /** * Returns the hash code value for this map entry. The hash code of a * map entry <tt>e</tt> is defined to be: * <code><pre> * (e.getKey()==null ? 0 : e.getKey().hashCode()) ^ * (e.getValue()==null ? 0 : e.getValue().hashCode()) * </pre></code> * This ensures that <code>e1.equals(e2)</code> implies that * <code>e1.hashCode()==e2.hashCode()</code> for any two Entries * <code>e1</code> and <code>e2</code>, as required by the general contract * of Object.hashCode. * * @return the hash code value for this map entry. * @see Object#hashCode() * @see Object#equals(Object) * @see #equals(Object) */ @Override public int hashCode() { return (getKey() == null ? 0: getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode()); } /** * Returns the value corresponding to this entry. If the mapping has * been removed from the backing map (by the iterator's remove * operation), the results of this call are undefined. * * @param key the new key of the map entry. * @return the value corresponding to this entry. */ public K setKey(K key) { K oldKey = this.key; this.key = key; return oldKey; } /** * Replaces the value corresponding to this entry with the specified * value. The behavior of this call is undefined if the mapping has * already been removed from the map (by the iterator's remove * operation). * * @param value new value to be stored in this entry. * @return old value corresponding to the entry. * @throws UnsupportedOperationException if the <tt>put</tt> operation * is not supported by the backing map. * @throws ClassCastException if the class of the specified value * prevents it from being stored in the backing map. * @throws IllegalArgumentException if some aspect of this value * prevents it from being stored in the backing map. * @throws NullPointerException the backing map does not permit null * values, and the specified value is null. */ public V setValue(V value) throws ClassCastException, IllegalArgumentException, NullPointerException, UnsupportedOperationException { V oldValue = this.value; this.value = value; return oldValue; } /** * Converts the MapEntry to a String. * @return a String representation of the key value pair. */ @Override public String toString() { return "key: " + key + ", value: " + value; } }