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

org.javimmutable.collections.list.JImmutableArrayList Maven / Gradle / Ivy

///###////////////////////////////////////////////////////////////////////////
//
// Burton Computer Corporation
// http://www.burton-computer.com
//
// Copyright (c) 2017, Burton Computer Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//
//     Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in
//     the documentation and/or other materials provided with the
//     distribution.
//
//     Neither the name of the Burton Computer Corporation nor the names
//     of its contributors may be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package org.javimmutable.collections.list;

import org.javimmutable.collections.Cursor;
import org.javimmutable.collections.Indexed;
import org.javimmutable.collections.InsertableSequence;
import org.javimmutable.collections.JImmutableList;
import org.javimmutable.collections.Sequence;
import org.javimmutable.collections.SplitableIterator;
import org.javimmutable.collections.common.ListAdaptor;
import org.javimmutable.collections.common.StreamConstants;
import org.javimmutable.collections.common.Subindexed;
import org.javimmutable.collections.cursors.Cursors;
import org.javimmutable.collections.sequence.EmptySequenceNode;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.List;

/**
 * JImmutableList implementation using 32-way trees.  The underlying trees, like the JImmutableList,
 * only allow values to be inserted or deleted from the head or tail of the list.
 */
public class JImmutableArrayList
    implements JImmutableList
{
    @SuppressWarnings("unchecked")
    private static final JImmutableArrayList EMPTY = new JImmutableArrayList(EmptyNode.of());

    private final Node root;

    private JImmutableArrayList(Node root)
    {
        this.root = root;
    }

    @SuppressWarnings("unchecked")
    @Nonnull
    public static  JImmutableArrayList of()
    {
        return (JImmutableArrayList)EMPTY;
    }

    @Nonnull
    public static  JImmutableArrayList of(Indexed source,
                                                int offset,
                                                int limit)
    {
        return of(Subindexed.of(source, offset, limit));
    }

    @SuppressWarnings("unchecked")
    @Nonnull
    public static  JImmutableArrayList of(Indexed source)
    {
        final Node root = BranchNode.of(source);
        return root.isEmpty() ? (JImmutableArrayList)EMPTY : new JImmutableArrayList<>(root);
    }

    @Nonnull
    public static  Builder builder()
    {
        return new Builder<>();
    }

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

    @Override
    public T get(int index)
    {
        return root.get(index);
    }

    @Nonnull
    @Override
    public JImmutableArrayList assign(int index,
                                         @Nullable T value)
    {
        return new JImmutableArrayList<>(root.assign(index, value));
    }

    @Nonnull
    @Override
    public JImmutableArrayList insert(@Nullable T value)
    {
        return new JImmutableArrayList<>(root.insertLast(value));
    }

    @Nonnull
    @Override
    public JImmutableList getInsertableSelf()
    {
        return this;
    }

    @Nonnull
    @Override
    public JImmutableArrayList insert(@Nonnull Iterable values)
    {
        Node newRoot = root;
        for (T value : values) {
            newRoot = newRoot.insertLast(value);
        }
        return new JImmutableArrayList<>(newRoot);
    }

    @Nonnull
    @Override
    public JImmutableArrayList insertFirst(@Nullable T value)
    {
        return new JImmutableArrayList<>(root.insertFirst(value));
    }

    @Nonnull
    @Override
    public JImmutableArrayList insertLast(@Nullable T value)
    {
        return new JImmutableArrayList<>(root.insertLast(value));
    }

    @Nonnull
    @Override
    public JImmutableArrayList insertAll(@Nonnull Iterable values)
    {
        return insertAllLast(values);
    }

    @Nonnull
    @Override
    public JImmutableArrayList insertAll(@Nonnull Cursor values)
    {
        return insertAllLast(values);
    }

    @Nonnull
    @Override
    public JImmutableArrayList insertAll(@Nonnull Iterator values)
    {
        return insertAllLast(values);
    }

    @Nonnull
    @Override
    public JImmutableArrayList insertAllFirst(@Nonnull Iterable values)
    {
        return insertAllFirst(values.iterator());
    }

    @Nonnull
    @Override
    public JImmutableArrayList insertAllFirst(@Nonnull Cursor values)
    {
        return insertAllFirst(values.iterator());
    }

    @Nonnull
    @Override
    public JImmutableArrayList insertAllFirst(@Nonnull Iterator values)
    {
        InsertableSequence seq = EmptySequenceNode.of();
        while (values.hasNext()) {
            seq = seq.insert(values.next());
        }
        return insertAllFirstImpl(seq);
    }

    private JImmutableArrayList insertAllFirstImpl(Sequence seq)
    {
        Node newRoot = root;
        while (!seq.isEmpty()) {
            newRoot = newRoot.insertFirst(seq.getHead());
            seq = seq.getTail();
        }
        return new JImmutableArrayList<>(newRoot);
    }

    @Nonnull
    @Override
    public JImmutableArrayList insertAllLast(@Nonnull Iterable values)
    {
        return insertAllLast(values.iterator());
    }

    @Nonnull
    @Override
    public JImmutableArrayList insertAllLast(@Nonnull Cursor values)
    {
        return insertAllLast(values.iterator());
    }

    @Nonnull
    @Override
    public JImmutableArrayList insertAllLast(@Nonnull Iterator values)
    {
        Node newRoot = root;
        while (values.hasNext()) {
            newRoot = newRoot.insertLast(values.next());
        }
        return new JImmutableArrayList<>(newRoot);
    }


    @Nonnull
    @Override
    public JImmutableArrayList deleteFirst()
    {
        if (root.isEmpty()) {
            throw new IndexOutOfBoundsException();
        }
        return new JImmutableArrayList<>(root.deleteFirst());
    }

    @Nonnull
    @Override
    public JImmutableArrayList deleteLast()
    {
        if (root.isEmpty()) {
            throw new IndexOutOfBoundsException();
        }
        return new JImmutableArrayList<>(root.deleteLast());
    }

    @Override
    public boolean isEmpty()
    {
        return root.isEmpty();
    }

    @Nonnull
    @Override
    public JImmutableArrayList deleteAll()
    {
        return of();
    }

    @Nonnull
    @Override
    public List getList()
    {
        return ListAdaptor.of(this);
    }

    @Nonnull
    @Override
    public Cursor cursor()
    {
        return root.cursor();
    }

    @Override
    @Nonnull
    public SplitableIterator iterator()
    {
        return root.iterator();
    }

    @Override
    public int getSpliteratorCharacteristics()
    {
        return StreamConstants.SPLITERATOR_ORDERED;
    }

    @Override
    public void checkInvariants()
    {
        root.checkInvariants();
    }

    @Override
    public boolean equals(Object o)
    {
        return (o == this) || ((o instanceof JImmutableList) && Cursors.areEqual(cursor(), ((JImmutableList)o).cursor()));
    }

    @Override
    public int hashCode()
    {
        return Cursors.computeHashCode(cursor());
    }

    @Override
    public String toString()
    {
        return Cursors.makeString(cursor());
    }

    public static class Builder
        implements JImmutableList.Builder
    {
        private final BranchNode.Builder builder;

        public Builder()
        {
            this.builder = BranchNode.builder();
        }

        @Nonnull
        @Override
        public Builder add(T value)
        {
            builder.add(value);
            return this;
        }

        @Nonnull
        @Override
        public JImmutableArrayList build()
        {
            final Node node = builder.build();
            return node.isEmpty() ? JImmutableArrayList.of() : new JImmutableArrayList<>(node);
        }

        @Nonnull
        @Override
        public Builder add(Cursor source)
        {
            builder.add(source);
            return this;
        }

        @Nonnull
        @Override
        public Builder add(Iterator source)
        {
            builder.add(source);
            return this;
        }

        @Nonnull
        @Override
        public Builder add(Iterable source)
        {
            builder.add(source);
            return this;
        }

        @Nonnull
        @Override
        public  Builder add(K... source)
        {
            builder.add(source);
            return this;
        }

        @Nonnull
        @Override
        public Builder add(Indexed source)
        {
            builder.add(source);
            return this;
        }

        @Nonnull
        @Override
        public Builder add(Indexed source,
                              int offset,
                              int limit)
        {
            builder.add(source, offset, limit);
            return this;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy