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

net.cassite.f.MListImpl Maven / Gradle / Ivy

package net.cassite.f;

import org.jetbrains.annotations.NotNull;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

class SimpleMutableMListImpl extends ArrayList implements MList {
    SimpleMutableMListImpl() {
    }

    SimpleMutableMListImpl(Collection c) {
        super(c);
    }

    @Override
    @NotNull
    public MList subList(int fromIndex, int toIndex) {
        return new SimpleMutableMListImpl<>(super.subList(fromIndex, toIndex));
    }
}

class ImmutableMListImpl extends AbstractList implements MList, Immutable {
    private final List ls;

    ImmutableMListImpl(List ls) {
        this.ls = new ArrayList<>(ls);
    }

    @Override
    public E get(int index) {
        return ls.get(index);
    }

    @Override
    public int size() {
        return ls.size();
    }

    @Override
    @NotNull
    public MList subList(int fromIndex, int toIndex) {
        return MList.unit(super.subList(fromIndex, toIndex));
    }
}

class LazyMListImpl extends AbstractList implements MList, Immutable {
    private final Iterator ite;
    private final BiConsumer, E> fillElementFunc;
    private final List newList = new ArrayList<>();

    LazyMListImpl(List oldList, BiConsumer, E> fillElementFunc) {
        ite = oldList.iterator();
        this.fillElementFunc = fillElementFunc;
    }

    private void drainUntil(int index) {
        while (ite.hasNext() && newList.size() <= index) {
            E e = ite.next();
            fillElementFunc.accept(newList, e);
        }
    }

    @Override
    public U get(int index) {
        drainUntil(index);
        return newList.get(index);
    }

    @Override
    public int size() {
        while (ite.hasNext()) {
            E e = ite.next();
            fillElementFunc.accept(newList, e);
        }
        return newList.size();
    }

    @Override
    @NotNull
    public MList subList(int fromIndex, int toIndex) {
        return MList.unit(super.subList(fromIndex, toIndex));
    }

    private IndexOutOfBoundsException oob(int index) {
        return new IndexOutOfBoundsException("Index: " + index + ", Size: " + size());
    }

    private class LazyMListIteratorImpl implements ListIterator {
        int curIdx;

        LazyMListIteratorImpl(int curIdx) {
            this.curIdx = curIdx;
        }

        @Override
        public boolean hasNext() {
            if (newList.size() > curIdx) return true;
            drainUntil(curIdx);
            return newList.size() > curIdx;
        }

        @Override
        public U next() {
            if (hasNext()) {
                return newList.get(curIdx++);
            } else {
                throw new NoSuchElementException();
            }
        }

        @Override
        public boolean hasPrevious() {
            return curIdx != 0;
        }

        @Override
        public U previous() {
            if (hasPrevious()) {
                return newList.get(--curIdx);
            } else {
                throw new NoSuchElementException();
            }
        }

        @Override
        public int nextIndex() {
            return curIdx;
        }

        @Override
        public int previousIndex() {
            return curIdx - 1;
        }

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

        @Override
        public void set(U u) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void add(U u) {
            throw new UnsupportedOperationException();
        }
    }

    @Override
    @NotNull
    public Iterator iterator() {
        return listIterator();
    }

    @Override
    @NotNull
    public ListIterator listIterator() {
        return listIterator(0);
    }

    @Override
    @NotNull
    public ListIterator listIterator(int index) {
        if (index < 0) // throw for invalid index
            throw oob(index);
        if (index > newList.size()) {
            drainUntil(index);
            if (index > newList.size())
                throw oob(index); // throw for oob
        }
        return new LazyMListIteratorImpl(index);
    }
}

class TailMListImpl extends AbstractList implements MList, List, Immutable {
    private final List fullList;

    TailMListImpl(List fullList) {
        if (fullList.isEmpty()) {
            throw new IndexOutOfBoundsException("list is empty");
        }
        this.fullList = fullList;
    }

    @Override
    public E get(int index) {
        if (index + 1 >= fullList.size() || index < 0) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size());
        }
        return fullList.get(index + 1);
    }

    @Override
    public int size() {
        return fullList.size() - 1;
    }

    @Override
    @NotNull
    public MList subList(int fromIndex, int toIndex) {
        return MList.unit(super.subList(fromIndex, toIndex));
    }
}

class InitMListImpl extends AbstractList implements MList, List, Immutable {
    private final List fullList;

    InitMListImpl(List fullList) {
        if (fullList.isEmpty()) {
            throw new IndexOutOfBoundsException("list is empty");
        }
        this.fullList = fullList;
    }

    @Override
    public E get(int index) {
        if (index < 0 || index + 1 >= fullList.size()) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size());
        }
        return fullList.get(index);
    }

    @Override
    public int size() {
        return fullList.size() - 1;
    }

    @Override
    @NotNull
    public MList subList(int fromIndex, int toIndex) {
        return MList.unit(super.subList(fromIndex, toIndex));
    }
}

class MListCollector implements Collector, MList> {
    private final Supplier> SUPPLIER = SimpleMutableMListImpl::new;
    private final BiConsumer, E> ACCUMULATOR = List::add;
    private final BinaryOperator> COMBINER = (a, b) -> {
        a.addAll(b);
        return a;
    };
    private final Function, MList> FINISHER = MList::immutable;
    private static final Set C = Collections.unmodifiableSet(Collections.emptySet());
    private static final MListCollector self = new MListCollector();

    @SuppressWarnings("unchecked")
    static  Collector, MList> collector() {
        return self;
    }

    MListCollector() {
    }

    @Override
    public Supplier> supplier() {
        return SUPPLIER;
    }

    @Override
    public BiConsumer, E> accumulator() {
        return ACCUMULATOR;
    }

    @Override
    public BinaryOperator> combiner() {
        return COMBINER;
    }

    @Override
    public Function, MList> finisher() {
        return FINISHER;
    }

    @Override
    public Set characteristics() {
        return C;
    }
}

class MutableMListCollector extends MListCollector {
    private static final Set C = Collections.unmodifiableSet(Collections.singleton(Characteristics.IDENTITY_FINISH));
    private static final MutableMListCollector self = new MutableMListCollector();

    @SuppressWarnings("unchecked")
    static  Collector, MList> collector() {
        return self;
    }

    private MutableMListCollector() {
    }

    @Override
    public Set characteristics() {
        return C;
    }
}