Mega Code Archive

 
Categories / Java / Collections Data Structure
 

Prefetch Iterator

/*   * JGraphT : a free Java graph-theory library  *   *  * Project Info:  http://jgrapht.sourceforge.net/  * Project Creator:  Barak Naveh (http://sourceforge.net/users/barak_naveh)  *  * (C) Copyright 2003-2007, by Barak Naveh and Contributors.  *  * 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 2.1 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, write to the Free Software Foundation,  * Inc.,  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.  */ /* -----------------  * PrefetchIterator.java  * -----------------  * (C) Copyright 2005-2007, by Assaf Lehr and Contributors.  *  * Original Author:  Assaf Lehr  * Contributor(s):   -  *  * $Id: PrefetchIterator.java 568 2007-09-30 00:12:18Z perfecthash $  *  * Changes  * -------  */ import java.util.*; /**  * Utility class to help implement an iterator/enumerator in which the hasNext()  * method needs to calculate the next elements ahead of time.  *  * <p>Many classes which implement an iterator face a common problem: if there  * is no easy way to calculate hasNext() other than to call getNext(), then they  * save the result for fetching in the next call to getNext(). This utility  * helps in doing just that.  *  * <p><b>Usage:</b> The new iterator class will hold this class as a member  * variable and forward the hasNext() and next() to it. When creating an  * instance of this class, you supply it with a functor that is doing the real  * job of calculating the next element.  *  * <pre><code>     //This class supllies enumeration of integer till 100.     public class IteratorExample implements Enumeration{     private int counter=0;     private PrefetchIterator nextSupplier;         IteratorExample()         {             nextSupplier = new PrefetchIterator(new PrefetchIterator.NextElementFunctor(){                 public Object nextElement() throws NoSuchElementException {                     counter++;                     if (counter>=100)                         throw new NoSuchElementException();                     else                         return new Integer(counter);                 }             });         }         //forwarding to nextSupplier and return its returned value         public boolean hasMoreElements() {             return this.nextSupplier.hasMoreElements();         }     //  forwarding to nextSupplier and return its returned value         public Object nextElement() {             return this.nextSupplier.nextElement();         }   }</pre>  * </code>  *  * @author Assaf_Lehr  */ public class PrefetchIterator<E>     implements Iterator<E>,         Enumeration<E> {     //~ Instance fields --------------------------------------------------------     private NextElementFunctor<E> innerEnum;     private E getNextLastResult;     private boolean isGetNextLastResultUpToDate = false;     private boolean endOfEnumerationReached = false;     private boolean flagIsEnumerationStartedEmpty = true;     private int innerFunctorUsageCounter = 0;     //~ Constructors -----------------------------------------------------------     public PrefetchIterator(NextElementFunctor<E> aEnum)     {         innerEnum = aEnum;     }     //~ Methods ----------------------------------------------------------------     /**      * Serves as one contact place to the functor; all must use it and not      * directly the NextElementFunctor.      */     private E getNextElementFromInnerFunctor()     {         innerFunctorUsageCounter++;         E result = this.innerEnum.nextElement();         // if we got here , an exception was not thrown, so at least         // one time a good value returned         flagIsEnumerationStartedEmpty = false;         return result;     }     /**      * 1. Retrieves the saved value or calculates it if it does not exist 2.      * Changes isGetNextLastResultUpToDate to false. (Because it does not save      * the NEXT element now; it saves the current one!)      */     public E nextElement()     {         E result = null;         if (this.isGetNextLastResultUpToDate) {             result = this.getNextLastResult;         } else {             result = getNextElementFromInnerFunctor();         }         this.isGetNextLastResultUpToDate = false;         return result;     }     /**      * If (isGetNextLastResultUpToDate==true) returns true else 1. calculates      * getNext() and saves it 2. sets isGetNextLastResultUpToDate to true.      */     public boolean hasMoreElements()     {         if (endOfEnumerationReached) {             return false;         }         if (isGetNextLastResultUpToDate) {             return true;         } else {             try {                 this.getNextLastResult = getNextElementFromInnerFunctor();                 this.isGetNextLastResultUpToDate = true;                 return true;             } catch (NoSuchElementException noSuchE) {                 endOfEnumerationReached = true;                 return false;             }         } // else     } // method     /**      * Tests whether the enumeration started as an empty one. It does not matter      * if it hasMoreElements() now, only at initialization time. Efficiency: if      * nextElements(), hasMoreElements() were never used, it activates the      * hasMoreElements() once. Else it is immediately(O(1))      */     public boolean isEnumerationStartedEmpty()     {         if (this.innerFunctorUsageCounter == 0) {             if (hasMoreElements()) {                 return false;             } else {                 return true;             }         } else // it is not the first time , so use the saved value                // which was initilaizeed during a call to                // getNextElementFromInnerFunctor         {             return flagIsEnumerationStartedEmpty;         }     }     public boolean hasNext()     {         return this.hasMoreElements();     }     public E next()     {         return this.nextElement();     }     /**      * Always throws UnsupportedOperationException.      */     public void remove()         throws UnsupportedOperationException     {         throw new UnsupportedOperationException();     }     //~ Inner Interfaces -------------------------------------------------------     public interface NextElementFunctor<EE>     {         /**          * You must implement that NoSuchElementException is thrown on          * nextElement() if it is out of bound.          */         public EE nextElement()             throws NoSuchElementException;     } } // End PrefetchIterator.java ///////////////////////// /*   * JGraphT : a free Java graph-theory library  *   *  * Project Info:  http://jgrapht.sourceforge.net/  * Project Creator:  Barak Naveh (http://sourceforge.net/users/barak_naveh)  *  * (C) Copyright 2003-2007, by Barak Naveh and Contributors.  *  * 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 2.1 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, write to the Free Software Foundation,  * Inc.,  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.  */ /* -----------------  * PrefetchIteratorTest.java  * -----------------  * (C) Copyright 2005-2007, by Assaf Lehr and Contributors.  *  * Original Author:  Assaf Lehr  * Contributor(s):   -  *  * $Id: PrefetchIteratorTest.java 568 2007-09-30 00:12:18Z perfecthash $  *  * Changes  * -------  */ package org.jgrapht.util; import java.util.*; import junit.framework.*; public class PrefetchIteratorTest     extends TestCase {     //~ Methods ----------------------------------------------------------------     public void testIteratorInterface()     {         Iterator iterator = new IterateFrom1To99();         for (int i = 1; i < 100; i++) {             assertEquals(true, iterator.hasNext());             assertEquals(i, iterator.next());         }         assertEquals(false, iterator.hasNext());         Exception exceptionThrown = null;         try {             iterator.next();         } catch (Exception e) {             exceptionThrown = e;         }         assertTrue(exceptionThrown instanceof NoSuchElementException);     }     public void testEnumInterface()     {         Enumeration enumuration = new IterateFrom1To99();         for (int i = 1; i < 100; i++) {             assertEquals(true, enumuration.hasMoreElements());             assertEquals(i, enumuration.nextElement());         }         assertEquals(false, enumuration.hasMoreElements());         Exception exceptionThrown = null;         try {             enumuration.nextElement();         } catch (Exception e) {             exceptionThrown = e;         }         assertTrue(exceptionThrown instanceof NoSuchElementException);     }     //~ Inner Classes ----------------------------------------------------------     // This test class supplies enumeration of integer from 1 till 100.     public static class IterateFrom1To99         implements Enumeration,             Iterator     {         private int counter = 0;         private PrefetchIterator nextSupplier;         public IterateFrom1To99()         {             nextSupplier =                 new PrefetchIterator<Integer>(                     new PrefetchIterator.NextElementFunctor<Integer>() {                         public Integer nextElement()                             throws NoSuchElementException                         {                             counter++;                             if (counter >= 100) {                                 throw new NoSuchElementException();                             } else {                                 return new Integer(counter);                             }                         }                     });         }         // forwarding to nextSupplier and return its returned value         public boolean hasMoreElements()         {             return this.nextSupplier.hasMoreElements();         }         // forwarding to nextSupplier and return its returned value         public Object nextElement()         {             return this.nextSupplier.nextElement();         }         public Object next()         {             return this.nextSupplier.next();         }         public boolean hasNext()         {             return this.nextSupplier.hasNext();         }         public void remove()         {             this.nextSupplier.remove();         }     } } // End PrefetchIteratorTest.java