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

org.jhotdraw8.icollection.MutableRedBlackSet Maven / Gradle / Ivy

package org.jhotdraw8.icollection;

import org.jhotdraw8.icollection.facade.ReadOnlySequencedSetFacade;
import org.jhotdraw8.icollection.impl.iteration.FailFastIterator;
import org.jhotdraw8.icollection.impl.iteration.FailFastSpliterator;
import org.jhotdraw8.icollection.impl.iteration.MappedIterator;
import org.jhotdraw8.icollection.impl.redblack.RedBlackTree;
import org.jhotdraw8.icollection.navigable.DescendingNavigableSetView;
import org.jhotdraw8.icollection.navigable.SubsetNavigableSetView;
import org.jhotdraw8.icollection.readonly.ReadOnlyCollection;
import org.jhotdraw8.icollection.readonly.ReadOnlyNavigableSet;
import org.jhotdraw8.icollection.readonly.ReadOnlySequencedSet;
import org.jhotdraw8.icollection.serialization.SortedSetSerializationProxy;
import org.jspecify.annotations.Nullable;

import java.io.Serial;
import java.io.Serializable;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.NavigableSet;
import java.util.SortedSet;
import java.util.Spliterator;
import java.util.stream.Stream;

/**
 * Implements the {@link NavigableSet} interface using a Red-Black tree.
 * 

* References: *

* For a similar design, see 'TreeSet.java' in vavr. The internal data structure of * this class is licensed from vavr. *

*
TreeSet.java. Copyright 2023 (c) vavr. MIT License.
*
github.com
*
* * @param the element type */ public class MutableRedBlackSet extends AbstractSet implements NavigableSet, Serializable, Cloneable, ReadOnlyNavigableSet { @Serial private static final long serialVersionUID = 0L; @SuppressWarnings({"serial", "RedundantSuppression"})// Conditionally serializable final Comparator comparator; /** * The number of times this set has been structurally modified. */ protected transient int modCount; transient RedBlackTree root; /** * Constructs a new, empty set, sorted according to the * specified comparator. * * @param comparator a comparator, if {@code null} the natural ordering of the elements is used */ public MutableRedBlackSet(@Nullable Comparator comparator) { this.comparator = comparator == null ? NaturalComparator.instance() : comparator; this.root = RedBlackTree.empty(); } /** * Constructs a new tree set containing the elements in the specified * collection, sorted according to the specified comparator. * * @param comparator a comparator, if {@code null} the natural ordering of the elements is used * @param c the collection */ @SuppressWarnings("this-escape") public MutableRedBlackSet(@Nullable Comparator comparator, Collection c) { this.comparator = comparator == null ? NaturalComparator.instance() : comparator; this.root = RedBlackTree.empty(); this.addAll(c); } /** * Constructs a new, empty set, sorted according to the * natural ordering of its elements. */ @SuppressWarnings("this-escape") public MutableRedBlackSet() { this.comparator = NaturalComparator.instance(); this.root = RedBlackTree.empty(); } /** * Constructs a new tree set containing the elements in the specified * collection, sorted according to the natural ordering of its * elements. * * @param c the collection */ @SuppressWarnings("this-escape") public MutableRedBlackSet(Iterable c) { this.comparator = NaturalComparator.instance(); this.root = RedBlackTree.empty(); this.addAll(c); } MutableRedBlackSet(@Nullable Comparator comparator, RedBlackTree root) { this.comparator = comparator == null ? NaturalComparator.instance() : comparator; this.root = root; } @Override public boolean add(E e) { RedBlackTree newRoot = root.insert(e, null, comparator); if (newRoot.size() != root.size()) { root = newRoot; modCount++; return true; } return false; } public boolean addAll(Iterable c) { boolean modified = false; for (E e : c) { if (add(e)) { modified = true; } } return modified; } @Nullable @Override public E ceiling(E e) { return root.ceiling(e, comparator).keyOrNull(); } @Override public void clear() { if (!isEmpty()) { modCount++; root = RedBlackTree.empty(); } } @SuppressWarnings("unchecked") @Override public MutableRedBlackSet clone() { try { return (MutableRedBlackSet) super.clone(); } catch (CloneNotSupportedException e) { throw new AssertionError(); } } @Nullable @Override public Comparator comparator() { return comparator == NaturalComparator.instance() ? null : comparator; } @Override @SuppressWarnings("unchecked") public boolean contains(Object o) { return root.contains((E) o, comparator); } @Override public Iterator descendingIterator() { return new FailFastIterator<>( new MappedIterator<>(root.reverseIterator(), Map.Entry::getKey), this::iteratorRemove, this::getModCount ); } @Override public NavigableSet descendingSet() { return new DescendingNavigableSetView<>(this, this::getModCount); } @Override public E first() { return root.min().getKey(); } @Nullable @Override public E floor(E e) { return root.floor(e, comparator).keyOrNull(); } @Override public E getFirst() { return first(); } @Override public E getLast() { return last(); } /** * Returns the current value of the modification counter. * * @return value of modification counter */ protected int getModCount() { return modCount; } @Override public NavigableSet headSet(E toElement, boolean inclusive) { return new SubsetNavigableSetView<>(this, this::getModCount, true, null, true, false, toElement, inclusive, true); } @Override public SortedSet headSet(E toElement) { return headSet(toElement, false); } @Nullable @Override public E higher(E e) { return root.higher(e, comparator).keyOrNull(); } @Override public boolean isEmpty() { return root.isEmpty(); } @Override public Iterator iterator() { return new FailFastIterator<>( new MappedIterator<>(root.iterator(), Map.Entry::getKey), this::iteratorRemove, this::getModCount ); } private void iteratorRemove(E e) { remove(e); } @Override public E last() { return root.max().getKey(); } @Nullable @Override public E lower(E e) { return root.lower(e, comparator).keyOrNull(); } @Nullable @Override public E pollFirst() { E value = root.min().keyOrNull(); root = root.delete(value, comparator); return value; } @Nullable @Override public E pollLast() { E value = root.max().keyOrNull(); root = root.delete(value, comparator); return value; } @Override public ReadOnlySequencedSet readOnlyReversed() { return new ReadOnlySequencedSetFacade<>( this::reverseIterator, this::iterator, this::size, this::contains, this::getLast, this::getFirst, Spliterator.IMMUTABLE); } @SuppressWarnings("unchecked") @Override public boolean remove(Object o) { RedBlackTree newRoot = root.delete((E) o, comparator); if (newRoot.size() != root.size()) { root = newRoot; modCount++; return true; } return false; } Iterator reverseIterator() { return new FailFastIterator<>( new MappedIterator<>(root.reverseIterator(), Map.Entry::getKey), this::iteratorRemove, this::getModCount ); } @Override public int size() { return root.size(); } @Override public Spliterator spliterator() { return new FailFastSpliterator<>( NavigableSet.super.spliterator(), this::getModCount, comparator == NaturalComparator.instance() ? null : comparator); } @Override public Stream stream() { return super.stream(); } @Override public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { return new SubsetNavigableSetView<>(this, this::getModCount, false, fromElement, fromInclusive, false, toElement, toInclusive, true); } @Override public SortedSet subSet(E fromElement, E toElement) { return subSet(fromElement, true, toElement, false); } @Override public NavigableSet tailSet(E fromElement, boolean inclusive) { return new SubsetNavigableSetView<>(this, this::getModCount, false, fromElement, inclusive, true, null, true, true); } @Override public SortedSet tailSet(E fromElement) { return tailSet(fromElement, true); } /** * Returns an immutable copy of this set. * * @return an immutable copy */ public RedBlackSet toImmutable() { return new RedBlackSet<>(comparator, root); } @Override public String toString() { return ReadOnlyCollection.iterableToString(this); } @Serial private Object writeReplace() { return new MutableRedBlackSet.SerializationProxy<>(this); } private static class SerializationProxy extends SortedSetSerializationProxy { @Serial private static final long serialVersionUID = 0L; protected SerializationProxy(SortedSet target) { super(target); } @Serial @Override protected Object readResolve() { return new MutableRedBlackSet<>(deserializedComparator, deserializedElements); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy