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

com.iodesystems.fn.data.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.data;


import com.iodesystems.fn.logic.Where;
import com.iodesystems.fn.tree.NodeWithParent;

import java.util.*;

public abstract class Iterables {

    public static final Iterator EMPTY_ITERATOR = new Iterator() {
        @Override
        public boolean hasNext() {
            return false;
        }

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

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

    public static final Iterable EMPTY = (Iterable) Iterables::iterator;

    public static  Iterable take(final int count, final Iterable source) {
        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 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 join(final Iterable a, final Iterable b) {
        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 Iterator() {
            final Iterator sourceA = sources.iterator();
            Iterator sourceB = null;

            @Override
            public boolean hasNext() {
                while ((sourceB == null || !sourceB.hasNext()) && sourceA.hasNext()) {
                    sourceB = multiplier.from(sourceA.next()).iterator();
                    if (sourceB.hasNext()) {
                        return true;
                    }
                }
                return sourceB != null && sourceB.hasNext();
            }

            @Override
            public B next() {
                return sourceB.next();
            }

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

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

        return () -> {
            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 Iterables.filter(as, uniques::add);
    }

    public static  Iterable filter(final Iterable source, final Where where) {
        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  int size(Iterable as) {
        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 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 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);
    }

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

    public static  Iterable> parallel(final Iterable as, final Iterable bs) {
        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 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 repeat(final Iterable as, final int times) {
        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, 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) {
        Option last = Option.empty();
        for (A a : as) {
            if (where.is(a)) {
                last = Option.of(a);
            }
        }
        return last;
    }

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

    public static  Iterable> split(final Iterable contents, final Where splitter) {
        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  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 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 () -> {
            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 join(final Iterable nexts) {
        return () -> new Iterator() {
            final Iterator sources = nexts.iterator();
            Iterator current = null;

            @Override
            public boolean hasNext() {
                while ((current == null || !current.hasNext())) {
                    if (!sources.hasNext()) {
                        return false;
                    }
                    current = sources.next().iterator();
                    if (current.hasNext()) {
                        return true;
                    }
                }
                return true;
            }

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

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

    public static  Iterable breadth(final Iterable sources,
                                          final From> multiplier) {
        return () -> new Iterator() {
            final List todo = new LinkedList<>();
            Iterator currentLevel = sources.iterator();
            A nextA;

            @Override
            public boolean hasNext() {
                if (currentLevel.hasNext()) {
                    nextA = currentLevel.next();
                    todo.add(nextA);
                    return true;
                } else if (!todo.isEmpty()) {
                    currentLevel = multiplier.from(todo.remove(0)).iterator();
                    return hasNext();
                } else {
                    return false;
                }
            }

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

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

        };
    }

    public static  Iterable> breadthPaths(final Iterable sources,
                                                     final From> multiplier) {
        return () -> new Iterator>() {
            private final LinkedList> todo = new LinkedList<>();
            private NodeWithParent parent;
            private NodeWithParent current;
            private Iterator currentLevel = sources.iterator();

            @Override
            public boolean hasNext() {
                if (currentLevel.hasNext()) {
                    current = new NodeWithParent<>(parent, currentLevel.next());
                    todo.add(current);
                    return true;
                } else if (!todo.isEmpty()) {
                    parent = todo.removeFirst();
                    currentLevel = multiplier.from(parent.getItem()).iterator();
                    return hasNext();
                } else {
                    return false;
                }
            }

            @Override
            public List next() {
                LinkedList path = new LinkedList<>();
                path.add(current.getItem());
                while (current.getParent() != null) {
                    current = current.getParent();
                    path.addFirst(current.getItem());
                }
                return path;
            }

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

        };
    }

    public static  Iterable depth(final Iterable sources, final From> multiplier) {
        return () -> new Iterator() {
            final Iterator source = sources.iterator();
            final List> descent = new LinkedList<>();
            A nextA;

            @Override
            public boolean hasNext() {
                while (!descent.isEmpty()) {
                    int lastIndex = descent.size() - 1;
                    Iterator top = descent.get(lastIndex);
                    if (!top.hasNext()) {
                        descent.remove(lastIndex);
                    } else {
                        nextA = top.next();
                        descent.add(multiplier.from(nextA).iterator());
                        return true;
                    }
                }

                if (source.hasNext()) {
                    nextA = source.next();
                    descent.add(multiplier.from(nextA).iterator());
                    return true;
                }
                return false;
            }

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

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

    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;
    }

    private static Iterator iterator() {
        return (Iterator) EMPTY_ITERATOR;
    }
}