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 = new Iterable() {
        @Override
        @SuppressWarnings("unchecked")
        public Iterator iterator() {
            return (Iterator) EMPTY_ITERATOR;
        }
    };

    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 join(final Iterable a, final Iterable b) {
        return new Iterable() {
            public Iterator iterator() {
                return new Iterator() {
                    final Iterator next = b.iterator();
                    Iterator current = a.iterator();
                    final Iterator first = current;

                    public boolean hasNext() {
                        if (current.hasNext()) {
                            return true;
                        } else if (current == first) {
                            current = next;
                            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();
                    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 new Iterable() {
            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 Iterables.filter(as, new Where() {
            @Override
            public boolean is(A a) {
                return uniques.add(a);
            }
        });
    }

    public static  Iterable filter(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  int size(Iterable as) {
        int i = 0;
        for (A ignored : as) {
            i += 1;
        }
        return i;
    }

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

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

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

                    @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 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 repeat(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, 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 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  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 next = null;

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

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

                    @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 join(final Iterable nexts) {
        return new Iterable() {
            @Override
            public Iterator iterator() {
                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 Iterable() {
            @Override
            public Iterator iterator() {
                return new Iterator() {
                    final List todo = new LinkedList();
                    Iterator currentLevel = sources.iterator();
                    A next;

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

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

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

                };
            }
        };
    }

    public static  Iterable> breadthPaths(final Iterable sources,
                                                     final From> multiplier) {
        return new Iterable>() {
            @Override
            public Iterator> iterator() {
                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 Iterable() {
            @Override
            public Iterator iterator() {
                return new Iterator() {
                    final Iterator source = sources.iterator();
                    final List> descent = new LinkedList>();
                    A next;

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

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

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

                    @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();
                    }
                };
            }
        };
    }
}