Created
February 21, 2017 00:21
-
-
Save deyindra/f4ff7ef5f38d2384544d51f8719ad32c to your computer and use it in GitHub Desktop.
Sliding Window Iterator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.idey.algo.util; | |
import java.util.function.Predicate; | |
/** | |
* Assertion Utility class which will Assert statement in case statement is false, | |
* it will throw IllegalArgument Exception. | |
*/ | |
public class AssertJ { | |
private AssertJ(){ | |
throw new AssertionError("Invalid Access"); | |
} | |
/** | |
* | |
* @param object which will satisfy following code | |
* <pre> | |
* new Predicate<T>(){ | |
* public boolean test(T t){ | |
* return t!=null; | |
* } | |
* } | |
* </pre> | |
* @param message Error message in case Predicate fails | |
* @param <T> describe the type of the object | |
* @throws IllegalArgumentException in case passed object is null | |
*/ | |
public static <T> void notNull(T object, String message){ | |
assertTrue(t -> t!=null,object,message); | |
} | |
/** | |
* | |
* @param predicate {@link Predicate} to test the condition | |
* @param object Object which will satisfy the predicate | |
* @param message Error message | |
* @param args Argument to format the message | |
* @param <T> describe the type of the object | |
* @throws IllegalArgumentException throws {@link IllegalArgumentException} in case Asserttion fails | |
*/ | |
public static <T> void assertTrue(Predicate<? super T> predicate, T object, String message, Object... args){ | |
if(!predicate.test(object)){ | |
message = getFinalErrorMessage(message, args); | |
if(message==null){ | |
throw new IllegalArgumentException(); | |
}else{ | |
throw new IllegalArgumentException(message); | |
} | |
} | |
} | |
/** | |
* | |
* @param message Error Message in can be null or empty | |
* @param args Arguments for format the error message | |
* @return Empty Error Message in case this is null or empty or actual error message | |
*/ | |
private static String getFinalErrorMessage(String message, Object... args){ | |
String actualMessage=null; | |
if(message!=null && !("").equals(message.trim())){ | |
message = message.trim(); | |
if(args!=null && args.length>0) { | |
actualMessage = String.format(message, args); | |
}else{ | |
actualMessage = message; | |
} | |
} | |
return actualMessage; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.idey.algo.iterator; | |
import org.idey.algo.util.AssertJ; | |
import java.util.Collections; | |
import java.util.Deque; | |
import java.util.Iterator; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.NoSuchElementException; | |
/** | |
* Sliding/Rolling Window Iterator which return group of object from given {@link Iterator} | |
* <pre> | |
* Iterator<Integer> it = Arrays.asList(1,2,3,4,5,6).iterator(); | |
* SlidingWindowIterator<Integer> slidingWindow = new SlidingWindowIterator<>(it, 2, 3); | |
* while(slidingWindow.hasNext()){ | |
* //print [1,2] [4,5] | |
* System.out.println(slidingWindow.next()); | |
* } | |
* </pre> | |
* @param <T> T object | |
*/ | |
public class SlidingWindowIterator<T> implements Iterator<List<T>>{ | |
//Underlying Iterator | |
private Iterator<T> it; | |
//Size of the window | |
private final int size; | |
//Steps from from where window start | |
private final int step; | |
private final Deque<T> deque; | |
private boolean hasNext; | |
/** | |
* | |
* @param it {@link Iterator} | |
* @param size size of the window | |
* @param step step form where window will start | |
* @throws IllegalArgumentException in case of {@link Iterator} is null | |
* @throws IllegalArgumentException in case size <0 | |
* @throws IllegalArgumentException in case of step <0 | |
*/ | |
public SlidingWindowIterator(Iterator<T> it, int size, int step) { | |
AssertJ.notNull(it, "Iterator can not be null"); | |
AssertJ.assertTrue(i->i>0, size, "size can not be zero or negative"); | |
AssertJ.assertTrue(i->i>0, step, "step can not be zero or negative"); | |
this.it = it; | |
this.size = size; | |
this.step = step; | |
deque = new LinkedList<>(); | |
setAdvance(); | |
} | |
/** | |
* | |
* @return true in case hasNext will return true | |
*/ | |
@Override | |
public boolean hasNext() { | |
return hasNext; | |
} | |
/** | |
* | |
* @return {@link Collections#unmodifiableList(List)} of given size | |
* @throws NoSuchElementException in case there is no more elements | |
*/ | |
@Override | |
public List<T> next() { | |
if(!hasNext){ | |
throw new NoSuchElementException(); | |
} | |
List<T> list = Collections.unmodifiableList(new LinkedList<>(this.deque)); | |
setAdvance(); | |
return list; | |
} | |
/** | |
* @throws UnsupportedOperationException as this operation is not supported | |
*/ | |
@Override | |
public void remove() { | |
throw new UnsupportedOperationException("Invalid Operation"); | |
} | |
private void setAdvance(){ | |
hasNext=false; | |
//Check first if the iterator is empty of not | |
if(it.hasNext()){ | |
//if deque is not empty | |
if(!deque.isEmpty()){ | |
//window size is greater than step | |
if(size>step){ | |
//remove all the element from the begining | |
// based on given step and if deque is not empty | |
for(int count=0;!deque.isEmpty() && count<step; count++){ | |
deque.poll(); | |
} | |
//if size less than or equal to step | |
}else if(size<=step){ | |
//clear dqueue | |
deque.clear(); | |
//Move the pointer in the iterator based on difference of step and size | |
for(int count=0;it.hasNext() && count<step-size; count++){ | |
it.next(); | |
} | |
} | |
} | |
//finally populate deque | |
while (it.hasNext() && deque.size()<size){ | |
deque.offer(it.next()); | |
} | |
if(!deque.isEmpty()) { | |
hasNext = true; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment