All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.iodesystems.fn.aspects.Iterables Maven / Gradle / Ivy

Go to download

Fn is a lazy Java Library that helps utilize some rudimentary functional concepts with more nounular objects

There is a newer version: 3.0.4
Show newest version
package com.iodesystems.fn.aspects;

import com.iodesystems.fn.data.Combine;
import com.iodesystems.fn.data.From;
import com.iodesystems.fn.data.Generator;
import com.iodesystems.fn.data.Option;
import com.iodesystems.fn.data.Pair;
import com.iodesystems.fn.logic.Where;
import com.iodesystems.fn.thread.Invokable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class Iterables {

  public static final Iterator EMPTY_ITERATOR =
      new Iterator() {

        @Override
        public boolean hasNext() {
          return false;
        }

        @Override
        public Object next() {
          return null;
        }
      };

  public static final Iterable EMPTY =
      new Iterable() {
        @Override
        public Iterator iterator() {
          return EMPTY_ITERATOR;
        }
      };

  public static  Option first(Iterable as) {
    Iterator iterator = as.iterator();
    if (iterator.hasNext()) {
      return Option.empty();
    } else {
      return Option.of(iterator.next());
    }
  }

  public static  Option last(Iterable as) {
    A last = null;
    for (A a : as) {
      last = a;
    }
    return Option.of(last);
  }

  public static  Iterable take(final int count, final Iterable source) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          final Iterator parent = source.iterator();
          int soFar = 0;

          @Override
          public boolean hasNext() {
            return soFar++ < count && parent.hasNext();
          }

          @Override
          public A next() {
            return parent.next();
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  Iterable drop(final int count, final Iterable source) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          final Iterator parent = source.iterator();
          int skip = 0;

          @Override
          public boolean hasNext() {
            while (skip++ < count && parent.hasNext()) {
              parent.next();
            }
            return parent.hasNext();
          }

          @Override
          public A next() {
            return parent.next();
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  Iterable concat(final Iterable a, final Iterable b) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          final Iterator nextB = b.iterator();
          Iterator current = a.iterator();
          final Iterator first = current;

          public boolean hasNext() {
            if (current.hasNext()) {
              return true;
            } else if (current == first) {
              current = nextB;
              return current.hasNext();
            }
            return false;
          }

          public A next() {
            return current.next();
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  Iterable> multiply(
      final Iterable sources, final From> multiplier) {
    return new Iterable>() {
      @Override
      public Iterator> iterator() {
        return new Iterator>() {
          final Iterator sourceA = sources.iterator();
          Iterable next = null;

          @Override
          public boolean hasNext() {
            if (sourceA.hasNext()) {
              next = multiplier.from(sourceA.next());
              return true;
            }
            return false;
          }

          @Override
          public Iterable next() {
            return next;
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  Iterable convert(final Iterable source, final From from) {

    return new Iterable() {
      @Override
      public Iterator iterator() {
        final Iterator sourceItems = source.iterator();
        return new Iterator() {
          public boolean hasNext() {
            return sourceItems.hasNext();
          }

          public B next() {
            return from.from(sourceItems.next());
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  Iterable unique(Iterable as) {
    final Set uniques = new HashSet<>();
    return where(as, uniques::add);
  }

  public static  Iterable where(final Iterable source, final Class cls) {
    //noinspection unchecked
    return (Iterable) where(source, (Where) Wheres.is(cls));
  }

  public static  Iterable where(final Iterable source, final Where where) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          final Iterator parent = source.iterator();
          A current;

          @Override
          public boolean hasNext() {
            while (parent.hasNext()) {
              current = parent.next();
              if (where.is(current)) {
                return true;
              }
            }
            return false;
          }

          @Override
          public A next() {
            return current;
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  void consume(Iterable as) {
    //noinspection StatementWithEmptyBody
    for (A ignored : as) {}
  }

  public static  int size(Iterable as) {
    if (as instanceof Collection) {
      return ((Collection) as).size();
    } else {
      int i = 0;
      for (A ignored : as) {
        i += 1;
      }
      return i;
    }
  }

  public static  Enumeration toEnumeration(Iterable contents) {
    final Iterator iterator = contents.iterator();
    return new Enumeration() {

      @Override
      public boolean hasMoreElements() {
        return iterator.hasNext();
      }

      @Override
      public A nextElement() {
        return iterator.next();
      }
    };
  }

  public static  List toList(Iterable contents) {
    if (contents instanceof List) {
      return (List) contents;
    }
    List list = new ArrayList<>();
    for (A content : contents) {
      list.add(content);
    }
    return list;
  }

  public static  Iterable of(final Generator generator) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          A nextA;

          @Override
          public boolean hasNext() {
            nextA = generator.next();
            return nextA != null;
          }

          @Override
          public A next() {
            return nextA;
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  Iterable of(final Enumeration source) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          @Override
          public boolean hasNext() {
            return source.hasMoreElements();
          }

          @Override
          public A next() {
            return source.nextElement();
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  Iterable of(A source) {
    return Collections.singletonList(source);
  }

  @SafeVarargs
  public static  Iterable of(A... source) {
    return Arrays.asList(source);
  }

  public static  Iterable> parallel(final Iterable as, final Iterable bs) {
    return new Iterable>() {
      @Override
      public Iterator> iterator() {
        return new Iterator>() {
          final Iterator sourceA = as.iterator();
          final Iterator sourceB = bs.iterator();

          @Override
          public boolean hasNext() {
            return sourceA.hasNext() && sourceB.hasNext();
          }

          @Override
          public Pair next() {
            return new Pair<>(sourceA.next(), sourceB.next());
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  Iterable repeat(final A a, final int times) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          int count = 0;

          @Override
          public boolean hasNext() {
            return times == -1 || ++count <= times;
          }

          @Override
          public A next() {
            return a;
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  Iterable loop(final Iterable as, final int times) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          int count = 0;
          Iterator source = as.iterator();

          @Override
          public boolean hasNext() {
            if (source.hasNext()) {
              return true;
            } else if (times == -1 || ++count < times) {
              source = as.iterator();
              return source.hasNext();
            }
            return false;
          }

          @Override
          public A next() {
            return source.next();
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  @SuppressWarnings("unchecked")
  public static  Iterable empty() {
    return (Iterable) EMPTY;
  }

  public static  Option first(Iterable as, Class cls) {
    return first(where(as, cls));
  }

  public static  Option first(Iterable as, Where where) {
    for (A a : as) {
      if (where.is(a)) {
        return Option.of(a);
      }
    }
    return Option.empty();
  }

  public static  Option last(Iterable as, Where where) {
    A last = null;
    for (A a : as) {
      if (where.is(a)) {
        last = a;
      }
    }
    return Option.of(last);
  }

  public static  Iterable glue(Iterable current, A joiner, Iterable next) {
    return concat(concat(current, of(joiner)), next);
  }

  public static  Iterable> split(
      final Iterable contents, final Where splitter) {
    return new Iterable>() {
      @Override
      public Iterator> iterator() {
        return new Iterator>() {
          final Iterator source = contents.iterator();
          List segment;
          boolean isTrailingEnd;

          @Override
          public boolean hasNext() {
            segment = new ArrayList<>();
            while (source.hasNext()) {
              A next = source.next();
              if (splitter.is(next)) {
                isTrailingEnd = true;
                return true;
              } else {
                segment.add(next);
              }
            }

            if (isTrailingEnd) {
              isTrailingEnd = false;
              return true;
            } else {
              return !segment.isEmpty();
            }
          }

          @Override
          public Iterable next() {
            return segment;
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static > Iterable flatten(Iterable contents) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          final Iterator iterator = contents.iterator();
          Iterator next;

          @Override
          public boolean hasNext() {
            if (next != null && next.hasNext()) {
              return true;
            } else {
              next = null;
            }
            while (iterator.hasNext()) {
              next = this.iterator.next().iterator();
              if (next.hasNext()) {
                return true;
              }
            }
            return false;
          }

          @Override
          public A next() {
            return next.next();
          }
        };
      }
    };
  }

  public static  B combine(Iterable contents, B initial, Combine condenser) {
    B condensate = initial;
    for (A content : contents) {
      condensate = condenser.from(content, condensate);
    }
    return condensate;
  }

  public static  Iterable takeWhile(final Iterable contents, final Where where) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          final Iterator source = contents.iterator();
          A nextA = null;

          @Override
          public boolean hasNext() {
            if (source.hasNext()) {
              nextA = source.next();
              return where.is(nextA);
            }
            return false;
          }

          @Override
          public A next() {
            return nextA;
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  Iterable dropWhile(final Iterable contents, final Where where) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        final Iterator source = contents.iterator();

        return new Iterator() {
          A first = null;
          boolean yieldedFirst = false;

          @Override
          public boolean hasNext() {
            if (first == null) {
              while (source.hasNext()) {
                first = source.next();
                if (!where.is(first)) {
                  return true;
                }
              }
            }
            return source.hasNext();
          }

          @Override
          public A next() {
            if (!yieldedFirst) {
              yieldedFirst = true;
              return first;
            }
            return source.next();
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  Set toSet(Iterable contents) {
    if (contents instanceof Set) {
      return (Set) contents;
    }
    Set set = new HashSet<>();
    for (A content : contents) {
      set.add(content);
    }
    return set;
  }

  public static  Iterable loop(final Iterable contents) {
    return new Iterable() {
      Iterator iterator = contents.iterator();
      boolean first = true;

      @Override
      public Iterator iterator() {
        return new Iterator() {
          @Override
          public boolean hasNext() {
            if (first) {
              first = false;
              return iterator.hasNext();
            } else if (!iterator.hasNext()) {
              iterator = contents.iterator();
            }
            return true;
          }

          @Override
          public A next() {
            return iterator.next();
          }

          @Override
          public void remove() {
            throw new IllegalStateException();
          }
        };
      }
    };
  }

  public static  A[] toArray(Iterable contents, A[] preallocated) {
    int i = 0;
    for (A content : contents) {
      preallocated[i++] = content;
    }
    return preallocated;
  }

  public static  Iterable withNext(
      final Iterable contents, final From nextFromCurrent) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          A current = null;
          final Iterator original = contents.iterator();

          @Override
          public boolean hasNext() {
            if (current != null) {
              current = nextFromCurrent.from(current);
              if (current != null) {
                return true;
              }
            }
            return original.hasNext();
          }

          @Override
          public A next() {
            if (current != null) {
              return current;
            } else {
              return current = original.next();
            }
          }
        };
      }
    };
  }

  public static  Iterable each(final Iterable contents, final Invokable handler) {
    return new Iterable() {
      @Override
      public Iterator iterator() {
        return new Iterator() {
          final Iterator parent = contents.iterator();

          @Override
          public boolean hasNext() {
            return parent.hasNext();
          }

          @Override
          public A next() {
            A next = parent.next();
            handler.invoke(next);
            return next;
          }
        };
      }
    };
  }
}