You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mahout.apache.org by bi...@apache.org on 2010/01/14 01:12:34 UTC

svn commit: r899006 - in /lucene/mahout/trunk: math/ math/src/main/java-templates/org/apache/mahout/math/function/ math/src/main/java-templates/org/apache/mahout/math/map/ math/src/main/java/org/apache/mahout/math/function/ math/src/main/java/org/apach...

Author: bimargulies
Date: Thu Jan 14 00:12:34 2010
New Revision: 899006

URL: http://svn.apache.org/viewvc?rev=899006&view=rev
Log:
MAHOUT-243: primitive-to-object maps

Added:
    lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/function/KeyTypeObjectProcedure.java.t
    lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/AbstractKeyTypeObjectMap.java.t
    lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/OpenKeyTypeObjectHashMap.java.t
    lucene/mahout/trunk/math/src/test/java-templates/org/apache/mahout/math/map/OpenKeyTypeObjectHashMapTest.java.t
Removed:
    lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/function/IntObjectProcedure.java
    lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/function/LongObjectProcedure.java
    lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/map/AbstractIntObjectMap.java
    lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/map/AbstractLongObjectMap.java
    lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/map/OpenIntObjectHashMap.java
    lucene/mahout/trunk/math/src/main/java/org/apache/mahout/math/map/OpenLongObjectHashMap.java
    lucene/mahout/trunk/math/src/test/java/org/apache/mahout/math/map/OpenIntIntHashMapTest.java
Modified:
    lucene/mahout/trunk/math/pom.xml
    lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/AbstractKeyTypeValueTypeMap.java.t
    lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/OpenKeyTypeValueTypeHashMap.java.t
    lucene/mahout/trunk/math/src/test/java-templates/org/apache/mahout/math/map/OpenKeyTypeValueTypeHashMapTest.java.t
    lucene/mahout/trunk/utils/pom.xml

Modified: lucene/mahout/trunk/math/pom.xml
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/pom.xml?rev=899006&r1=899005&r2=899006&view=diff
==============================================================================
--- lucene/mahout/trunk/math/pom.xml (original)
+++ lucene/mahout/trunk/math/pom.xml Thu Jan 14 00:12:34 2010
@@ -136,7 +136,6 @@
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>${junit.version}</version>
       <scope>test</scope>
     </dependency>
   </dependencies>

Added: lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/function/KeyTypeObjectProcedure.java.t
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/function/KeyTypeObjectProcedure.java.t?rev=899006&view=auto
==============================================================================
--- lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/function/KeyTypeObjectProcedure.java.t (added)
+++ lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/function/KeyTypeObjectProcedure.java.t Thu Jan 14 00:12:34 2010
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.mahout.math.function;
+
+/*
+Copyright 1999 CERN - European Organization for Nuclear Research.
+Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose 
+is hereby granted without fee, provided that the above copyright notice appear in all copies and 
+that both that copyright notice and this permission notice appear in supporting documentation. 
+CERN makes no representations about the suitability of this software for any purpose. 
+It is provided "as is" without expressed or implied warranty.
+*/
+
+/**
+ * Interface that represents a procedure object: a procedure that takes two arguments and does not return a value.
+ *
+*/
+public interface ${keyTypeCap}ObjectProcedure<T> {
+
+  /**
+   * Applies a procedure to two arguments. Optionally can return a boolean flag to inform the object calling the
+   * procedure.
+   *
+   * <p>Example: forEach() methods often use procedure objects. To signal to a forEach() method whether iteration should
+   * continue normally or terminate (because for example a matching element has been found), a procedure can return
+   * <tt>false</tt> to indicate termination and <tt>true</tt> to indicate continuation.
+   *
+   * @param first  first argument passed to the procedure.
+   * @param second second argument passed to the procedure.
+   * @return a flag  to inform the object calling the procedure.
+   */
+  boolean apply(${keyType} first, T second);
+}

Added: lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/AbstractKeyTypeObjectMap.java.t
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/AbstractKeyTypeObjectMap.java.t?rev=899006&view=auto
==============================================================================
--- lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/AbstractKeyTypeObjectMap.java.t (added)
+++ lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/AbstractKeyTypeObjectMap.java.t Thu Jan 14 00:12:34 2010
@@ -0,0 +1,444 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+Copyright � 1999 CERN - European Organization for Nuclear Research.
+Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose 
+is hereby granted without fee, provided that the above copyright notice appear in all copies and 
+that both that copyright notice and this permission notice appear in supporting documentation. 
+CERN makes no representations about the suitability of this software for any purpose. 
+It is provided "as is" without expressed or implied warranty.
+*/
+package org.apache.mahout.math.map;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.mahout.math.Sorting;
+import org.apache.mahout.math.Swapper;
+import org.apache.mahout.math.function.IntComparator;
+
+import org.apache.mahout.math.function.${keyTypeCap}ObjectProcedure;
+import org.apache.mahout.math.function.${keyTypeCap}Procedure;
+import org.apache.mahout.math.list.${keyTypeCap}ArrayList;
+
+public abstract class Abstract${keyTypeCap}ObjectMap<T> extends AbstractMap {
+
+  /**
+   * Returns <tt>true</tt> if the receiver contains the specified key.
+   *
+   * @return <tt>true</tt> if the receiver contains the specified key.
+   */
+  public boolean containsKey(final ${keyType} key) {
+    return !forEachKey(
+        new ${keyTypeCap}Procedure() {
+          @Override
+          public boolean apply(${keyType} iterKey) {
+            return (key != iterKey);
+          }
+        }
+    );
+  }
+
+  /**
+   * Returns <tt>true</tt> if the receiver contains the specified value. Tests for identity.
+   *
+   * @return <tt>true</tt> if the receiver contains the specified value.
+   */
+  public boolean containsValue(final T value) {
+    return !forEachPair(
+        new ${keyTypeCap}ObjectProcedure<T>() {
+          @Override
+          public boolean apply(${keyType} iterKey, Object iterValue) {
+            return (value != iterValue);
+          }
+        }
+    );
+  }
+
+  /**
+   * Returns a deep copy of the receiver; uses <code>clone()</code> and casts the result.
+   *
+   * @return a deep copy of the receiver.
+   */
+  @SuppressWarnings("unchecked") // seemingly unavoidable.
+  public Abstract${keyTypeCap}ObjectMap<T> copy() {
+    return this.getClass().cast(clone());
+  }
+
+  /**
+   * Compares the specified object with this map for equality.  Returns <tt>true</tt> if the given object is also a map
+   * and the two maps represent the same mappings.  More formally, two maps <tt>m1</tt> and <tt>m2</tt> represent the
+   * same mappings iff
+   * <pre>
+   * m1.forEachPair(
+   *    new ${keyTypeCap}ObjectProcedure() {
+   *      public boolean apply(${keyType} key, Object value) {
+   *        return m2.containsKey(key) && m2.get(key) == value;
+   *      }
+   *    }
+   *  )
+   * &&
+   * m2.forEachPair(
+   *    new ${keyTypeCap}ObjectProcedure() {
+   *      public boolean apply(${keyType} key, Object value) {
+   *        return m1.containsKey(key) && m1.get(key) == value;
+   *      }
+   *    }
+   *  );
+   * </pre>
+   *
+   * This implementation first checks if the specified object is this map; if so it returns <tt>true</tt>.  Then, it
+   * checks if the specified object is a map whose size is identical to the size of this set; if not, it it returns
+   * <tt>false</tt>.  If so, it applies the iteration as described above.
+   *
+   * @param obj object to be compared for equality with this map.
+   * @return <tt>true</tt> if the specified object is equal to this map.
+   */
+  @SuppressWarnings("unchecked") // incompressible
+  public boolean equals(Object obj) {
+    if (obj == this) {
+      return true;
+    }
+
+    if (!(obj instanceof Abstract${keyTypeCap}ObjectMap)) {
+      return false;
+    }
+    final Abstract${keyTypeCap}ObjectMap other = (Abstract${keyTypeCap}ObjectMap) obj;
+    if (other.size() != size()) {
+      return false;
+    }
+
+    return
+        forEachPair(
+            new ${keyTypeCap}ObjectProcedure() {
+              @Override
+              public boolean apply(${keyType} key, Object value) {
+                return other.containsKey(key) && other.get(key) == value;
+              }
+            }
+        )
+            &&
+            other.forEachPair(
+                new ${keyTypeCap}ObjectProcedure() {
+                  @Override
+                  public boolean apply(${keyType} key, Object value) {
+                    return containsKey(key) && get(key) == value;
+                  }
+                }
+            );
+  }
+
+  /**
+   * Applies a procedure to each key of the receiver, if any. Note: Iterates over the keys in no particular order.
+   * Subclasses can define a particular order, for example, "sorted by key". All methods which <i>can</i> be expressed
+   * in terms of this method (most methods can) <i>must guarantee</i> to use the <i>same</i> order defined by this
+   * method, even if it is no particular order. This is necessary so that, for example, methods <tt>keys</tt> and
+   * <tt>values</tt> will yield association pairs, not two uncorrelated lists.
+   *
+   * @param procedure the procedure to be applied. Stops iteration if the procedure returns <tt>false</tt>, otherwise
+   *                  continues.
+   * @return <tt>false</tt> if the procedure stopped before all keys where iterated over, <tt>true</tt> otherwise.
+   */
+  public abstract boolean forEachKey(${keyTypeCap}Procedure procedure);
+
+  /**
+   * Applies a procedure to each (key,value) pair of the receiver, if any. Iteration order is guaranteed to be
+   * <i>identical</i> to the order used by method {@link #forEachKey(${keyTypeCap}Procedure)}.
+   *
+   * @param procedure the procedure to be applied. Stops iteration if the procedure returns <tt>false</tt>, otherwise
+   *                  continues.
+   * @return <tt>false</tt> if the procedure stopped before all keys where iterated over, <tt>true</tt> otherwise.
+   */
+  public boolean forEachPair(final ${keyTypeCap}ObjectProcedure<T> procedure) {
+    return forEachKey(
+        new ${keyTypeCap}Procedure() {
+          @Override
+          public boolean apply(${keyType} key) {
+            return procedure.apply(key, get(key));
+          }
+        }
+    );
+  }
+
+  /**
+   * Returns the value associated with the specified key. It is often a good idea to first check with {@link
+   * #containsKey(${keyType})} whether the given key has a value associated or not, i.e. whether there exists an association
+   * for the given key or not.
+   *
+   * @param key the key to be searched for.
+   * @return the value associated with the specified key; <tt>null</tt> if no such key is present.
+   */
+  public abstract T get(${keyType} key);
+
+  /**
+   * Returns a list filled with all keys contained in the receiver. The returned list has a size that equals
+   * <tt>this.size()</tt>. Iteration order is guaranteed to be <i>identical</i> to the order used by method {@link
+   * #forEachKey(${keyTypeCap}Procedure)}. <p> This method can be used to iterate over the keys of the receiver.
+   *
+   * @return the keys.
+   */
+  public ${keyTypeCap}ArrayList keys() {
+    ${keyTypeCap}ArrayList list = new ${keyTypeCap}ArrayList(size());
+    keys(list);
+    return list;
+  }
+
+  /**
+   * Fills all keys contained in the receiver into the specified list. Fills the list, starting at index 0. After this
+   * call returns the specified list has a new size that equals <tt>this.size()</tt>. Iteration order is guaranteed to
+   * be <i>identical</i> to the order used by method {@link #forEachKey(${keyTypeCap}Procedure)}. <p> This method can be used to
+   * iterate over the keys of the receiver.
+   *
+   * @param list the list to be filled, can have any size.
+   */
+  public void keys(final ${keyTypeCap}ArrayList list) {
+    list.clear();
+    forEachKey(
+        new ${keyTypeCap}Procedure() {
+          @Override
+          public boolean apply(${keyType} key) {
+            list.add(key);
+            return true;
+          }
+        }
+    );
+  }
+
+  /**
+   * Fills all keys <i>sorted ascending by their associated value</i> into the specified list. Fills into the list,
+   * starting at index 0. After this call returns the specified list has a new size that equals <tt>this.size()</tt>.
+   * Primary sort criterium is "value", secondary sort criterium is "key". This means that if any two values are equal,
+   * the smaller key comes first. <p> <b>Example:</b> <br> <tt>keys = (8,7,6), values = (1,2,2) --> keyList =
+   * (8,6,7)</tt>
+   *
+   * @param keyList the list to be filled, can have any size.
+   */
+  public void keysSortedByValue(${keyTypeCap}ArrayList keyList) {
+    pairsSortedByValue(keyList, new ArrayList<T>(size()));
+  }
+
+  /**
+   * Fills all pairs satisfying a given condition into the specified lists. Fills into the lists, starting at index 0.
+   * After this call returns the specified lists both have a new size, the number of pairs satisfying the condition.
+   * Iteration order is guaranteed to be <i>identical</i> to the order used by method {@link #forEachKey(${keyTypeCap}Procedure)}.
+   * <p> <b>Example:</b> <br>
+   * <pre>
+   * ${keyTypeCap}ObjectProcedure condition = new ${keyTypeCap}ObjectProcedure() { // match even keys only
+   * public boolean apply(${keyType} key, Object value) { return key%2==0; }
+   * }
+   * keys = (8,7,6), values = (1,2,2) --> keyList = (6,8), valueList = (2,1)</tt>
+   * </pre>
+   *
+   * @param condition the condition to be matched. Takes the current key as first and the current value as second
+   *                  argument.
+   * @param keyList   the list to be filled with keys, can have any size.
+   * @param valueList the list to be filled with values, can have any size.
+   */
+  public void pairsMatching(final ${keyTypeCap}ObjectProcedure<T> condition, 
+                            final ${keyTypeCap}ArrayList keyList,
+                            final List<T> valueList) {
+    keyList.clear();
+    valueList.clear();
+
+    forEachPair(
+        new ${keyTypeCap}ObjectProcedure<T>() {
+          @Override
+          public boolean apply(${keyType} key, T value) {
+            if (condition.apply(key, value)) {
+              keyList.add(key);
+              valueList.add(value);
+            }
+            return true;
+          }
+        }
+    );
+  }
+  
+  /**
+   * Fills all keys and values <i>sorted ascending by key</i> into the specified lists. Fills into the lists, starting
+   * at index 0. After this call returns the specified lists both have a new size that equals <tt>this.size()</tt>. <p>
+   * <b>Example:</b> <br> <tt>keys = (8,7,6), values = (1,2,2) --> keyList = (6,7,8), valueList = (2,2,1)</tt>
+   *
+   * @param keyList   the list to be filled with keys, can have any size.
+   * @param valueList the list to be filled with values, can have any size.
+   */
+  @SuppressWarnings("unchecked")
+  public void pairsSortedByKey(${keyTypeCap}ArrayList keyList, List<T> valueList) {
+    keys(keyList);
+    keyList.sort();
+    // the following is straightforward if not the most space-efficient possibility
+    T[] tempValueList = (T[]) new Object[keyList.size()];
+
+    for (int i = keyList.size(); --i >= 0;) {
+      tempValueList[i] = get(keyList.getQuick(i));
+    }
+    valueList.clear();
+    for (int i = 0; i < tempValueList.length; i ++) {
+      valueList.add(tempValueList[i]);
+    }
+    
+  }
+
+  /**
+   * Fills all keys and values <i>sorted ascending by value according to natural ordering</i> into the specified lists.
+   * Fills into the lists, starting at index 0. After this call returns the specified lists both have a new size that
+   * equals <tt>this.size()</tt>. Primary sort criterium is "value", secondary sort criterium is "key". This means that
+   * if any two values are equal, the smaller key comes first. <p> <b>Example:</b> <br> <tt>keys = (8,7,6), values =
+   * (1,2,2) --> keyList = (8,6,7), valueList = (1,2,2)</tt>
+   *
+   * @param keyList   the list to be filled with keys, can have any size.
+   * @param valueList the list to be filled with values, can have any size.
+   */
+  @SuppressWarnings("unchecked")
+  public void pairsSortedByValue(${keyTypeCap}ArrayList keyList, List<T> valueList) {
+    keys(keyList);
+    values(valueList);
+    
+    if (valueList.size() > 0 && !(valueList.get(0) instanceof Comparable)) {
+      throw new UnsupportedOperationException("Cannot sort the values; " 
+          + valueList.get(0).getClass()
+          + " does not implement Comparable");
+    }
+
+    final ${keyType}[] k = keyList.elements();
+    final List<T> valueRef = valueList;
+    Swapper swapper = new Swapper() {
+      @Override
+      public void swap(int a, int b) {
+        T t1 = valueRef.get(a);
+        valueRef.set(a, valueRef.get(b));
+        valueRef.set(b, t1);
+        ${keyType} t2 = k[a];
+        k[a] = k[b];
+        k[b] = t2;
+      }
+    };
+
+    IntComparator comp = new IntComparator() {
+      @Override
+      public int compare(int a, int b) {
+        int ab = ((Comparable)valueRef.get(a)).compareTo(valueRef.get(b));
+        return ab < 0 ? -1 : ab > 0 ? 1 : (k[a] < k[b] ? -1 : (k[a] == k[b] ? 0 : 1));
+      }
+    };
+
+    Sorting.quickSort(0, keyList.size(), comp, swapper);
+  }
+
+  /**
+   * Associates the given key with the given value. Replaces any old <tt>(key,someOtherValue)</tt> association, if
+   * existing.
+   *
+   * @param key   the key the value shall be associated with.
+   * @param value the value to be associated.
+   * @return <tt>true</tt> if the receiver did not already contain such a key; <tt>false</tt> if the receiver did
+   *         already contain such a key - the new value has now replaced the formerly associated value.
+   */
+  public abstract boolean put(${keyType} key, T value);
+
+  /**
+   * Removes the given key with its associated element from the receiver, if present.
+   *
+   * @param key the key to be removed from the receiver.
+   * @return <tt>true</tt> if the receiver contained the specified key, <tt>false</tt> otherwise.
+   */
+  public abstract boolean removeKey(${keyType} key);
+
+  /**
+   * Returns a string representation of the receiver, containing the String representation of each key-value pair,
+   * sorted ascending by key.
+   */
+  public String toString() {
+    ${keyTypeCap}ArrayList theKeys = keys();
+    theKeys.sort();
+
+    StringBuilder buf = new StringBuilder();
+    buf.append('[');
+    int maxIndex = theKeys.size() - 1;
+    for (int i = 0; i <= maxIndex; i++) {
+      ${keyType} key = theKeys.get(i);
+      buf.append(String.valueOf(key));
+      buf.append("->");
+      buf.append(String.valueOf(get(key)));
+      if (i < maxIndex) {
+        buf.append(", ");
+      }
+    }
+    buf.append(']');
+    return buf.toString();
+  }
+
+  /**
+   * Returns a string representation of the receiver, containing the String representation of each key-value pair,
+   * sorted ascending by value, according to natural ordering.
+   */
+  public String toStringByValue() {
+    ${keyTypeCap}ArrayList theKeys = new ${keyTypeCap}ArrayList();
+    keysSortedByValue(theKeys);
+
+    StringBuilder buf = new StringBuilder();
+    buf.append('[');
+    int maxIndex = theKeys.size() - 1;
+    for (int i = 0; i <= maxIndex; i++) {
+      ${keyType} key = theKeys.get(i);
+      buf.append(String.valueOf(key));
+      buf.append("->");
+      buf.append(String.valueOf(get(key)));
+      if (i < maxIndex) {
+        buf.append(", ");
+      }
+    }
+    buf.append(']');
+    return buf.toString();
+  }
+
+  /**
+   * Returns a list filled with all values contained in the receiver. The returned list has a size that equals
+   * <tt>this.size()</tt>. Iteration order is guaranteed to be <i>identical</i> to the order used by method {@link
+   * #forEachKey(${keyTypeCap}Procedure)}. <p> This method can be used to iterate over the values of the receiver.
+   *
+   * @return the values.
+   */
+  public List<T> values() {
+    List<T> list = new ArrayList<T>(size());
+    values(list);
+    return list;
+  }
+
+  /**
+   * Fills all values contained in the receiver into the specified list. Fills the list, starting at index 0. After this
+   * call returns the specified list has a new size that equals <tt>this.size()</tt>. Iteration order is guaranteed to
+   * be <i>identical</i> to the order used by method {@link #forEachKey(${keyTypeCap}Procedure)}. <p> This method can be used to
+   * iterate over the values of the receiver.
+   *
+   * @param list the list to be filled, can have any size.
+   */
+  public void values(final List<T> list) {
+    list.clear();
+    forEachKey(
+        new ${keyTypeCap}Procedure() {
+          @Override
+          public boolean apply(${keyType} key) {
+            list.add(get(key));
+            return true;
+          }
+        }
+    );
+  }
+}

Modified: lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/AbstractKeyTypeValueTypeMap.java.t
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/AbstractKeyTypeValueTypeMap.java.t?rev=899006&r1=899005&r2=899006&view=diff
==============================================================================
--- lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/AbstractKeyTypeValueTypeMap.java.t (original)
+++ lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/AbstractKeyTypeValueTypeMap.java.t Thu Jan 14 00:12:34 2010
@@ -188,35 +188,6 @@
   public abstract ${valueType} get(${keyType} key);
 
   /**
-   * Returns the first key the given value is associated with. It is often a good idea to first check with {@link
-   * #containsValue(int)} whether there exists an association from a key to this value. Search order is guaranteed to be
-   * <i>identical</i> to the order used by method {@link #forEachKey(IntProcedure)}.
-   *
-   * @param value the value to search for.
-   * @return the first key for which holds <tt>get(key) == value</tt>; returns <tt>${keyObjectType}.MIN_VALUE</tt> if no such key
-   *         exists.
-   */
-  public ${keyType} keyOf(final ${valueType} value) {
-    final ${keyType}[] foundKey = new ${keyType}[1];
-    boolean notFound = forEachPair(
-        new ${keyTypeCap}${valueTypeCap}Procedure() {
-          @Override
-          public boolean apply(${keyType} iterKey, ${valueType} iterValue) {
-            boolean found = value == iterValue;
-            if (found) {
-              foundKey[0] = iterKey;
-            }
-            return !found;
-          }
-        }
-    );
-    if (notFound) {
-      return ${keyObjectType}.MIN_VALUE;
-    }
-    return foundKey[0];
-  }
-
-  /**
    * Returns a list filled with all keys contained in the receiver. The returned list has a size that equals
    * <tt>this.size()</tt>. Iteration order is guaranteed to be <i>identical</i> to the order used by method {@link
    * #forEachKey(IntProcedure)}. <p> This method can be used to iterate over the keys of the receiver.

Added: lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/OpenKeyTypeObjectHashMap.java.t
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/OpenKeyTypeObjectHashMap.java.t?rev=899006&view=auto
==============================================================================
--- lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/OpenKeyTypeObjectHashMap.java.t (added)
+++ lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/OpenKeyTypeObjectHashMap.java.t Thu Jan 14 00:12:34 2010
@@ -0,0 +1,565 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+Copyright � 1999 CERN - European Organization for Nuclear Research.
+Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose 
+is hereby granted without fee, provided that the above copyright notice appear in all copies and 
+that both that copyright notice and this permission notice appear in supporting documentation. 
+CERN makes no representations about the suitability of this software for any purpose. 
+It is provided "as is" without expressed or implied warranty.
+*/
+package org.apache.mahout.math.map;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.mahout.math.function.${keyTypeCap}ObjectProcedure;
+import org.apache.mahout.math.function.${keyTypeCap}Procedure;
+import org.apache.mahout.math.list.${keyTypeCap}ArrayList;
+
+public class Open${keyTypeCap}ObjectHashMap<T> extends Abstract${keyTypeCap}ObjectMap<T> {
+
+  private static final byte FREE = 0;
+  private static final byte FULL = 1;
+  private static final byte REMOVED = 2;
+
+  /** The hash table keys. */
+  private ${keyType}[] table;
+
+  /** The hash table values. */
+  private T[] values;
+
+  /** The state of each hash table entry (FREE, FULL, REMOVED). */
+  private byte[] state;
+
+  /** The number of table entries in state==FREE. */
+  private int freeEntries;
+
+  /** Constructs an empty map with default capacity and default load factors. */
+  public Open${keyTypeCap}ObjectHashMap() {
+    this(defaultCapacity);
+  }
+
+  /**
+   * Constructs an empty map with the specified initial capacity and default load factors.
+   *
+   * @param initialCapacity the initial capacity of the map.
+   * @throws IllegalArgumentException if the initial capacity is less than zero.
+   */
+  public Open${keyTypeCap}ObjectHashMap(int initialCapacity) {
+    this(initialCapacity, defaultMinLoadFactor, defaultMaxLoadFactor);
+  }
+
+  /**
+   * Constructs an empty map with the specified initial capacity and the specified minimum and maximum load factor.
+   *
+   * @param initialCapacity the initial capacity.
+   * @param minLoadFactor   the minimum load factor.
+   * @param maxLoadFactor   the maximum load factor.
+   * @throws IllegalArgumentException if <tt>initialCapacity < 0 || (minLoadFactor < 0.0 || minLoadFactor >= 1.0) ||
+   *                                  (maxLoadFactor <= 0.0 || maxLoadFactor >= 1.0) || (minLoadFactor >=
+   *                                  maxLoadFactor)</tt>.
+   */
+  public Open${keyTypeCap}ObjectHashMap(int initialCapacity, double minLoadFactor, double maxLoadFactor) {
+    setUp(initialCapacity, minLoadFactor, maxLoadFactor);
+  }
+
+  /** Removes all (key,value) associations from the receiver. Implicitly calls <tt>trimToSize()</tt>. */
+  @Override
+  public void clear() {
+    Arrays.fill(state, 0, this.state.length - 1, FREE);
+    Arrays.fill(values, 0, state.length - 1, null); // delta
+
+    this.distinct = 0;
+    this.freeEntries = table.length; // delta
+    trimToSize();
+  }
+
+  /**
+   * Returns a deep copy of the receiver.
+   *
+   * @return a deep copy of the receiver.
+   */
+  @SuppressWarnings("unchecked") 
+  @Override
+  public Open${keyTypeCap}ObjectHashMap<T> clone() {
+    Open${keyTypeCap}ObjectHashMap<T> copy = (Open${keyTypeCap}ObjectHashMap<T>) super.clone();
+    copy.table = copy.table.clone();
+    copy.values = copy.values.clone();
+    copy.state = copy.state.clone();
+    return copy;
+  }
+
+  /**
+   * Returns <tt>true</tt> if the receiver contains the specified key.
+   *
+   * @return <tt>true</tt> if the receiver contains the specified key.
+   */
+  @Override
+  public boolean containsKey(${keyType} key) {
+    return indexOfKey(key) >= 0;
+  }
+
+  /**
+   * Returns <tt>true</tt> if the receiver contains the specified value.
+   *
+   * @return <tt>true</tt> if the receiver contains the specified value.
+   */
+  @Override
+  public boolean containsValue(T value) {
+    return indexOfValue(value) >= 0;
+  }
+
+  /**
+   * Ensures that the receiver can hold at least the specified number of associations without needing to allocate new
+   * internal memory. If necessary, allocates new internal memory and increases the capacity of the receiver. <p> This
+   * method never need be called; it is for performance tuning only. Calling this method before <tt>put()</tt>ing a
+   * large number of associations boosts performance, because the receiver will grow only once instead of potentially
+   * many times and hash collisions get less probable.
+   *
+   * @param minCapacity the desired minimum capacity.
+   */
+  @Override
+  public void ensureCapacity(int minCapacity) {
+    if (table.length < minCapacity) {
+      int newCapacity = nextPrime(minCapacity);
+      rehash(newCapacity);
+    }
+  }
+
+  /**
+   * Applies a procedure to each key of the receiver, if any. Note: Iterates over the keys in no particular order.
+   * Subclasses can define a particular order, for example, "sorted by key". All methods which <i>can</i> be expressed
+   * in terms of this method (most methods can) <i>must guarantee</i> to use the <i>same</i> order defined by this
+   * method, even if it is no particular order. This is necessary so that, for example, methods <tt>keys</tt> and
+   * <tt>values</tt> will yield association pairs, not two uncorrelated lists.
+   *
+   * @param procedure the procedure to be applied. Stops iteration if the procedure returns <tt>false</tt>, otherwise
+   *                  continues.
+   * @return <tt>false</tt> if the procedure stopped before all keys where iterated over, <tt>true</tt> otherwise.
+   */
+  @Override
+  public boolean forEachKey(${keyTypeCap}Procedure procedure) {
+    for (int i = table.length; i-- > 0;) {
+      if (state[i] == FULL) {
+        if (!procedure.apply(table[i])) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Applies a procedure to each (key,value) pair of the receiver, if any. Iteration order is guaranteed to be
+   * <i>identical</i> to the order used by method {@link #forEachKey(${keyTypeCap}Procedure)}.
+   *
+   * @param procedure the procedure to be applied. Stops iteration if the procedure returns <tt>false</tt>, otherwise
+   *                  continues.
+   * @return <tt>false</tt> if the procedure stopped before all keys where iterated over, <tt>true</tt> otherwise.
+   */
+  @Override
+  public boolean forEachPair(${keyTypeCap}ObjectProcedure<T> procedure) {
+    for (int i = table.length; i-- > 0;) {
+      if (state[i] == FULL) {
+        if (!procedure.apply(table[i], values[i])) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Returns the value associated with the specified key. It is often a good idea to first check with {@link
+   * #containsKey(int)} whether the given key has a value associated or not, i.e. whether there exists an association
+   * for the given key or not.
+   *
+   * @param key the key to be searched for.
+   * @return the value associated with the specified key; <tt>null</tt> if no such key is present.
+   */
+  @Override
+  public T get(${keyType} key) {
+    int i = indexOfKey(key);
+    if (i < 0) {
+      return null;
+    } //not contained
+    return values[i];
+  }
+
+  /**
+   * @param key the key to be added to the receiver.
+   * @return the index where the key would need to be inserted, if it is not already contained. Returns -index-1 if the
+   *         key is already contained at slot index. Therefore, if the returned index < 0, then it is already contained
+   *         at slot -index-1. If the returned index >= 0, then it is NOT already contained and should be inserted at
+   *         slot index.
+   */
+  protected int indexOfInsertion(${keyType} key) {
+    ${keyType}[] tab = table;
+    byte[] stat = state;
+    int length = tab.length;
+
+    int hash = HashFunctions.hash(key) & 0x7FFFFFFF;
+    int i = hash % length;
+    int decrement = hash % (length - 2); // double hashing, see http://www.eece.unm.edu/faculty/heileman/hash/node4.html
+    //int decrement = (hash / length) % length;
+    if (decrement == 0) {
+      decrement = 1;
+    }
+
+    // stop if we find a removed or free slot, or if we find the key itself
+    // do NOT skip over removed slots (yes, open addressing is like that...)
+    while (stat[i] == FULL && tab[i] != key) {
+      i -= decrement;
+      //hashCollisions++;
+      if (i < 0) {
+        i += length;
+      }
+    }
+
+    if (stat[i] == REMOVED) {
+      // stop if we find a free slot, or if we find the key itself.
+      // do skip over removed slots (yes, open addressing is like that...)
+      // assertion: there is at least one FREE slot.
+      int j = i;
+      while (stat[i] != FREE && (stat[i] == REMOVED || tab[i] != key)) {
+        i -= decrement;
+        //hashCollisions++;
+        if (i < 0) {
+          i += length;
+        }
+      }
+      if (stat[i] == FREE) {
+        i = j;
+      }
+    }
+
+
+    if (stat[i] == FULL) {
+      // key already contained at slot i.
+      // return a negative number identifying the slot.
+      return -i - 1;
+    }
+    // not already contained, should be inserted at slot i.
+    // return a number >= 0 identifying the slot.
+    return i;
+  }
+
+  /**
+   * @param key the key to be searched in the receiver.
+   * @return the index where the key is contained in the receiver, returns -1 if the key was not found.
+   */
+  protected int indexOfKey(${keyType} key) {
+    ${keyType}[] tab = table;
+    byte[] stat = state;
+    int length = tab.length;
+
+    int hash = HashFunctions.hash(key) & 0x7FFFFFFF;
+    int i = hash % length;
+    int decrement = hash % (length - 2); // double hashing, see http://www.eece.unm.edu/faculty/heileman/hash/node4.html
+    //int decrement = (hash / length) % length;
+    if (decrement == 0) {
+      decrement = 1;
+    }
+
+    // stop if we find a free slot, or if we find the key itself.
+    // do skip over removed slots (yes, open addressing is like that...)
+    while (stat[i] != FREE && (stat[i] == REMOVED || tab[i] != key)) {
+      i -= decrement;
+      //hashCollisions++;
+      if (i < 0) {
+        i += length;
+      }
+    }
+
+    if (stat[i] == FREE) {
+      return -1;
+    } // not found
+    return i; //found, return index where key is contained
+  }
+
+  /**
+   * @param value the value to be searched in the receiver.
+   * @return the index where the value is contained in the receiver, returns -1 if the value was not found.
+   */
+  protected int indexOfValue(T value) {
+    T[] val = values;
+    byte[] stat = state;
+
+    for (int i = stat.length; --i >= 0;) {
+      if (stat[i] == FULL && val[i] == value) {
+        return i;
+      }
+    }
+
+    return -1; // not found
+  }
+
+  /**
+   * Fills all keys contained in the receiver into the specified list. Fills the list, starting at index 0. After this
+   * call returns the specified list has a new size that equals <tt>this.size()</tt>. Iteration order is guaranteed to
+   * be <i>identical</i> to the order used by method {@link #forEachKey(${keyTypeCap}Procedure)}. <p> This method can be used to
+   * iterate over the keys of the receiver.
+   *
+   * @param list the list to be filled, can have any size.
+   */
+  @Override
+  public void keys(${keyTypeCap}ArrayList list) {
+    list.setSize(distinct);
+    ${keyType}[] elements = list.elements();
+
+    ${keyType}[] tab = table;
+    byte[] stat = state;
+
+    int j = 0;
+    for (int i = tab.length; i-- > 0;) {
+      if (stat[i] == FULL) {
+        elements[j++] = tab[i];
+      }
+    }
+  }
+
+  /**
+   * Fills all pairs satisfying a given condition into the specified lists. Fills into the lists, starting at index 0.
+   * After this call returns the specified lists both have a new size, the number of pairs satisfying the condition.
+   * Iteration order is guaranteed to be <i>identical</i> to the order used by method {@link #forEachKey(${keyTypeCap}Procedure)}.
+   * <p> <b>Example:</b> <br>
+   * <pre>
+   * ${keyTypeCap}ObjectProcedure condition = new ${keyTypeCap}ObjectProcedure() { // match even keys only
+   * public boolean apply(${keyType} key, Object value) { return key%2==0; }
+   * }
+   * keys = (8,7,6), values = (1,2,2) --> keyList = (6,8), valueList = (2,1)</tt>
+   * </pre>
+   *
+   * @param condition the condition to be matched. Takes the current key as first and the current value as second
+   *                  argument.
+   * @param keyList   the list to be filled with keys, can have any size.
+   * @param valueList the list to be filled with values, can have any size.
+   */
+  @Override
+  public void pairsMatching(${keyTypeCap}ObjectProcedure<T> condition, 
+                            ${keyTypeCap}ArrayList keyList, 
+                            List<T> valueList) {
+    keyList.clear();
+    valueList.clear();
+
+    for (int i = table.length; i-- > 0;) {
+      if (state[i] == FULL && condition.apply(table[i], values[i])) {
+        keyList.add(table[i]);
+        valueList.add(values[i]);
+      }
+    }
+  }
+
+  /**
+   * Associates the given key with the given value. Replaces any old <tt>(key,someOtherValue)</tt> association, if
+   * existing.
+   *
+   * @param key   the key the value shall be associated with.
+   * @param value the value to be associated.
+   * @return <tt>true</tt> if the receiver did not already contain such a key; <tt>false</tt> if the receiver did
+   *         already contain such a key - the new value has now replaced the formerly associated value.
+   */
+  @Override
+  public boolean put(${keyType} key, T value) {
+    int i = indexOfInsertion(key);
+    if (i < 0) { //already contained
+      i = -i - 1;
+      this.values[i] = value;
+      return false;
+    }
+
+    if (this.distinct > this.highWaterMark) {
+      int newCapacity = chooseGrowCapacity(this.distinct + 1, this.minLoadFactor, this.maxLoadFactor);
+      rehash(newCapacity);
+      return put(key, value);
+    }
+
+    this.table[i] = key;
+    this.values[i] = value;
+    if (this.state[i] == FREE) {
+      this.freeEntries--;
+    }
+    this.state[i] = FULL;
+    this.distinct++;
+
+    if (this.freeEntries < 1) { //delta
+      int newCapacity = chooseGrowCapacity(this.distinct + 1, this.minLoadFactor, this.maxLoadFactor);
+      rehash(newCapacity);
+    }
+
+    return true;
+  }
+
+  /**
+   * Rehashes the contents of the receiver into a new table with a smaller or larger capacity. This method is called
+   * automatically when the number of keys in the receiver exceeds the high water mark or falls below the low water
+   * mark.
+   */
+  @SuppressWarnings("unchecked")
+  protected void rehash(int newCapacity) {
+    int oldCapacity = table.length;
+    //if (oldCapacity == newCapacity) return;
+
+    ${keyType}[] oldTable = table;
+    T[] oldValues = values;
+    byte[] oldState = state;
+
+    ${keyType}[] newTable = new ${keyType}[newCapacity];
+    T[] newValues = (T[]) new Object[newCapacity];
+    byte[] newState = new byte[newCapacity];
+
+    this.lowWaterMark = chooseLowWaterMark(newCapacity, this.minLoadFactor);
+    this.highWaterMark = chooseHighWaterMark(newCapacity, this.maxLoadFactor);
+
+    this.table = newTable;
+    this.values = newValues;
+    this.state = newState;
+    this.freeEntries = newCapacity - this.distinct; // delta
+
+    for (int i = oldCapacity; i-- > 0;) {
+      if (oldState[i] == FULL) {
+        ${keyType} element = oldTable[i];
+        int index = indexOfInsertion(element);
+        newTable[index] = element;
+        newValues[index] = oldValues[i];
+        newState[index] = FULL;
+      }
+    }
+  }
+
+  /**
+   * Removes the given key with its associated element from the receiver, if present.
+   *
+   * @param key the key to be removed from the receiver.
+   * @return <tt>true</tt> if the receiver contained the specified key, <tt>false</tt> otherwise.
+   */
+  @Override
+  public boolean removeKey(${keyType} key) {
+    int i = indexOfKey(key);
+    if (i < 0) {
+      return false;
+    } // key not contained
+
+    this.state[i] = REMOVED;
+    this.values[i] = null; // delta
+    this.distinct--;
+
+    if (this.distinct < this.lowWaterMark) {
+      int newCapacity = chooseShrinkCapacity(this.distinct, this.minLoadFactor, this.maxLoadFactor);
+      rehash(newCapacity);
+    }
+
+    return true;
+  }
+
+  /**
+   * Initializes the receiver.
+   *
+   * @param initialCapacity the initial capacity of the receiver.
+   * @param minLoadFactor   the minLoadFactor of the receiver.
+   * @param maxLoadFactor   the maxLoadFactor of the receiver.
+   * @throws IllegalArgumentException if <tt>initialCapacity < 0 || (minLoadFactor < 0.0 || minLoadFactor >= 1.0) ||
+   *                                  (maxLoadFactor <= 0.0 || maxLoadFactor >= 1.0) || (minLoadFactor >=
+   *                                  maxLoadFactor)</tt>.
+   */
+  @SuppressWarnings("unchecked")
+  @Override
+  protected void setUp(int initialCapacity, double minLoadFactor, double maxLoadFactor) {
+    int capacity = initialCapacity;
+    super.setUp(capacity, minLoadFactor, maxLoadFactor);
+    capacity = nextPrime(capacity);
+    if (capacity == 0) {
+      capacity = 1;
+    } // open addressing needs at least one FREE slot at any time.
+
+    this.table = new ${keyType}[capacity];
+    this.values = (T[]) new Object[capacity];
+    this.state = new byte[capacity];
+
+    // memory will be exhausted long before this pathological case happens, anyway.
+    this.minLoadFactor = minLoadFactor;
+    if (capacity == PrimeFinder.largestPrime) {
+      this.maxLoadFactor = 1.0;
+    } else {
+      this.maxLoadFactor = maxLoadFactor;
+    }
+
+    this.distinct = 0;
+    this.freeEntries = capacity; // delta
+
+    // lowWaterMark will be established upon first expansion.
+    // establishing it now (upon instance construction) would immediately make the table shrink upon first put(...).
+    // After all the idea of an "initialCapacity" implies violating lowWaterMarks when an object is young.
+    // See ensureCapacity(...)
+    this.lowWaterMark = 0;
+    this.highWaterMark = chooseHighWaterMark(capacity, this.maxLoadFactor);
+  }
+
+  /**
+   * Trims the capacity of the receiver to be the receiver's current size. Releases any superfluous internal memory. An
+   * application can use this operation to minimize the storage of the receiver.
+   */
+  @Override
+  public void trimToSize() {
+    // * 1.2 because open addressing's performance exponentially degrades beyond that point
+    // so that even rehashing the table can take very long
+    int newCapacity = nextPrime((int) (1 + 1.2 * size()));
+    if (table.length > newCapacity) {
+      rehash(newCapacity);
+    }
+  }
+
+  /**
+   * Fills all values contained in the receiver into the specified list. Fills the list, starting at index 0. After this
+   * call returns the specified list has a new size that equals <tt>this.size()</tt>. Iteration order is guaranteed to
+   * be <i>identical</i> to the order used by method {@link #forEachKey(${keyTypeCap}Procedure)}. <p> This method can be used to
+   * iterate over the values of the receiver.
+   *
+   * @param list the list to be filled, can have any size.
+   */
+  @Override
+  public void values(List<T> list) {
+    list.clear();
+
+    T[] val = values;
+    byte[] stat = state;
+
+    for (int i = stat.length; i-- > 0;) {
+      if (stat[i] == FULL) {
+        list.add(val[i]);
+      }
+    }
+  }
+  
+  /**
+   * Access for unit tests.
+   * @param capacity
+   * @param minLoadFactor
+   * @param maxLoadFactor
+   */
+  void getInternalFactors(int[] capacity, 
+      double[] minLoadFactor, 
+      double[] maxLoadFactor) {
+    capacity[0] = table.length;
+    minLoadFactor[0] = this.minLoadFactor;
+    maxLoadFactor[0] = this.maxLoadFactor;
+  }
+}

Modified: lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/OpenKeyTypeValueTypeHashMap.java.t
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/OpenKeyTypeValueTypeHashMap.java.t?rev=899006&r1=899005&r2=899006&view=diff
==============================================================================
--- lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/OpenKeyTypeValueTypeHashMap.java.t (original)
+++ lucene/mahout/trunk/math/src/main/java-templates/org/apache/mahout/math/map/OpenKeyTypeValueTypeHashMap.java.t Thu Jan 14 00:12:34 2010
@@ -323,26 +323,6 @@
   }
 
   /**
-   * Returns the first key the given value is associated with. It is often a good idea to first check with {@link
-   * #containsValue(int)} whether there exists an association from a key to this value. Search order is guaranteed to be
-   * <i>identical</i> to the order used by method {@link #forEachKey(${keyTypeCap}Procedure)}.
-   *
-   * @param value the value to search for.
-   * @return the first key for which holds <tt>get(key) == value</tt>; 
-   * returns <tt>${noKeyComment}</tt> if no such key
-   *         exists.
-   */
-  @Override
-  public ${keyType} keyOf(${valueType} value) {
-    //returns the first key found; there may be more matching keys, however.
-    int i = indexOfValue(value);
-    if (i < 0) {
-      return NO_KEY_VALUE;
-    }
-    return table[i];
-  }
-
-  /**
    * Fills all keys contained in the receiver into the specified list. Fills the list, starting at index 0. After this
    * call returns the specified list has a new size that equals <tt>this.size()</tt>. Iteration order is guaranteed to
    * be <i>identical</i> to the order used by method {@link #forEachKey(${keyTypeCap}Procedure)}.

Added: lucene/mahout/trunk/math/src/test/java-templates/org/apache/mahout/math/map/OpenKeyTypeObjectHashMapTest.java.t
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/test/java-templates/org/apache/mahout/math/map/OpenKeyTypeObjectHashMapTest.java.t?rev=899006&view=auto
==============================================================================
--- lucene/mahout/trunk/math/src/test/java-templates/org/apache/mahout/math/map/OpenKeyTypeObjectHashMapTest.java.t (added)
+++ lucene/mahout/trunk/math/src/test/java-templates/org/apache/mahout/math/map/OpenKeyTypeObjectHashMapTest.java.t Thu Jan 14 00:12:34 2010
@@ -0,0 +1,427 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#if (${keyTypeFloating} == 'true')
+#set ($keyEpsilon = ", (${keyType})0.000001")
+#else 
+#set ($keyEpsilon = "")
+#end
+  
+ package org.apache.mahout.math.map;
+ 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.mahout.math.function.${keyTypeCap}ObjectProcedure;
+import org.apache.mahout.math.function.${keyTypeCap}Procedure;
+import org.apache.mahout.math.list.${keyTypeCap}ArrayList;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class Open${keyTypeCap}ObjectHashMapTest extends Assert {
+  
+  private static class TestClass implements Comparable<TestClass>{
+    
+    public TestClass(${keyType} x) {
+      this.x = x;
+    }
+    
+    @Override
+    public String toString() {
+      return "[ts " + x + " ]";
+    }
+
+    @Override
+    public int hashCode() {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ${keyObjectType}.valueOf(x).hashCode();
+      return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null) return false;
+      if (getClass() != obj.getClass()) return false;
+      TestClass other = (TestClass) obj;
+      if (x != other.x) return false;
+      return true;
+    }
+
+    ${keyType} x;
+
+    @Override
+    public int compareTo(TestClass o) {
+
+#if (${keyTypeFloating} == 'true')
+      return ${keyObjectType}.compare(x, o.x);
+#else
+      return (int)(x - o.x);
+#end
+    }
+  }
+  
+  private TestClass item;
+  private TestClass anotherItem;
+  private TestClass anotherItem2;
+  private TestClass anotherItem3;
+  private TestClass anotherItem4;
+  private TestClass anotherItem5;
+  
+  @Before
+  public void before() {
+    item = new TestClass((${keyType})101);
+    anotherItem = new TestClass((${keyType})99);
+    anotherItem2 = new TestClass((${keyType})2);
+    anotherItem3 = new TestClass((${keyType})3);
+    anotherItem4 = new TestClass((${keyType})4);
+    anotherItem5 = new TestClass((${keyType})5);
+    
+  }
+
+  
+  @Test
+  public void testConstructors() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    int[] capacity = new int[1];
+    double[] minLoadFactor = new double[1];
+    double[] maxLoadFactor = new double[1];
+    
+    map.getInternalFactors(capacity, minLoadFactor, maxLoadFactor);
+    assertEquals(AbstractMap.defaultCapacity, capacity[0]);
+    assertEquals(AbstractMap.defaultMaxLoadFactor, maxLoadFactor[0], 0.001);
+    assertEquals(AbstractMap.defaultMinLoadFactor, minLoadFactor[0], 0.001);
+    int prime = PrimeFinder.nextPrime(907);
+    map = new Open${keyTypeCap}ObjectHashMap<TestClass>(prime);
+    
+    map.getInternalFactors(capacity, minLoadFactor, maxLoadFactor);
+    assertEquals(prime, capacity[0]);
+    assertEquals(AbstractMap.defaultMaxLoadFactor, maxLoadFactor[0], 0.001);
+    assertEquals(AbstractMap.defaultMinLoadFactor, minLoadFactor[0], 0.001);
+    
+    map = new Open${keyTypeCap}ObjectHashMap<TestClass>(prime, 0.4, 0.8);
+    map.getInternalFactors(capacity, minLoadFactor, maxLoadFactor);
+    assertEquals(prime, capacity[0]);
+    assertEquals(0.4, minLoadFactor[0], 0.001);
+    assertEquals(0.8, maxLoadFactor[0], 0.001);
+  }
+  
+  @Test
+  public void testEnsureCapacity() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    int prime = PrimeFinder.nextPrime(907);
+    
+    map.ensureCapacity(prime);
+    int[] capacity = new int[1];
+    double[] minLoadFactor = new double[1];
+    double[] maxLoadFactor = new double[1];
+    
+    map.getInternalFactors(capacity, minLoadFactor, maxLoadFactor);
+    assertEquals(prime, capacity[0]);
+  }
+  
+  @Test
+  public void testClear() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, item); 
+    assertEquals(1, map.size());
+    map.clear();
+    assertEquals(0, map.size());
+    assertSame(null, map.get((${keyType}) 11));
+  }
+  
+  @Test
+  public void testClone() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, item);
+    Open${keyTypeCap}ObjectHashMap<TestClass> map2 = (Open${keyTypeCap}ObjectHashMap<TestClass>) map.clone();
+    map.clear();
+    assertEquals(1, map2.size());
+  }
+  
+  @Test
+  public void testContainsKey() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, item);
+    assertTrue(map.containsKey((${keyType}) 11));
+    assertFalse(map.containsKey((${keyType}) 12));
+  }
+  
+  @Test
+  public void testContainValue() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, item);
+    assertTrue(map.containsValue(item));
+    assertFalse(map.containsValue(anotherItem));
+  }
+  
+  @Test
+  public void testForEachKey() {
+    final ${keyTypeCap}ArrayList keys = new ${keyTypeCap}ArrayList();
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, anotherItem);
+    map.put((${keyType}) 12, anotherItem2);
+    map.put((${keyType}) 13, anotherItem3);
+    map.put((${keyType}) 14, anotherItem4);
+    map.removeKey((${keyType}) 13);
+    map.forEachKey(new ${keyTypeCap}Procedure() {
+      
+      @Override
+      public boolean apply(${keyType} element) {
+        keys.add(element);
+        return true;
+      }
+    });
+    
+    ${keyType}[] keysArray = keys.toArray(new ${keyType}[keys.size()]);
+    Arrays.sort(keysArray);
+    
+    assertArrayEquals(new ${keyType}[] {11, 12, 14}, keysArray ${keyEpsilon});
+  }
+  
+  private static class Pair implements Comparable<Pair> {
+    ${keyType} k;
+    TestClass v;
+    
+    Pair(${keyType} k, TestClass v) {
+      this.k = k;
+      this.v = v;
+    }
+    
+    @Override
+    public int compareTo(Pair o) {
+      if (k < o.k) {
+        return -1;
+      } else if (k == o.k) {
+        return 0;
+      } else {
+        return 1;
+      }
+    }
+  }
+  
+  @Test
+  public void testForEachPair() {
+    final List<Pair> pairs = new ArrayList<Pair>();
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, anotherItem);
+    map.put((${keyType}) 12, anotherItem2);
+    map.put((${keyType}) 13, anotherItem3);
+    map.put((${keyType}) 14, anotherItem4);
+    map.removeKey((${keyType}) 13);
+    map.forEachPair(new ${keyTypeCap}ObjectProcedure<TestClass>() {
+      
+      @Override
+      public boolean apply(${keyType} first, TestClass second) {
+        pairs.add(new Pair(first, second));
+        return true;
+      }
+    });
+    
+    Collections.sort(pairs);
+    assertEquals(3, pairs.size());
+    assertEquals((${keyType}) 11, pairs.get(0).k ${keyEpsilon});
+    assertSame(anotherItem, pairs.get(0).v );
+    assertEquals((${keyType}) 12, pairs.get(1).k ${keyEpsilon});
+    assertSame(anotherItem2, pairs.get(1).v );
+    assertEquals((${keyType}) 14, pairs.get(2).k ${keyEpsilon});
+    assertSame(anotherItem4, pairs.get(2).v );
+    
+    pairs.clear();
+    map.forEachPair(new ${keyTypeCap}ObjectProcedure<TestClass>() {
+      int count = 0;
+      
+      @Override
+      public boolean apply(${keyType} first, TestClass second) {
+        pairs.add(new Pair(first, second));
+        count++;
+        return count < 2;
+      }
+    });
+    
+    assertEquals(2, pairs.size());
+  }
+  
+  @Test
+  public void testGet() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, item);
+    map.put((${keyType}) 12, anotherItem);
+    assertSame(item, map.get((${keyType})11) );
+    assertSame(null, map.get((${keyType})0) );
+  }
+
+  @Test
+  public void testKeys() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, item);
+    map.put((${keyType}) 12, item);
+    ${keyTypeCap}ArrayList keys = new ${keyTypeCap}ArrayList();
+    map.keys(keys);
+    keys.sort();
+    assertEquals(11, keys.get(0) ${keyEpsilon});
+    assertEquals(12, keys.get(1) ${keyEpsilon});
+    ${keyTypeCap}ArrayList k2 = map.keys();
+    k2.sort();
+    assertEquals(keys, k2);
+  }
+  
+  @Test
+  public void testPairsMatching() {
+    ${keyTypeCap}ArrayList keyList = new ${keyTypeCap}ArrayList();
+    List<TestClass> valueList = new ArrayList<TestClass>();
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, anotherItem2);
+    map.put((${keyType}) 12, anotherItem3);
+    map.put((${keyType}) 13, anotherItem4);
+    map.put((${keyType}) 14, anotherItem5);
+    map.removeKey((${keyType}) 13);
+    map.pairsMatching(new ${keyTypeCap}ObjectProcedure<TestClass>() {
+
+      @Override
+      public boolean apply(${keyType} first, TestClass second) {
+        return (first % 2) == 0;
+      }},
+        keyList, valueList);
+    keyList.sort();
+    Collections.sort(valueList);
+    assertEquals(2, keyList.size());
+    assertEquals(2, valueList.size());
+    assertEquals(12, keyList.get(0) ${keyEpsilon});
+    assertEquals(14, keyList.get(1) ${keyEpsilon});
+    assertSame(anotherItem3, valueList.get(0) );
+    assertSame(anotherItem5, valueList.get(1) );
+  }
+  
+  @Test
+  public void testValues() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, anotherItem);
+    map.put((${keyType}) 12, anotherItem2);
+    map.put((${keyType}) 13, anotherItem3);
+    map.put((${keyType}) 14, anotherItem4);
+    map.removeKey((${keyType}) 13);
+    List<TestClass> values = new ArrayList<TestClass>(100);
+    map.values(values);
+    assertEquals(3, values.size());
+    Collections.sort(values);
+    assertEquals(anotherItem2, values.get(0) );
+    assertEquals(anotherItem4, values.get(1) );
+    assertEquals(anotherItem, values.get(2) );
+  }
+  
+  // tests of the code in the abstract class
+  
+  @Test
+  public void testCopy() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, item);
+    Open${keyTypeCap}ObjectHashMap<TestClass> map2 = (Open${keyTypeCap}ObjectHashMap<TestClass>) map.copy();
+    map.clear();
+    assertEquals(1, map2.size());
+  }
+  
+  @Test
+  public void testEquals() {
+    // since there are no other subclasses of 
+    // Abstractxxx available, we have to just test the
+    // obvious.
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, anotherItem);
+    map.put((${keyType}) 12, anotherItem2);
+    map.put((${keyType}) 13, anotherItem3);
+    map.put((${keyType}) 14, anotherItem4);
+    map.removeKey((${keyType}) 13);
+    Open${keyTypeCap}ObjectHashMap<TestClass> map2 = (Open${keyTypeCap}ObjectHashMap<TestClass>) map.copy();
+    assertTrue(map.equals(map2));
+    assertTrue(map2.equals(map));
+    assertFalse("Hello Sailor".equals(map));
+    assertFalse(map.equals("hello sailor"));
+    map2.removeKey((${keyType}) 11);
+    assertFalse(map.equals(map2));
+    assertFalse(map2.equals(map));
+  }
+  
+  // keys() tested in testKeys
+  
+  @Test
+  public void testKeysSortedByValue() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, anotherItem5);
+    map.put((${keyType}) 12, anotherItem4);
+    map.put((${keyType}) 13, anotherItem3);
+    map.put((${keyType}) 14, anotherItem2);
+    map.removeKey((${keyType}) 13);
+    ${keyTypeCap}ArrayList keys = new ${keyTypeCap}ArrayList();
+    map.keysSortedByValue(keys);
+    ${keyType}[] keysArray = keys.toArray(new ${keyType}[keys.size()]);
+    assertArrayEquals(new ${keyType}[] {14, 12, 11},
+        keysArray ${keyEpsilon});
+  }
+  
+  @Test
+  public void testPairsSortedByKey() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, anotherItem5);
+    map.put((${keyType}) 12, anotherItem4);
+    map.put((${keyType}) 13, anotherItem3);
+    map.put((${keyType}) 14, anotherItem2);
+    
+    ${keyTypeCap}ArrayList keys = new ${keyTypeCap}ArrayList();
+    List<TestClass> values = new ArrayList<TestClass>();
+    map.pairsSortedByKey(keys, values);
+    
+    assertEquals(4, keys.size());
+    assertEquals(4, values.size());
+    assertEquals((${keyType}) 11, keys.get(0) ${keyEpsilon});
+    assertSame(anotherItem5, values.get(0) );
+    assertEquals((${keyType}) 12, keys.get(1) ${keyEpsilon});
+    assertSame(anotherItem4, values.get(1) );
+    assertEquals((${keyType}) 13, keys.get(2) ${keyEpsilon});
+    assertSame(anotherItem3, values.get(2) );
+    assertEquals((${keyType}) 14, keys.get(3) ${keyEpsilon});
+    assertSame(anotherItem2, values.get(3) );
+  }
+  
+  @Test
+  public void testPairsSortedByValue() {
+    Open${keyTypeCap}ObjectHashMap<TestClass> map = new Open${keyTypeCap}ObjectHashMap<TestClass>();
+    map.put((${keyType}) 11, anotherItem5);
+    map.put((${keyType}) 12, anotherItem4);
+    map.put((${keyType}) 13, anotherItem3);
+    map.put((${keyType}) 14, anotherItem2);
+    
+    ${keyTypeCap}ArrayList keys = new ${keyTypeCap}ArrayList();
+    List<TestClass> values = new ArrayList<TestClass>();
+    map.pairsSortedByValue(keys, values);
+    assertEquals((${keyType}) 11, keys.get(3) ${keyEpsilon});
+    assertEquals(anotherItem5, values.get(3) );
+    assertEquals((${keyType}) 12, keys.get(2) ${keyEpsilon});
+    assertEquals(anotherItem4, values.get(2) );
+    assertEquals((${keyType}) 13, keys.get(1) ${keyEpsilon});
+    assertEquals(anotherItem3, values.get(1) );
+    assertEquals((${keyType}) 14, keys.get(0) ${keyEpsilon});
+    assertEquals(anotherItem2, values.get(0) );
+  }
+ 
+ }

Modified: lucene/mahout/trunk/math/src/test/java-templates/org/apache/mahout/math/map/OpenKeyTypeValueTypeHashMapTest.java.t
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/math/src/test/java-templates/org/apache/mahout/math/map/OpenKeyTypeValueTypeHashMapTest.java.t?rev=899006&r1=899005&r2=899006&view=diff
==============================================================================
--- lucene/mahout/trunk/math/src/test/java-templates/org/apache/mahout/math/map/OpenKeyTypeValueTypeHashMapTest.java.t (original)
+++ lucene/mahout/trunk/math/src/test/java-templates/org/apache/mahout/math/map/OpenKeyTypeValueTypeHashMapTest.java.t Thu Jan 14 00:12:34 2010
@@ -217,25 +217,6 @@
     assertEquals(22, map.get(($keyType)11) ${valueEpsilon});
     assertEquals(0, map.get(($keyType)0) ${valueEpsilon});
   }
-
-  /*
-   * Note that the javadoc says 'first' but the order
-   * is not defined.
-   */
-  @Test
-  public void testKeyOf() {
-    Open${keyTypeCap}${valueTypeCap}HashMap map = new Open${keyTypeCap}${valueTypeCap}HashMap();
-    map.put(($keyType) 11, (${valueType}) 22);
-    map.put(($keyType) 12, (${valueType}) 22);
-    ${keyType} k = map.keyOf((${valueType})22);
-    assertTrue(k == 11 || k == 12);
-    k = map.keyOf((${valueType})101);
-#if (${keyTypeFloating} == 'true')
-    assertTrue(${keyTypeCap}.isNaN(k));
-#else
-    assertEquals(0, k ${keyEpsilon});
-#end
-  }
   
   @Test
   public void testKeys() {

Modified: lucene/mahout/trunk/utils/pom.xml
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/utils/pom.xml?rev=899006&r1=899005&r2=899006&view=diff
==============================================================================
--- lucene/mahout/trunk/utils/pom.xml (original)
+++ lucene/mahout/trunk/utils/pom.xml Thu Jan 14 00:12:34 2010
@@ -122,7 +122,6 @@
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>3.8.2</version>
       <scope>test</scope>
     </dependency>