package iteratorFun;



public class Test {
	

	public static void main(String [] args) {
		
		// Let us say that you are a huge fan of enhanced
		// for loops in Java 5. You would like to write:
		
		/*
		for (Integer i : First100Integers) {
			System.out.println(i);
		}
		*/

		// Unfortunately, the enhanced for loop needs an Iterable
		// object after the ":". So let us make one.
		
		// First, we need an iterator:
		
		class MyIterator implements java.util.Iterator<Integer> {
	  		   Integer current = 0;
	  		   public boolean hasNext() {
	  			   return current.intValue() <= 100;
	  		   }
	  		   public Integer next() {
	  			   return current++;
	  		   }
	  		   public void remove() {
	  			   throw new java.util.NoSuchElementException();
	  		   }
	  	   };
	  	   
	  	// Now we can use this iterator in an Iterable class:
	  	   
		class MyIterable implements Iterable<Integer> {
			public java.util.Iterator<Integer> iterator() {
	         	   return new MyIterator();
	            }
		}
		
		// This is how to use it:
		
		Iterable<Integer> First100Integers = new MyIterable();

        for (Integer i : First100Integers)
        System.out.println(i);

        // In Java, you can create classes "inline", i.e. whenever you
        // need the class. For example, you can write the class directly
        // after "new". This is called an "anonymous inner class", because
        // you don't even need to give the class a name. You only need
        // to specify what class it extends:
        
        Iterable<Integer> First200Integers 
        = new Iterable<Integer>(){
                public java.util.Iterator<Integer> iterator() {
 	               return 
 	               new java.util.Iterator<Integer>() {
 	     	               Integer current = 0;
 	     	               public boolean hasNext() {
 	     	            	   return current <= 200;
 	     	               }
 	     	               public Integer next() {
 	     	            	   return current++;
 	     	               }
 	     	               public void remove() {
 	     	            	   throw new java.util.NoSuchElementException();
 	     	               }
 	                   };
  	            }
             };

        for (Integer i : First200Integers)
        	System.out.println(i);

        // Now this still is quite lengthy. Instead of specifying the next and
        // hasNext methods, we could specify how to get from one value to the next
        // using an "op" method, and when we are "done". These two operations
        // are passed to a Generator object (which is of course Iterable) along
        // with an initial value:
        
		Generator<Integer> First300Integers = 
			new Generator<Integer>(0,
					               new Operator<Integer>() {public Integer op(Integer i) { return i+1;}},
								   new Terminator<Integer>() {public boolean done(Integer i) { return i>300;}});
		
		for (Integer i : First300Integers)
			System.out.println(i);
		
		// Here are a couple of other uses of our fancy Iterators.
		
		// Iterate through all "long" powers of 2
		// (note the nifty "done" condition: If i overflows, the result is 
		//  the binary number 1000...000 with 63 zeros, which represents -2^63,
		//  which is a negative number)
		
		Generator<Long> AllLongPowersOf2 = 
			new Generator<Long>(new Long(1),
					            new Operator<Long>() {Long op(Long i) { return i*2;}},
								new Terminator<Long>() {boolean done(Long i) { return i<0; }});
		
		for (Long i : AllLongPowersOf2)
			System.out.println(i);
						
		// Here is a method to generate larger and larger strings out of "ab".
		
		Generator<String> SomeStrings = 
			new Generator<String>("",
					            new Operator<String>() {String op(String s) { return s+"ab";}},
								new Terminator<String>() {boolean done(String s) { return s.length()>100; }});
		
		for (String s : SomeStrings)
			System.out.println(s);
	
		// Of course, if you know how ordinary for-loops work, you can achieve the same by writing:
		
		for (String s=""; s.length()<=100; s = s + "xy")
			System.out.println(s);
		
		// but we said that you are huge fans of the for (...:...) loops...
	}
}
