All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.organicdesign.fp.collections.UnmodIterable Maven / Gradle / Ivy
Go to download
Immutable Clojure collections and a Transformation abstraction for Java 8+, immutably, type-safely, and with good performance. Name will change to "Paguro" in November 2016.
package org.organicdesign.fp.collections;
import org.organicdesign.fp.Option;
import org.organicdesign.fp.function.Function1;
import org.organicdesign.fp.function.Function2;
import org.organicdesign.fp.xform.Transformable;
import org.organicdesign.fp.xform.Xform;
import java.util.Iterator;
/** An unmodifiable Iterable, without any guarantee about order. */
public interface UnmodIterable extends Iterable, Transformable {
// ==================================================== Static ====================================================
static UnmodIterable EMPTY = () -> UnmodIterator.empty();
@SuppressWarnings("unchecked")
static UnmodIterable emptyUnmodIterable() { return (UnmodIterable) EMPTY; }
// /**
// Caution: this is a convenient optimization for immutable data structures and a nightmare waiting to happen to
// mutable ones. Don't go slapping this on immutable wrappers for mutable data. If all the underlying
// data is truly immutable, this allows you to compute the hashCode the first time it is needed, then return
// that same code without re-computing it again. It's the internal version of a memoizer. Also, use this only
// for decent sized collections. If you only have 2 or 3 fields, this isn't buying you anything.
// */
// static Lazy.Int lazyHashCode(UnmodIterable iter) {
// if (iter == null) { throw new IllegalArgumentException("Can't have a null iterable."); }
// return Lazy.Int.of(() -> UnmodIterable.hashCode(iter));
// }
//
// /**
// Caution: this is a convenient optimization for immutable data structures and a nightmare waiting to happen to
// mutable ones. Don't go slapping this on immutable wrappers for mutable data structures. If all the underlying
// data is truly immutable, this allows you to compute a reasonable toString() the first time it is needed, then
// return that same String without re-computing it again. It's the internal version of a memoizer.
// */
// static LazyRef lazyToString(String name, UnmodIterable iter) {
// if (name == null) { throw new IllegalArgumentException("Can't have a null name."); }
// if (iter == null) { throw new IllegalArgumentException("Can't have a null iterable."); }
// return LazyRef.of(() -> UnmodIterable.toString(name, iter));
// }
// /** Lets underlying compareTo method handle comparing nulls to non-null values. */
// static > int compareHelper(E e1, E e2) {
// if (e1 == e2) { return 0; }
// if (e1 == null) {
// //noinspection ConstantConditions
// return -e2.compareTo(e1);
// }
// return e1.compareTo(e2);
// }
//
// /** A default comparator for UnIterables comparable */
// static ,E extends UnmodIterable> Comparator iterableComparator() {
// return new Comparator() {
// @Override
// public int compare(E o1, E o2) {
// if (o1 == null) {
// if (o2 == null) {
// return 0;
// } else {
// //noinspection ConstantConditions
// return -compare(o2, o1);
// }
// }
// UnmodIterator as = o1.iterator();
// UnmodIterator bs = o2.iterator();
// while (as.hasNext() && bs.hasNext()) {
// int ret = compareHelper(as.next(), bs.next());
// if (ret != 0) {
// return ret;
// }
// }
// // If we run out of items in one, the longer one is considered greater, just like ordering words in a
// // dictionary.
// if (as.hasNext()) { return -1; }
// if (bs.hasNext()) { return 1; }
// // All items compare 0 and same number of items - these are sorted the same (and probably equal)
// return 0;
// }
// };
// }
/**
This is correct, but O(n).
It also works regardless of the order of the items because a + b = b + a, even when an overflow occurs.
*/
static int hashCode(Iterable is) {
if (is == null) { throw new IllegalArgumentException("Can't have a null iteratable."); }
// System.out.println("hashCode for: " + is);
int ret = 0;
for (Object t : is) {
if (t != null) {
// System.out.println("\tt: " + t + " hashCode: " + t.hashCode());
ret = ret + t.hashCode();
}
}
return ret;
}
/** Computes a reasonable to-string. */
static String toString(String name, Iterable iterable) {
if (name == null) { throw new IllegalArgumentException("Can't have a null name."); }
if (iterable == null) { throw new IllegalArgumentException("Can't have a null iteratable."); }
StringBuilder sB = new StringBuilder();
sB.append(name).append("(");
int i = 0;
Iterator iter = iterable.iterator();
while (iter.hasNext()) {
Object item = iter.next();
if (i > 0) { sB.append(","); }
if (i > 4) { break; }
sB.append(item);
i++;
}
if (iter.hasNext()) {
sB.append("...");
}
return sB.append(")").toString();
}
// ================================== Inherited from Iterable ==================================
/**
A one-time use, mutable, not-thread-safe way to get each value of the underling collection in
turn. I experimented with various thread-safe alternatives, but the JVM is optimized around
iterators so this is the lowest common denominator of collection iteration, even though
iterators are inherently mutable.
*/
@Override UnmodIterator iterator();
// =============================== Inherited from Transformable ===============================
/** {@inheritDoc} */
@Override default UnmodIterable concat(Iterable extends T> list) {
return Xform.of(this).concat(list);
}
/** {@inheritDoc} */
@Override default UnmodIterable precat(Iterable extends T> list) {
return Xform.of(this).precat(list);
}
/** {@inheritDoc} */
@Override default UnmodIterable drop(long n) {
return Xform.of(this).drop(n);
}
/** {@inheritDoc} */
@Override default B foldLeft(B ident, Function2 reducer) {
return Xform.of(this).foldLeft(ident, reducer);
}
/** {@inheritDoc} */
@Override default B foldLeft(B ident, Function2 reducer,
Function1 super B,Boolean> terminateWhen) {
return Xform.of(this).foldLeft(ident, reducer, terminateWhen);
}
/** {@inheritDoc} */
@Override default UnmodIterable filter(Function1 super T,Boolean> f) {
return Xform.of(this).filter(f);
}
/** {@inheritDoc} */
@Override default UnmodIterable flatMap(Function1 super T,Iterable> f) {
return Xform.of(this).flatMap(f);
}
/** {@inheritDoc} */
@Override default UnmodIterable map(Function1 super T, ? extends B> f) {
return Xform.of(this).map(f);
}
/** {@inheritDoc} */
@Override default UnmodIterable take(long numItems) {
return Xform.of(this).take(numItems);
}
/** {@inheritDoc} */
@Override default UnmodIterable takeWhile(Function1 super T,Boolean> f) {
return Xform.of(this).takeWhile(f);
}
// TODO: This is for temporary Sequence backward-compatibility. Remove once Sequence is deleted.
/**
The first item in this sequence. This was originally called first() but that conflicted with SortedSet.first()
which did not return an Option and threw an exception when the set was empty.
*/
default Option head() {
Iterator iter = iterator();
return iter.hasNext() ? Option.of(iter.next())
: Option.none();
}
// /**
// The rest of this sequnce (all the items after its head). This was originally called rest(), but when I renamed
// first() to head(), I renamed rest() to tail() so that it wouldn't mix metaphors.
// */
// @Deprecated
// default Transformable tail() {
// return Xform.of(this).drop(1);
// }
}