mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
checkstyle
This commit is contained in:
@@ -34,7 +34,6 @@ import forge.quest.gui.main.QuestChallenge;
|
|||||||
import forge.quest.gui.main.QuestEvent;
|
import forge.quest.gui.main.QuestEvent;
|
||||||
import forge.view.swing.WinLoseModeHandler;
|
import forge.view.swing.WinLoseModeHandler;
|
||||||
|
|
||||||
// TODO: Auto-generated Javadoc
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* QuestWinLoseHandler.
|
* QuestWinLoseHandler.
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class WinLoseModeHandler {
|
|||||||
* Action performed when "quit" button is pressed in default win/lose UI.
|
* Action performed when "quit" button is pressed in default win/lose UI.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final void actionOnQuit() {
|
public void actionOnQuit() {
|
||||||
if (System.getenv("NG2") != null) {
|
if (System.getenv("NG2") != null) {
|
||||||
if (System.getenv("NG2").equalsIgnoreCase("true")) {
|
if (System.getenv("NG2").equalsIgnoreCase("true")) {
|
||||||
String[] argz = {};
|
String[] argz = {};
|
||||||
@@ -69,7 +69,7 @@ public class WinLoseModeHandler {
|
|||||||
* with other game modes.
|
* with other game modes.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final void startNextRound() {
|
public void startNextRound() {
|
||||||
AllZone.getGameAction().newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0]);
|
AllZone.getGameAction().newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ public class WinLoseModeHandler {
|
|||||||
*
|
*
|
||||||
* @return true, if successful
|
* @return true, if successful
|
||||||
*/
|
*/
|
||||||
public final boolean populateCustomPanel() {
|
public boolean populateCustomPanel() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,5 +4,12 @@ package net.slightlymagic.braids.util;
|
|||||||
* Like Runnable, but it can throw any Exception.
|
* Like Runnable, but it can throw any Exception.
|
||||||
*/
|
*/
|
||||||
public interface ClumsyRunnable {
|
public interface ClumsyRunnable {
|
||||||
public void run() throws Exception;
|
|
||||||
|
/**
|
||||||
|
* Run.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* the exception
|
||||||
|
*/
|
||||||
|
void run() throws Exception;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,56 +5,66 @@ import java.util.Iterator;
|
|||||||
/**
|
/**
|
||||||
* Acts as both immutable Iterator and Iterable; remove method always throws
|
* Acts as both immutable Iterator and Iterable; remove method always throws
|
||||||
* exception.
|
* exception.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* the generic type
|
||||||
*/
|
*/
|
||||||
public class ImmutableIterableFrom<T> implements Iterable<T>, Iterator<T> {
|
public class ImmutableIterableFrom<T> implements Iterable<T>, Iterator<T> {
|
||||||
private Iterator<T> iterator;
|
private Iterator<T> iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap an iterable so that it cannot be changed via
|
* Wrap an iterable so that it cannot be changed via the remove method.
|
||||||
* the remove method.
|
*
|
||||||
*
|
* @param iterable
|
||||||
* @param iterable the iterable to wrap
|
* the iterable to wrap
|
||||||
*/
|
*/
|
||||||
public ImmutableIterableFrom(Iterable<T> iterable) {
|
public ImmutableIterableFrom(final Iterable<T> iterable) {
|
||||||
this.iterator = iterable.iterator();
|
this.iterator = iterable.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap an iterator so that its container cannot be changed via
|
* Wrap an iterator so that its container cannot be changed via the remove
|
||||||
* the remove method.
|
* method.
|
||||||
*
|
*
|
||||||
* @param iterator the iterator to wrap
|
* @param iterator
|
||||||
*/
|
* the iterator to wrap
|
||||||
public ImmutableIterableFrom(Iterator<T> iterator) {
|
*/
|
||||||
this.iterator = iterator;
|
public ImmutableIterableFrom(final Iterator<T> iterator) {
|
||||||
}
|
this.iterator = iterator;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class acts as both an Iterable and an Iterator.
|
* This class acts as both an Iterable and an Iterator.
|
||||||
*/
|
*
|
||||||
public Iterator<T> iterator() {
|
* @return the iterator
|
||||||
return this;
|
*/
|
||||||
}
|
public final Iterator<T> iterator() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns hasNext from the wrapped [object's] iterator.
|
* Returns hasNext from the wrapped [object's] iterator.
|
||||||
*/
|
*
|
||||||
public boolean hasNext() {
|
* @return true, if successful
|
||||||
return iterator.hasNext();
|
*/
|
||||||
}
|
public final boolean hasNext() {
|
||||||
|
return iterator.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns next from the wrapped [object's] iterator.
|
* Returns next from the wrapped [object's] iterator.
|
||||||
*/
|
*
|
||||||
public T next() {
|
* @return the t
|
||||||
return iterator.next();
|
*/
|
||||||
}
|
public final T next() {
|
||||||
|
return iterator.next();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Never succeeeds.
|
* Never succeeeds.
|
||||||
* @throws UnsupportedOperationException always.
|
*
|
||||||
*/
|
*/
|
||||||
public void remove() {
|
public final void remove() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ public class NotImplementedError extends RuntimeException {
|
|||||||
/**
|
/**
|
||||||
* Indicates what has not been implemented.
|
* Indicates what has not been implemented.
|
||||||
*
|
*
|
||||||
* @param message indicates what exactly has not been implemented.
|
* @param message
|
||||||
* May include information about future plans to implement the described
|
* indicates what exactly has not been implemented. May include
|
||||||
* section of code.
|
* information about future plans to implement the described
|
||||||
|
* section of code.
|
||||||
*/
|
*/
|
||||||
public NotImplementedError(final String message) {
|
public NotImplementedError(final String message) {
|
||||||
super(message);
|
super(message);
|
||||||
@@ -34,7 +35,8 @@ public class NotImplementedError extends RuntimeException {
|
|||||||
/**
|
/**
|
||||||
* Like the no-arg constructor, but with a cause parameter.
|
* Like the no-arg constructor, but with a cause parameter.
|
||||||
*
|
*
|
||||||
* @param cause the exception that caused this one to be thrown
|
* @param cause
|
||||||
|
* the exception that caused this one to be thrown
|
||||||
*
|
*
|
||||||
* @see #NotImplementedError()
|
* @see #NotImplementedError()
|
||||||
*/
|
*/
|
||||||
@@ -45,11 +47,13 @@ public class NotImplementedError extends RuntimeException {
|
|||||||
/**
|
/**
|
||||||
* Like the String constructor, but with a cause parameter.
|
* Like the String constructor, but with a cause parameter.
|
||||||
*
|
*
|
||||||
* @param message indicates what exactly has not been implemented.
|
* @param message
|
||||||
* May include information about future plans to implement the described
|
* indicates what exactly has not been implemented. May include
|
||||||
* section of code.
|
* information about future plans to implement the described
|
||||||
|
* section of code.
|
||||||
*
|
*
|
||||||
* @param cause the exception that caused this one to be thrown
|
* @param cause
|
||||||
|
* the exception that caused this one to be thrown
|
||||||
*
|
*
|
||||||
* @see #NotImplementedError(String)
|
* @see #NotImplementedError(String)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,12 +19,13 @@ public final class UtilFunctions {
|
|||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws a NullPointerException if param is null.
|
* Throws a NullPointerException if param is null.
|
||||||
*
|
*
|
||||||
* @param paramName the name of the parameter; may be null
|
* @param paramName
|
||||||
* @param param the parameter to test
|
* the name of the parameter; may be null
|
||||||
|
* @param param
|
||||||
|
* the parameter to test
|
||||||
*/
|
*/
|
||||||
public static void checkNotNull(final String paramName, final Object param) {
|
public static void checkNotNull(final String paramName, final Object param) {
|
||||||
if (param != null) {
|
if (param != null) {
|
||||||
@@ -34,10 +35,16 @@ public final class UtilFunctions {
|
|||||||
NullPointerException exn = null;
|
NullPointerException exn = null;
|
||||||
|
|
||||||
if (paramName == null) {
|
if (paramName == null) {
|
||||||
exn = new NullPointerException(); // NOPMD by Braids on 8/18/11 11:19 PM
|
exn = new NullPointerException(); // NOPMD by Braids on 8/18/11
|
||||||
}
|
// 11:19 PM
|
||||||
else {
|
} else {
|
||||||
exn = new NullPointerException(paramName + " must not be null"); // NOPMD by Braids on 8/18/11 11:19 PM
|
exn = new NullPointerException(paramName + " must not be null"); // NOPMD
|
||||||
|
// by
|
||||||
|
// Braids
|
||||||
|
// on
|
||||||
|
// 8/18/11
|
||||||
|
// 11:19
|
||||||
|
// PM
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doctor the exception to appear to come from the caller.
|
// Doctor the exception to appear to come from the caller.
|
||||||
@@ -48,42 +55,51 @@ public final class UtilFunctions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke the given Runnable in an Event Dispatch Thread and wait for it
|
* Invoke the given Runnable in an Event Dispatch Thread and wait for it to
|
||||||
* to finish; but <B>try to use SwingUtilities.invokeLater instead whenever
|
* finish; but <B>try to use SwingUtilities.invokeLater instead whenever
|
||||||
* feasible.</B>
|
* feasible.</B>
|
||||||
*
|
*
|
||||||
* Exceptions generated by SwingUtilities.invokeAndWait (if used), are
|
* Exceptions generated by SwingUtilities.invokeAndWait (if used), are
|
||||||
* rethrown as RuntimeExceptions.
|
* rethrown as RuntimeExceptions.
|
||||||
*
|
*
|
||||||
|
* @param proc
|
||||||
|
* the Runnable to run
|
||||||
* @see javax.swing.SwingUtilities#invokeLater(Runnable)
|
* @see javax.swing.SwingUtilities#invokeLater(Runnable)
|
||||||
*
|
|
||||||
* @param proc the Runnable to run
|
|
||||||
*/
|
*/
|
||||||
public static void invokeInEventDispatchThreadAndWait(final Runnable proc) { // NOPMD by Braids on 8/18/11 11:19 PM
|
public static void invokeInEventDispatchThreadAndWait(final Runnable proc) { // NOPMD
|
||||||
|
// by
|
||||||
|
// Braids
|
||||||
|
// on
|
||||||
|
// 8/18/11
|
||||||
|
// 11:19
|
||||||
|
// PM
|
||||||
if (SwingUtilities.isEventDispatchThread()) {
|
if (SwingUtilities.isEventDispatchThread()) {
|
||||||
// Just run in the current thread.
|
// Just run in the current thread.
|
||||||
proc.run();
|
proc.run();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
try {
|
try {
|
||||||
SwingUtilities.invokeAndWait(proc);
|
SwingUtilities.invokeAndWait(proc);
|
||||||
} catch (InterruptedException exn) {
|
} catch (InterruptedException exn) {
|
||||||
throw new RuntimeException(exn); // NOPMD by Braids on 8/18/11 11:19 PM
|
throw new RuntimeException(exn); // NOPMD by Braids on 8/18/11
|
||||||
|
// 11:19 PM
|
||||||
} catch (InvocationTargetException exn) {
|
} catch (InvocationTargetException exn) {
|
||||||
throw new RuntimeException(exn); // NOPMD by Braids on 8/18/11 11:19 PM
|
throw new RuntimeException(exn); // NOPMD by Braids on 8/18/11
|
||||||
|
// 11:19 PM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an array from the (rest of) an iterator's output;
|
* Create an array from the (rest of) an iterator's output; this function is
|
||||||
* this function is horribly inefficient.
|
* horribly inefficient.
|
||||||
*
|
*
|
||||||
* Please, only use it on small iterators.
|
* Please, only use it on small iterators.
|
||||||
*
|
*
|
||||||
* @param <T> (inferred automatically)
|
* @param <T>
|
||||||
|
* (inferred automatically)
|
||||||
*
|
*
|
||||||
* @param iter the iterator to traverse
|
* @param iter
|
||||||
|
* the iterator to traverse
|
||||||
*
|
*
|
||||||
* @return an array of (the rest of) the iterator's values
|
* @return an array of (the rest of) the iterator's values
|
||||||
*/
|
*/
|
||||||
@@ -101,27 +117,28 @@ public final class UtilFunctions {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the rightmost portion of an array, Python-style.
|
* Returns the rightmost portion of an array, Python-style.
|
||||||
*
|
*
|
||||||
* @param <T> (inferred automatically)
|
* @param <T>
|
||||||
|
* (inferred automatically)
|
||||||
*
|
*
|
||||||
* @param dstArray the array in which to place new items
|
* @param dstArray
|
||||||
|
* the array in which to place new items
|
||||||
*
|
*
|
||||||
* @param srcArray the array to copy (shallowly)
|
* @param srcArray
|
||||||
|
* the array to copy (shallowly)
|
||||||
*
|
*
|
||||||
* @param startIndexIn if positive, the index (from the left) at which to
|
* @param startIndexIn
|
||||||
* start copying; if negative, we treat this as the index from the right.
|
* if positive, the index (from the left) at which to start
|
||||||
* For example, calling this with startIndex = -2 returns the last two
|
* copying; if negative, we treat this as the index from the
|
||||||
* items in the array, if it has that many.
|
* right. For example, calling this with startIndex = -2 returns
|
||||||
|
* the last two items in the array, if it has that many.
|
||||||
*
|
*
|
||||||
* @return a shallow copy of array starting at startIndex; this may return
|
* @return a shallow copy of array starting at startIndex; this may return
|
||||||
* an empty array if the startIndex is out of bounds.
|
* an empty array if the startIndex is out of bounds.
|
||||||
*/
|
*/
|
||||||
public static <T extends Object> T[] slice(final T[] dstArray, final T[] srcArray,
|
public static <T extends Object> T[] slice(final T[] dstArray, final T[] srcArray, final int startIndexIn) {
|
||||||
final int startIndexIn)
|
|
||||||
{
|
|
||||||
int startIndex = startIndexIn;
|
int startIndex = startIndexIn;
|
||||||
if (startIndex < 0) {
|
if (startIndex < 0) {
|
||||||
startIndex = srcArray.length + startIndex;
|
startIndex = srcArray.length + startIndex;
|
||||||
@@ -131,55 +148,51 @@ public final class UtilFunctions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dstArray == null) {
|
if (dstArray == null) {
|
||||||
throw new NullPointerException(); // NOPMD by Braids on 8/18/11 11:19 PM
|
throw new NullPointerException(); // NOPMD by Braids on 8/18/11
|
||||||
|
// 11:19 PM
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srcArray == null) {
|
if (srcArray == null) {
|
||||||
throw new NullPointerException(); // NOPMD by Braids on 8/18/11 11:19 PM
|
throw new NullPointerException(); // NOPMD by Braids on 8/18/11
|
||||||
|
// 11:19 PM
|
||||||
}
|
}
|
||||||
|
|
||||||
final int resultLength = getSliceLength(srcArray, startIndex);
|
final int resultLength = getSliceLength(srcArray, startIndex);
|
||||||
|
|
||||||
if (dstArray.length != resultLength) {
|
if (dstArray.length != resultLength) {
|
||||||
throw new ArrayIndexOutOfBoundsException(
|
throw new ArrayIndexOutOfBoundsException("First parameter must have length " + resultLength
|
||||||
"First parameter must have length " + resultLength
|
|
||||||
+ ", but length is " + dstArray.length + ".");
|
+ ", but length is " + dstArray.length + ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
int srcIx = startIndex;
|
int srcIx = startIndex;
|
||||||
|
|
||||||
for (int dstIx = 0;
|
for (int dstIx = 0; dstIx < resultLength && srcIx < srcArray.length; dstIx++, srcIx++) {
|
||||||
dstIx < resultLength && srcIx < srcArray.length;
|
|
||||||
dstIx++, srcIx++)
|
|
||||||
{
|
|
||||||
dstArray[dstIx] = srcArray[srcIx];
|
dstArray[dstIx] = srcArray[srcIx];
|
||||||
}
|
}
|
||||||
|
|
||||||
return dstArray;
|
return dstArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a slice's length in preparation for taking a slice.
|
* Get a slice's length in preparation for taking a slice.
|
||||||
*
|
*
|
||||||
* I do not like the fact that I have to use this function, but
|
* I do not like the fact that I have to use this function, but Java left me
|
||||||
* Java left me with little choice.
|
* with little choice.
|
||||||
*
|
|
||||||
* @see #slice(Object[], Object[], int)
|
|
||||||
*
|
|
||||||
* @param <T> (inferred automatically)
|
|
||||||
*
|
|
||||||
* @param srcArray the array that would be copied (shallowly)
|
|
||||||
*
|
|
||||||
* @param startIndexIn if positive, the index (from the left) at which
|
|
||||||
* copying would start; if negative, we treat this as the index from the
|
|
||||||
* right. For example, calling this with startIndex = -2 computes the
|
|
||||||
* length if slice would return the last two items in the array, if it has
|
|
||||||
* that many.
|
|
||||||
*
|
*
|
||||||
|
* @param <T>
|
||||||
|
* (inferred automatically)
|
||||||
|
* @param srcArray
|
||||||
|
* the array that would be copied (shallowly)
|
||||||
|
* @param startIndexIn
|
||||||
|
* if positive, the index (from the left) at which copying would
|
||||||
|
* start; if negative, we treat this as the index from the right.
|
||||||
|
* For example, calling this with startIndex = -2 computes the
|
||||||
|
* length if slice would return the last two items in the array,
|
||||||
|
* if it has that many.
|
||||||
* @return the length of the array that would result from calling
|
* @return the length of the array that would result from calling
|
||||||
* slice(Object[], Object[], int) with the given srcArray and
|
* slice(Object[], Object[], int) with the given srcArray and
|
||||||
* startIndex.
|
* startIndex.
|
||||||
|
* @see #slice(Object[], Object[], int)
|
||||||
*/
|
*/
|
||||||
public static <T> int getSliceLength(final T[] srcArray, final int startIndexIn) {
|
public static <T> int getSliceLength(final T[] srcArray, final int startIndexIn) {
|
||||||
int startIndex = startIndexIn;
|
int startIndex = startIndexIn;
|
||||||
@@ -195,34 +208,43 @@ public final class UtilFunctions {
|
|||||||
return resultLength;
|
return resultLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the boilerplate null and isinstance check for an equals method.
|
* Handles the boilerplate null and isinstance check for an equals method.
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* public boolean equals(Object obj) {
|
* public boolean equals(Object obj) {
|
||||||
* MyClassName that = checkNullOrNotInstance(this, obj);
|
* MyClassName that = checkNullOrNotInstance(this, obj);
|
||||||
* if (that == null) {
|
* if (that == null) {
|
||||||
* return false;
|
* return false;
|
||||||
* }
|
* }
|
||||||
* //...
|
* // ...
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param <T> (inferred automatically)
|
* @param <T>
|
||||||
|
* (inferred automatically)
|
||||||
*
|
*
|
||||||
* @param goodInstance a non-null instance of type T; looks neater than
|
* @param goodInstance
|
||||||
* passing in goodInstance.getClass()
|
* a non-null instance of type T; looks neater than passing in
|
||||||
|
* goodInstance.getClass()
|
||||||
*
|
*
|
||||||
* @param obj the object to test
|
* @param obj
|
||||||
|
* the object to test
|
||||||
*
|
*
|
||||||
* @return null if obj is null or not an instance of goodInstance's class;
|
* @return null if obj is null or not an instance of goodInstance's class;
|
||||||
* otherwise, we return obj cast to goodInstance's type
|
* otherwise, we return obj cast to goodInstance's type
|
||||||
*/
|
*/
|
||||||
public static <T> T checkNullOrNotInstance(final T goodInstance, final Object obj) {
|
public static <T> T checkNullOrNotInstance(final T goodInstance, final Object obj) {
|
||||||
if (goodInstance == null) {
|
if (goodInstance == null) {
|
||||||
throw new NullPointerException("first parameter must not be null"); // NOPMD by Braids on 8/18/11 11:19 PM
|
throw new NullPointerException("first parameter must not be null"); // NOPMD
|
||||||
|
// by
|
||||||
|
// Braids
|
||||||
|
// on
|
||||||
|
// 8/18/11
|
||||||
|
// 11:19
|
||||||
|
// PM
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -246,12 +268,11 @@ public final class UtilFunctions {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Safely converts an object to a String.
|
* Safely converts an object to a String.
|
||||||
*
|
*
|
||||||
* @param obj to convert; may be null
|
* @param obj
|
||||||
|
* to convert; may be null
|
||||||
*
|
*
|
||||||
* @return "null" if obj is null, obj.toString() otherwise
|
* @return "null" if obj is null, obj.toString() otherwise
|
||||||
*/
|
*/
|
||||||
@@ -260,8 +281,7 @@ public final class UtilFunctions {
|
|||||||
|
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
result = "null";
|
result = "null";
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
result = obj.toString();
|
result = obj.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,28 +295,28 @@ public final class UtilFunctions {
|
|||||||
* determine equality.
|
* determine equality.
|
||||||
*
|
*
|
||||||
* Advantages over HashSet: This consumes no unnecessary heap-memory, nor
|
* Advantages over HashSet: This consumes no unnecessary heap-memory, nor
|
||||||
* does it require objects to implement hashCode. It is OK if
|
* does it require objects to implement hashCode. It is OK if (o1.equals(o2)
|
||||||
* (o1.equals(o2) does not imply o1.hashCode() == o2.hashCode()).
|
* does not imply o1.hashCode() == o2.hashCode()).
|
||||||
*
|
*
|
||||||
* Advantages over TreeSet: This does not require a comparator.
|
* Advantages over TreeSet: This does not require a comparator.
|
||||||
*
|
*
|
||||||
* Disadvantages over HashSet and TreeSet: This runs in O(n*n) time.
|
* Disadvantages over HashSet and TreeSet: This runs in O(n*n) time.
|
||||||
*
|
*
|
||||||
* @param <T> (inferred automatically)
|
* @param <T>
|
||||||
|
* (inferred automatically)
|
||||||
*
|
*
|
||||||
* @param list the list to modify; this is fastest with ArrayList.
|
* @param list
|
||||||
|
* the list to modify; this is fastest with ArrayList.
|
||||||
*/
|
*/
|
||||||
public static <T> void smartRemoveDuplicatesAndNulls(final List<T> list) {
|
public static <T> void smartRemoveDuplicatesAndNulls(final List<T> list) {
|
||||||
// Get rid of pesky leading nulls.
|
// Get rid of pesky leading nulls.
|
||||||
smartRemoveDuplicatesAndNullsHelper(list, 0, null);
|
smartRemoveDuplicatesAndNullsHelper(list, 0, null);
|
||||||
|
|
||||||
for (int earlierIx = 0; earlierIx < list.size(); earlierIx++) {
|
for (int earlierIx = 0; earlierIx < list.size(); earlierIx++) {
|
||||||
for (int laterIx = earlierIx + 1; laterIx < list.size(); laterIx++)
|
for (int laterIx = earlierIx + 1; laterIx < list.size(); laterIx++) {
|
||||||
{
|
|
||||||
final T itemAtEarlierIx = list.get(earlierIx);
|
final T itemAtEarlierIx = list.get(earlierIx);
|
||||||
|
|
||||||
smartRemoveDuplicatesAndNullsHelper(list, laterIx,
|
smartRemoveDuplicatesAndNullsHelper(list, laterIx, itemAtEarlierIx);
|
||||||
itemAtEarlierIx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -304,28 +324,25 @@ public final class UtilFunctions {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method for smartRemoveDuplicatesAndNulls that is subject to
|
* Helper method for smartRemoveDuplicatesAndNulls that is subject to
|
||||||
* change; if you call this directly, you do so at your own risk!
|
* change; if you call this directly, you do so at your own risk!.
|
||||||
*
|
*
|
||||||
* @param <T> (inferred automatically)
|
* @param <T>
|
||||||
*
|
* (inferred automatically)
|
||||||
* @param list the list to modify; if all items from startIx to the end
|
* @param list
|
||||||
* are either null or equal to objSeenPreviously, then we truncate the
|
* the list to modify; if all items from startIx to the end are
|
||||||
* list just before startIx.
|
* either null or equal to objSeenPreviously, then we truncate
|
||||||
*
|
* the list just before startIx.
|
||||||
* @param startIx the index to examine; we only move items within the range
|
* @param startIx
|
||||||
* of [startIx, list.size()-1].
|
* the index to examine; we only move items within the range of
|
||||||
*
|
* [startIx, list.size()-1].
|
||||||
* @param objSeenPreviously the object with which to compare list[startIx];
|
* @param objSeenPreviously
|
||||||
* may be null.
|
* the object with which to compare list[startIx]; may be null.
|
||||||
*/
|
*/
|
||||||
public static <T> void smartRemoveDuplicatesAndNullsHelper(
|
public static <T> void smartRemoveDuplicatesAndNullsHelper(final List<T> list, final int startIx,
|
||||||
final List<T> list, final int startIx, final T objSeenPreviously)
|
final T objSeenPreviously) {
|
||||||
{
|
|
||||||
while (startIx < list.size()
|
while (startIx < list.size()
|
||||||
&& (list.get(startIx) == null
|
&& (list.get(startIx) == null || list.get(startIx) == objSeenPreviously || list.get(startIx).equals(
|
||||||
|| list.get(startIx) == objSeenPreviously
|
objSeenPreviously))) {
|
||||||
|| list.get(startIx).equals(objSeenPreviously)))
|
|
||||||
{
|
|
||||||
final int lastItemIx = list.size() - 1;
|
final int lastItemIx = list.size() - 1;
|
||||||
|
|
||||||
// Overwrite the item at laterIx with the one at the end,
|
// Overwrite the item at laterIx with the one at the end,
|
||||||
|
|||||||
@@ -1,61 +1,69 @@
|
|||||||
/** Licensed under both the GPL and the Apache 2.0 License. */
|
/** Licensed under both the GPL and the Apache 2.0 License. */
|
||||||
package net.slightlymagic.braids.util.generator;
|
package net.slightlymagic.braids.util.generator;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
import com.google.code.jyield.Generator;
|
import com.google.code.jyield.Generator;
|
||||||
import com.google.code.jyield.Yieldable;
|
import com.google.code.jyield.Yieldable;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a generator over all of the non-directories residing in a given
|
* This is a generator over all of the non-directories residing in a given
|
||||||
* starting directory and all subdirectories of it that do NOT start with a
|
* starting directory and all subdirectories of it that do NOT start with a dot;
|
||||||
* dot; this prevents the code from descending into .svn directories.
|
* this prevents the code from descending into .svn directories.
|
||||||
*
|
*
|
||||||
* For documentation on Java-Yield and its generators, see
|
* For documentation on Java-Yield and its generators, see
|
||||||
* {@link com.google.code.jyield.Generator}
|
* {@link com.google.code.jyield.Generator}
|
||||||
*/
|
*/
|
||||||
public class FindNonDirectoriesSkipDotDirectoriesGenerator implements Generator<File> {
|
public class FindNonDirectoriesSkipDotDirectoriesGenerator implements Generator<File> {
|
||||||
private File startDir;
|
private File startDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a generator at a given starting directory.
|
* Create a generator at a given starting directory.
|
||||||
*
|
*
|
||||||
* One can invoke this generator more than once by calling its generate
|
* One can invoke this generator more than once by calling its generate
|
||||||
* method.
|
* method.
|
||||||
*
|
*
|
||||||
* @param startDir the directory to start in; we ignore this directory's
|
* @param startDir
|
||||||
* name, so if it starts with a dot, we treat it as if it didn't.
|
* the directory to start in; we ignore this directory's name, so
|
||||||
*/
|
* if it starts with a dot, we treat it as if it didn't.
|
||||||
public FindNonDirectoriesSkipDotDirectoriesGenerator(File startDir) {
|
*/
|
||||||
this.startDir = startDir;
|
public FindNonDirectoriesSkipDotDirectoriesGenerator(final File startDir) {
|
||||||
}
|
this.startDir = startDir;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard generate method.
|
* Standard generate method.
|
||||||
*
|
*
|
||||||
* <p>Yields results to the given Yieldable. Convert Generator instances to
|
* <p>
|
||||||
* Iterables with YieldUtils.toIterable.</p>
|
* Yields results to the given Yieldable. Convert Generator instances to
|
||||||
*
|
* Iterables with YieldUtils.toIterable.
|
||||||
* See {@link com.google.code.jyield.YieldUtils#toIterable(com.google.code.jyield.Generator)}
|
* </p>
|
||||||
*/
|
*
|
||||||
public void generate(Yieldable<File> yy) {
|
* See
|
||||||
String[] list = startDir.list();
|
* {@link com.google.code.jyield.YieldUtils#toIterable(com.google.code.jyield.Generator)}
|
||||||
|
*
|
||||||
|
* @param yy
|
||||||
|
* the yy
|
||||||
|
*/
|
||||||
|
public final void generate(final Yieldable<File> yy) {
|
||||||
|
String[] list = startDir.list();
|
||||||
|
|
||||||
for (String filename : list) {
|
for (String filename : list) {
|
||||||
File entry = new File(startDir, filename);
|
File entry = new File(startDir, filename);
|
||||||
|
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
if (!filename.startsWith(".")) {
|
if (!filename.startsWith(".")) {
|
||||||
FindNonDirectoriesSkipDotDirectoriesGenerator child = new FindNonDirectoriesSkipDotDirectoriesGenerator(entry);
|
FindNonDirectoriesSkipDotDirectoriesGenerator child =
|
||||||
child.generate(yy);
|
new FindNonDirectoriesSkipDotDirectoriesGenerator(
|
||||||
child = null;
|
entry);
|
||||||
}
|
child.generate(yy);
|
||||||
// else do nothing, because it's a dot directory
|
child = null;
|
||||||
}
|
}
|
||||||
else {
|
// else do nothing, because it's a dot directory
|
||||||
// Use this instead of a return statement.
|
} else {
|
||||||
yy.yield(entry);
|
// Use this instead of a return statement.
|
||||||
}
|
yy.yield(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,33 +4,43 @@ import com.google.code.jyield.Generator;
|
|||||||
import com.google.code.jyield.Yieldable;
|
import com.google.code.jyield.Yieldable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Generator from an array; generators are a handy
|
* Creates a Generator from an array; generators are a handy substitute for
|
||||||
* substitute for passing around and creating temporary
|
* passing around and creating temporary lists, collections, and arrays.
|
||||||
* lists, collections, and arrays.
|
|
||||||
*
|
*
|
||||||
* {@link com.google.code.jyield.Generator}
|
* @param <T>
|
||||||
|
* the generic type {@link com.google.code.jyield.Generator}
|
||||||
*/
|
*/
|
||||||
public class GeneratorFromArray<T> implements Generator<T> {
|
public class GeneratorFromArray<T> implements Generator<T> {
|
||||||
private T[] array;
|
private T[] array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Generator from an array
|
* Create a Generator from an array.
|
||||||
*
|
*
|
||||||
* @param array from which to generate items
|
* @param array
|
||||||
*/
|
* from which to generate items
|
||||||
public GeneratorFromArray(T[] array) {
|
*/
|
||||||
this.array = array;
|
public GeneratorFromArray(final T[] array) {
|
||||||
}
|
this.array = array;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
/*
|
||||||
/**
|
* (non-Javadoc)
|
||||||
* Submits all of the array's elements to the yieldable.
|
*
|
||||||
*
|
* @see
|
||||||
* @param yy the yieldable which receives the elements
|
* com.google.code.jyield.Generator#generate(com.google.code.jyield.Yieldable
|
||||||
*/
|
* )
|
||||||
public void generate(Yieldable<T> yy) {
|
*/
|
||||||
for (T item : array) {
|
|
||||||
yy.yield(item);
|
/**
|
||||||
}
|
* Submits all of the array's elements to the yieldable.
|
||||||
}
|
*
|
||||||
|
* @param yy
|
||||||
|
* the yieldable which receives the elements
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final void generate(final Yieldable<T> yy) {
|
||||||
|
for (T item : array) {
|
||||||
|
yy.yield(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,204 +1,215 @@
|
|||||||
/** Licensed under both the GPL and the Apache 2.0 License. */
|
/** Licensed under both the GPL and the Apache 2.0 License. */
|
||||||
package net.slightlymagic.braids.util.generator;
|
package net.slightlymagic.braids.util.generator;
|
||||||
|
|
||||||
import com.google.code.jyield.Generator;
|
|
||||||
import com.google.code.jyield.YieldUtils;
|
|
||||||
import com.google.code.jyield.Yieldable;
|
|
||||||
import net.slightlymagic.braids.util.lambda.Lambda1;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import net.slightlymagic.braids.util.lambda.Lambda1;
|
||||||
|
|
||||||
|
import com.google.code.jyield.Generator;
|
||||||
|
import com.google.code.jyield.YieldUtils;
|
||||||
|
import com.google.code.jyield.Yieldable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For documentation on Java-Yield and its generators, see
|
* For documentation on Java-Yield and its generators, see.
|
||||||
|
*
|
||||||
* {@link com.google.code.jyield.Generator}.
|
* {@link com.google.code.jyield.Generator}.
|
||||||
*/
|
*/
|
||||||
public final class GeneratorFunctions {
|
public final class GeneratorFunctions {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do not instantiate.
|
* Do not instantiate.
|
||||||
*/
|
*/
|
||||||
private GeneratorFunctions() {
|
private GeneratorFunctions() {
|
||||||
;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Estimate the number of items in this generator by traversing all of its
|
* Estimate the number of items in this generator by traversing all of its
|
||||||
* elements.
|
* elements.
|
||||||
*
|
*
|
||||||
* Note this only works on a generator that can be reinstantiated once it
|
* Note this only works on a generator that can be reinstantiated once it
|
||||||
* has been traversed. This is only an estimate, because a generator's size
|
* has been traversed. This is only an estimate, because a generator's size
|
||||||
* may vary been traversals. This is especially true if the generator
|
* may vary been traversals. This is especially true if the generator relies
|
||||||
* relies on external resources, such as a file system.
|
* on external resources, such as a file system.
|
||||||
*
|
*
|
||||||
* If you call this on an infinite generator, this method will never
|
* If you call this on an infinite generator, this method will never return.
|
||||||
* return.
|
*
|
||||||
*
|
* @param <T>
|
||||||
* @return the estimated number of items provided by this generator
|
* the generic type
|
||||||
*/
|
* @param gen
|
||||||
public static <T> long estimateSize(Generator<T> gen) {
|
* the gen
|
||||||
long result = 0;
|
* @return the estimated number of items provided by this generator
|
||||||
for (@SuppressWarnings("unused") T ignored : YieldUtils.toIterable(gen))
|
*/
|
||||||
{
|
public static <T> long estimateSize(final Generator<T> gen) {
|
||||||
result++;
|
long result = 0;
|
||||||
}
|
for (@SuppressWarnings("unused")
|
||||||
|
T ignored : YieldUtils.toIterable(gen))
|
||||||
|
{
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Highly efficient means of filtering a long or infinite sequence.
|
* Highly efficient means of filtering a long or infinite sequence.
|
||||||
*
|
*
|
||||||
* @param <T> any type
|
* @param <T>
|
||||||
*
|
* any type
|
||||||
* @param predicate a Lambda (function) whose apply method takes an object
|
*
|
||||||
* of type <T> and returns a Boolean. If it returns false or null, the
|
* @param predicate
|
||||||
* item from the inputGenerator is not yielded by this Generator;
|
* a Lambda (function) whose apply method takes an object of type
|
||||||
* if predicate.apply returns true, then this Generator <i>does</i>
|
* <T> and returns a Boolean. If it returns false or null, the
|
||||||
* yield the value.
|
* item from the inputGenerator is not yielded by this Generator;
|
||||||
*
|
* if predicate.apply returns true, then this Generator
|
||||||
* @param inputGenerator the sequence upon which we operate
|
* <i>does</i> yield the value.
|
||||||
*
|
*
|
||||||
* @return a generator which produces a subset <= the inputGenerator
|
* @param inputGenerator
|
||||||
*/
|
* the sequence upon which we operate
|
||||||
public static <T> Generator<T> filterGenerator(
|
*
|
||||||
final Lambda1<Boolean,T> predicate, final Generator<T> inputGenerator)
|
* @return a generator which produces a subset <= the inputGenerator
|
||||||
{
|
*/
|
||||||
Generator<T> result = new Generator<T>() {
|
public static <T> Generator<T> filterGenerator(final Lambda1<Boolean, T> predicate,
|
||||||
|
final Generator<T> inputGenerator)
|
||||||
|
{
|
||||||
|
Generator<T> result = new Generator<T>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(final Yieldable<T> outputYield) {
|
public void generate(final Yieldable<T> outputYield) {
|
||||||
|
|
||||||
Yieldable<T> inputYield = new Yieldable<T>() {
|
Yieldable<T> inputYield = new Yieldable<T>() {
|
||||||
Boolean pResult;
|
Boolean pResult;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void yield(T input) {
|
public void yield(final T input) {
|
||||||
pResult = predicate.apply(input);
|
pResult = predicate.apply(input);
|
||||||
if (pResult != null && pResult) {
|
if (pResult != null && pResult) {
|
||||||
outputYield.yield(input);
|
outputYield.yield(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inputGenerator.generate(inputYield);
|
inputGenerator.generate(inputYield);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Highly efficient means of applying a transform to a long or infinite
|
* Highly efficient means of applying a transform to a long or infinite
|
||||||
* sequence.
|
* sequence.
|
||||||
*
|
*
|
||||||
* @param <T> any type
|
* @param <T>
|
||||||
*
|
* any type
|
||||||
* @param transform a Lambda (function) whose apply method takes an object
|
*
|
||||||
* of type <T> and returns an object of the same type. This transforms
|
* @param transform
|
||||||
* the values from the inputGenerator into this Generator.
|
* a Lambda (function) whose apply method takes an object of type
|
||||||
*
|
* <T> and returns an object of the same type. This transforms
|
||||||
* @param inputGenerator the sequence upon which we operate
|
* the values from the inputGenerator into this Generator.
|
||||||
*
|
*
|
||||||
* @return a generator that yields transform.apply's return value for
|
* @param inputGenerator
|
||||||
* each item in the inputGenerator
|
* the sequence upon which we operate
|
||||||
*/
|
*
|
||||||
public static <T> Generator<T> transformGenerator(
|
* @return a generator that yields transform.apply's return value for each
|
||||||
final Lambda1<T,T> transform, final Generator<T> inputGenerator)
|
* item in the inputGenerator
|
||||||
{
|
*/
|
||||||
Generator<T> result = new Generator<T>() {
|
public static <T> Generator<T> transformGenerator(final Lambda1<T, T> transform, final Generator<T> inputGenerator)
|
||||||
|
{
|
||||||
|
Generator<T> result = new Generator<T>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(final Yieldable<T> outputYield) {
|
public void generate(final Yieldable<T> outputYield) {
|
||||||
|
|
||||||
Yieldable<T> inputYield = new Yieldable<T>() {
|
Yieldable<T> inputYield = new Yieldable<T>() {
|
||||||
@Override
|
@Override
|
||||||
public void yield(T input) {
|
public void yield(final T input) {
|
||||||
outputYield.yield(transform.apply(input));
|
outputYield.yield(transform.apply(input));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inputGenerator.generate(inputYield);
|
inputGenerator.generate(inputYield);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces a generator to be completely evaluated into a temporary data
|
* Forces a generator to be completely evaluated into a temporary data
|
||||||
* structure, then returns the generator over that same structure.
|
* structure, then returns the generator over that same structure.
|
||||||
*
|
*
|
||||||
* This effectively returns the same Generator, but it is a faster one.
|
* This effectively returns the same Generator, but it is a faster one. This
|
||||||
* This trades away heap space for reduced CPU intensity. This is
|
* trades away heap space for reduced CPU intensity. This is particuarly
|
||||||
* particuarly helpful if you know that a Generator is going to be
|
* helpful if you know that a Generator is going to be totally evaluated
|
||||||
* totally evaluated more than once in the near future.
|
* more than once in the near future.
|
||||||
*
|
*
|
||||||
* @param <T> inferred automatically
|
* @param <T>
|
||||||
*
|
* inferred automatically
|
||||||
* @param unevaluated a Generator of T instances
|
*
|
||||||
*
|
* @param unevaluated
|
||||||
* @return the equivalent Generator, except that the result's generate
|
* a Generator of T instances
|
||||||
* method can be invoked multiple times for fast results.
|
*
|
||||||
*/
|
* @return the equivalent Generator, except that the result's generate
|
||||||
public static <T> Generator<T> solidify(Generator<T> unevaluated) {
|
* method can be invoked multiple times for fast results.
|
||||||
|
*/
|
||||||
|
public static <T> Generator<T> solidify(final Generator<T> unevaluated) {
|
||||||
ArrayList<T> solidTmp = YieldUtils.toArrayList(unevaluated);
|
ArrayList<T> solidTmp = YieldUtils.toArrayList(unevaluated);
|
||||||
solidTmp.trimToSize();
|
solidTmp.trimToSize();
|
||||||
return YieldUtils.toGenerator(solidTmp);
|
return YieldUtils.toGenerator(solidTmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select an item at random from a Generator; this causes the entire
|
* Select an item at random from a Generator; this causes the entire
|
||||||
* Generator to be evaluated once, but only once.
|
* Generator to be evaluated once, but only once.
|
||||||
*
|
*
|
||||||
* @param generator
|
* @param <T>
|
||||||
* the generator from which to select a random item
|
* the generic type
|
||||||
*
|
* @param generator
|
||||||
* @return an item chosen at random from the generator; this may be null, if
|
* the generator from which to select a random item
|
||||||
* the generator contains null items.
|
* @return an item chosen at random from the generator; this may be null, if
|
||||||
*
|
* the generator contains null items.
|
||||||
* @throws NoSuchElementException
|
* @throws NoSuchElementException
|
||||||
* if the generator has no contents
|
* if the generator has no contents
|
||||||
*/
|
*/
|
||||||
public static <T> T selectRandom(Generator<T> generator)
|
public static <T> T selectRandom(final Generator<T> generator) throws NoSuchElementException
|
||||||
throws NoSuchElementException
|
{
|
||||||
{
|
/*
|
||||||
/*
|
* This algorithm requires some explanation. Each time we encounter a
|
||||||
* This algorithm requires some explanation. Each time we encounter a
|
* new item from the generator, we determine via random chance if the
|
||||||
* new item from the generator, we determine via random chance if the
|
* item is the one we select. At the end of each iteration, we have a
|
||||||
* item is the one we select. At the end of each iteration, we have a
|
* candidate, and we have a count of the number of items encountered so
|
||||||
* candidate, and we have a count of the number of items encountered so
|
* far. Each iteration has a 1/n chance of replacing the candidate with
|
||||||
* far. Each iteration has a 1/n chance of replacing the candidate with
|
* the current item, where n is the number of items encountered so far.
|
||||||
* the current item, where n is the number of items encountered so far.
|
* This allows us to randomly select an item from the generated contents
|
||||||
* This allows us to randomly select an item from the generated contents
|
* with an equal distribution; and we don't have to count the number of
|
||||||
* with an equal distribution; and we don't have to count the number of
|
* items first!
|
||||||
* items first!
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
T candidate = null;
|
T candidate = null;
|
||||||
|
|
||||||
for (T item : YieldUtils.toIterable(generator)) {
|
for (T item : YieldUtils.toIterable(generator)) {
|
||||||
n++;
|
n++;
|
||||||
int rand = (int) (Math.random() * n);
|
int rand = (int) (Math.random() * n);
|
||||||
// At this point, 0 <= rand < n.
|
// At this point, 0 <= rand < n.
|
||||||
rand++; // Now, 1 <= rand <= n.
|
rand++; // Now, 1 <= rand <= n.
|
||||||
|
|
||||||
if (rand == 1) {
|
if (rand == 1) {
|
||||||
// We rolled a 1 on an n-sided die. We have a new candidate!
|
// We rolled a 1 on an n-sided die. We have a new candidate!
|
||||||
// Note that on the first iteration, this always happens,
|
// Note that on the first iteration, this always happens,
|
||||||
// because n = 1.
|
// because n = 1.
|
||||||
candidate = item;
|
candidate = item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
// There were no items in the generator!
|
// There were no items in the generator!
|
||||||
throw new NoSuchElementException("generator is empty");
|
throw new NoSuchElementException("generator is empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user