![JAR search and dependency download from the Maven repository](/logo.png)
org.jhotdraw8.icollection.MutableVectorList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.jhotdraw8.icollection Show documentation
Show all versions of org.jhotdraw8.icollection Show documentation
JHotDraw8 Immutable Collections
The newest version!
/*
* @(#)SimpleMutableList.java
* Copyright © 2023 The authors and contributors of JHotDraw. MIT License.
*/
package org.jhotdraw8.icollection;
import org.jhotdraw8.icollection.facade.ReadOnlyListFacade;
import org.jhotdraw8.icollection.impl.vector.BitMappedTrie;
import org.jhotdraw8.icollection.readonly.ReadOnlyList;
import org.jhotdraw8.icollection.readonly.ReadOnlySequencedCollection;
import org.jhotdraw8.icollection.sequenced.ReversedListView;
import org.jhotdraw8.icollection.serialization.ListSerializationProxy;
import java.io.Serial;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Spliterator;
import java.util.stream.Stream;
/**
* Implements the {@link List} interface using a bit-mapped trie (Vector).
*
* Features:
*
* - supports up to 231 - 1 elements
* - allows null elements
* - is immutable
* - is thread-safe
* - iterates in the order of the list
*
*
* Performance characteristics:
*
* - addLast: O(log N)
* - set: O(log N)
* - removeAt: O(N)
* - removeFirst,removeLast: O(log N)
* - contains: O(N)
* - toImmutable: O(1)
* - clone: O(1)
* - iterator.next(): O(1)
*
*
* References:
*
* This class has been derived from Vavr Vector.java.
*
* - Vector.java. Copyright 2023 (c) vavr. MIT License.
* - github.com
*
*
* @param the element type
*/
public class MutableVectorList extends AbstractList implements Serializable, ReadOnlyList, List, Cloneable {
@Serial
private static final long serialVersionUID = 0L;
private transient BitMappedTrie root;
/**
* Constructs a new empty list.
*/
public MutableVectorList() {
root = BitMappedTrie.empty();
}
@Override
public void addFirst(E e) {
root = root.prepend(Collections.singleton(e).iterator(), 1);
modCount++;
}
@Override
public void addLast(E e) {
root = root.append(e);
modCount++;
}
@Override
public ReadOnlySequencedCollection readOnlyReversed() {
return new ReadOnlyListFacade<>(
this::size,
index -> get(root.length - 1 - index),
() -> this
);
}
@Override
public List reversed() {
return new ReversedListView<>(this, this::modCount);
}
private int modCount() {
return modCount;
}
@Override
public int size() {
return root.length;
}
@Override
public E get(int index) {
Objects.checkIndex(index, root.length);
return root.get(index);
}
@Override
public E getFirst() {
return ReadOnlyList.super.getFirst();
}
@Override
public E getLast() {
return ReadOnlyList.super.getLast();
}
@Override
public ReadOnlyList readOnlySubList(int fromIndex, int toIndex) {
return new ReadOnlyListFacade<>(() -> toIndex - fromIndex, i -> get(i - fromIndex));
}
@Override
public boolean addAll(int index, Collection extends E> c) {
Objects.checkIndex(index, root.length + 1);
int oldSize = root.length;
VectorList immutable = toImmutable().addAll(index, c);
if (oldSize != immutable.size()) {
root = immutable.trie;
modCount++;
return true;
}
return false;
}
/**
* Adds all elements in the specified collection at the specified position.
*
* @param index the insertion position
* @param c the collection to be added to ths list
* @return {@code true} if this list changed as a result of the call
*/
public boolean addAll(int index, Iterable extends E> c) {
Objects.checkIndex(index, root.length + 1);
int oldSize = root.length;
VectorList immutable = toImmutable().addAll(index, c);
if (oldSize != immutable.size()) {
root = immutable.trie;
modCount++;
return true;
}
return false;
}
/**
* Adds all elements in the specified collection at the end of this list.
*
* @param c the collection to be added to ths list
* @return {@code true} if this list changed as a result of the call
*/
public boolean addAll(Iterable extends E> c) {
return addAll(size(), c);
}
@Override
public boolean removeAll(Collection> c) {
int oldSize = root.length;
VectorList immutable = toImmutable().removeAll(c);
if (oldSize != immutable.size()) {
root = immutable.trie;
modCount++;
return true;
}
return false;
}
@Override
public boolean retainAll(Collection> c) {
int oldSize = root.length;
VectorList immutable = toImmutable().retainAll(c);
if (oldSize != immutable.size()) {
root = immutable.trie;
modCount++;
return true;
}
return false;
}
/**
* Constructs a list containing the elements in the specified iterable.
*
* @param c an iterable
*/
@SuppressWarnings({"unchecked", "this-escape"})
public MutableVectorList(Iterable extends E> c) {
if (c instanceof MutableVectorList>) {
c = ((MutableVectorList extends E>) c).toImmutable();
}
if (c instanceof VectorList>) {
VectorList that = (VectorList) c;
this.root = that.trie;
} else {
this.root = BitMappedTrie.empty();
addAll(0, c);
}
}
public VectorList toImmutable() {
return root.length == 0 ? VectorList.of() : new VectorList<>(root);
}
@Serial
private Object writeReplace() {
return new MutableVectorList.SerializationProxy<>(this);
}
@Override
public boolean add(E e) {
root = root.append(e);
modCount++;
return true;
}
@Override
public E set(int index, E element) {
Objects.checkIndex(index, root.length);
E oldValue = get(index);
root = root.update(index, element);
// According to Guava Tests, this method must not affect modCount!
// modCount++;
return oldValue;
}
@Override
public void add(int index, E element) {
Objects.checkIndex(index, root.length + 1);
if (index == root.length) {
add(element);
} else {
addAll(index, Collections.singleton(element));
}
}
@Override
public E remove(int index) {
Objects.checkIndex(index, root.length);
E removed = get(index);
removeRange(index, index + 1);
return removed;
}
@Override
public Spliterator spliterator() {
return root.spliterator(0, size(), Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED);
}
@Override
public Stream stream() {
return super.stream();
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
root = toImmutable().removeRange(fromIndex, toIndex).trie;
modCount++;
}
@Override
public MutableVectorList clone() {
try {
@SuppressWarnings("unchecked")
MutableVectorList clone = (MutableVectorList) super.clone();
// TODO: copy mutable state here, so the clone can't change the internals of the original
return clone;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
private static class SerializationProxy extends ListSerializationProxy {
@Serial
private static final long serialVersionUID = 0L;
protected SerializationProxy(List target) {
super(target);
}
@Serial
@Override
protected Object readResolve() {
return new MutableVectorList<>(deserializedElements);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy