//============================================================================== // // Copyright (c) 2016- // Authors: // * Joachim Klein (TU Dresden) // //------------------------------------------------------------------------------ // // This file is part of PRISM. // // PRISM is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // PRISM is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with PRISM; if not, write to the Free Software Foundation, // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //============================================================================== package common; import java.util.BitSet; import java.util.Spliterator; import java.util.Spliterators; import java.util.PrimitiveIterator.OfInt; import java.util.stream.IntStream; import java.util.stream.StreamSupport; import common.IterableBitSet; /** * Interface for an ordered set of integers that allows efficient * (1) iteration (normal and reversed order) * and (2) efficient tests of set membership. *
* Provides static helpers for wrapping a BitSet or a singleton value. */ public interface IntSet extends Iterable { /** Return a PrimitiveIterator.OfInt iterator for iteration, normal order */ public OfInt iterator(); /** Return a PrimitiveIterator.OfInt iterator for iteration, reversed order */ public OfInt reversedIterator(); /** Return the cardinality (number of elements) for this set */ public int cardinality(); /** Return true if {@code index} is a member of this set */ public boolean contains(int index); /** * Return true if {@code index} is a member of this set * (convenience method to ease migration from use of BitSet). *

* Default implementation: Calls contains(index). */ public default boolean get(int index) { return contains(index); } /** * Return true if this set contains the {@code other} * set. *

* Default implementation: * Tests via contains for all elements of other. */ public default boolean contains(IntSet other) { return other.stream().allMatch(this::contains); } /** * Return true if this set contains the {@code other} * set. *

* Default implementation: * Uses contains(IntSet other). */ public default boolean contains(BitSet other) { return contains(asIntSet(other)); } /** * Produce an IntStream for this set. *

* Default implementation: * Wrap iterator() into an intStream. */ public default IntStream stream() { return StreamSupport.intStream( () -> Spliterators.spliterator( iterator(), cardinality(), Spliterator.DISTINCT), Spliterator.SIZED | Spliterator.DISTINCT, false); } /** * Wrapper class for obtaining an IntSet from a BitSet. *

* Note: The BitSet should not be modified as long as the * derived IntSet is in use. */ public static class IntSetFromBitSet implements IntSet { /** The wrapped BitSet */ private BitSet bs; /** The cardinality of the underlying BitSet (cached, -1 = not yet computed */ int cardinality = -1; /** Constructor */ public IntSetFromBitSet(BitSet bs) { this.bs = bs; } @Override public OfInt iterator() { return IterableBitSet.getSetBits(bs).iterator(); } @Override public OfInt reversedIterator() { return IterableBitSet.getSetBitsReversed(bs).iterator(); } @Override public IntStream stream() { return bs.stream(); } @Override public int cardinality() { // not yet computed? if (cardinality == -1) cardinality = bs.cardinality(); return cardinality; } @Override public boolean contains(int index) { return bs.get(index); } }; /** Convenience class for simulating a singleton set */ public static class SingletonIntSet implements IntSet { /** The single member of this singleton set */ private int singleMember; /** * Constructor. * @param singleMember the single member of this set */ public SingletonIntSet(int singleMember) { this.singleMember = singleMember; } @Override public OfInt iterator() { return new OfInt() { boolean done = false; @Override public boolean hasNext() { return !done; } @Override public int nextInt() { done = true; return singleMember; } }; } @Override public OfInt reversedIterator() { // iteration order does not matter for singleton set return iterator(); } @Override public int cardinality() { return 1; } @Override public boolean contains(int index) { return index == singleMember; } } /** * Static constructor for obtaining an IntSet from a BitSet *

* Note: The BitSet should not be modified as long as the derived IntSet is in use. * @param bs The underlying BitSet */ public static IntSet asIntSet(BitSet bs) { return new IntSetFromBitSet(bs); } /** * Static constructor for obtaining an IntSet for a singleton set. * @param singleMember The single member of the singleton set */ public static IntSet asIntSet(int singleMember) { return new SingletonIntSet(singleMember); } }