- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.druid.extendedset;
-
-
-import java.util.AbstractCollection;
-import java.util.AbstractSet;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.NoSuchElementException;
-
-/**
- * This class provides a skeletal implementation of the {@link ExtendedSet}
- * interface to minimize the effort required to implement this interface.
- *
- * The process of implementing a set by extending this class is very similar,
- * for example, to that of implementing a {@link Collection} by extending
- * {@link AbstractCollection}.
- *
- * @param the type of elements maintained by this set
- *
- * @author Alessandro Colantonio
- * @version $Id: AbstractExtendedSet.java 157 2011-11-14 14:25:15Z cocciasik $
- */
-public abstract class AbstractExtendedSet extends AbstractSet implements ExtendedSet
-{
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet intersection(Collection extends T> other)
- {
- ExtendedSet clone = clone();
- clone.retainAll(other);
- return clone;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet union(Collection extends T> other)
- {
- ExtendedSet clone = clone();
- clone.addAll(other);
- return clone;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet difference(Collection extends T> other)
- {
- ExtendedSet clone = clone();
- clone.removeAll(other);
- return clone;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet symmetricDifference(Collection extends T> other)
- {
- ExtendedSet res = union(other);
- res.removeAll(intersection(other));
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet complemented()
- {
- ExtendedSet clone = clone();
- clone.complement();
- return clone;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsAny(Collection extends T> other)
- {
- return other == null || other.isEmpty() || intersectionSize(other) > 0;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsAtLeast(Collection extends T> other, int minElements)
- {
- if (minElements < 1) {
- throw new IllegalArgumentException();
- }
- return intersectionSize(other) >= minElements;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int intersectionSize(Collection extends T> other)
- {
- if (other == null || other.isEmpty() || isEmpty()) {
- return 0;
- }
- return intersection(other).size();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int unionSize(Collection extends T> other)
- {
- return other == null ? size() : size() + other.size() - intersectionSize(other);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int symmetricDifferenceSize(Collection extends T> other)
- {
- return other == null ? size() : size() + other.size() - 2 * intersectionSize(other);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int differenceSize(Collection extends T> other)
- {
- return other == null ? size() : size() - intersectionSize(other);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int complementSize()
- {
- return complemented().size();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public abstract ExtendedSet empty();
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet headSet(T toElement)
- {
- return new ExtendedSubSet(null, toElement);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet subSet(T fromElement, T toElement)
- {
- return new ExtendedSubSet(fromElement, toElement);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet tailSet(T fromElement)
- {
- return new ExtendedSubSet(fromElement, null);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public T first()
- {
- if (isEmpty()) {
- throw new NoSuchElementException();
- }
- return iterator().next();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public T last()
- {
- if (isEmpty()) {
- throw new NoSuchElementException();
- }
- return descendingIterator().next();
- }
-
- /**
- * {@inheritDoc}
- *
- * NOTE: When overriding this method, please note that
- * Object.clone()
is much slower then performing
- * new
and "manually" copying data!
- */
- @SuppressWarnings("unchecked")
- @Override
- public ExtendedSet clone()
- {
- try {
- return (ExtendedSet) super.clone();
- }
- catch (CloneNotSupportedException e) {
- throw new InternalError();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public abstract double bitmapCompressionRatio();
-
- /**
- * {@inheritDoc}
- */
- @Override
- public abstract double collectionCompressionRatio();
-
- /**
- * {@inheritDoc}
- */
- @Override
- @SuppressWarnings("unchecked")
- public ExtendedIterator descendingIterator()
- {
- // used to compare items
- Comparator super T> tmpComp = AbstractExtendedSet.this.comparator();
- if (tmpComp == null) {
- tmpComp = new Comparator()
- {
- @Override
- public int compare(T o1, T o2)
- {
- return ((Comparable) o1).compareTo(o2);
- }
- };
- }
- final Comparator super T> comp = tmpComp;
-
- return new ExtendedIterator()
- {
- // iterator from last element
- private final ListIterator itr = new ArrayList(AbstractExtendedSet.this)
- .listIterator(AbstractExtendedSet.this.size());
-
- @Override
- public boolean hasNext()
- {
- return itr.hasPrevious();
- }
-
- @Override
- public T next()
- {
- return itr.previous();
- }
-
- @Override
- public void skipAllBefore(T element)
- {
- // iterate until the element is found
- while (itr.hasPrevious()) {
- int res = comp.compare(itr.previous(), element);
-
- // the element has not been found, thus the next call to
- // itr.previous() will provide the right value
- if (res < 0) {
- return;
- }
-
- // the element has been found. Hence, we have to get back
- // to make itr.previous() provide the right value
- if (res == 0) {
- itr.next();
- return;
- }
- }
- }
-
- @Override
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
- };
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Iterable descending()
- {
- return new Iterable()
- {
- @Override
- public Iterator iterator()
- {
- return descendingIterator();
- }
- };
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public List extends ExtendedSet> powerSet()
- {
- return powerSet(1, Integer.MAX_VALUE);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public List extends ExtendedSet> powerSet(int min, int max)
- {
- if (min < 1 || max < min) {
- throw new IllegalArgumentException();
- }
-
- // special cases
- List> res = new ArrayList>();
- if (size() < min) {
- return res;
- }
- if (size() == min) {
- res.add(this.clone());
- return res;
- }
- if (size() == min + 1) {
- for (T item : this.descending()) {
- ExtendedSet set = this.clone();
- set.remove(item);
- res.add(set);
- }
- if (max > min) {
- res.add(this.clone());
- }
- return res;
- }
-
- // the first level contains only one prefix made up of all 1-subsets
- List>> level = new ArrayList>>();
- level.add(new ArrayList>());
- for (T item : this) {
- ExtendedSet single = this.empty();
- single.add(item);
- level.get(0).add(single);
- }
- if (min == 1) {
- res.addAll(level.get(0));
- }
-
- // all combinations
- int l = 2;
- while (!level.isEmpty() && l <= max) {
- List>> newLevel = new ArrayList>>();
- for (List> prefix : level) {
- for (int i = 0; i < prefix.size() - 1; i++) {
- List> newPrefix = new ArrayList>();
- for (int j = i + 1; j < prefix.size(); j++) {
- ExtendedSet x = prefix.get(i).clone();
- x.add(prefix.get(j).last());
- newPrefix.add(x);
- if (l >= min) {
- res.add(x);
- }
- }
- if (newPrefix.size() > 1) {
- newLevel.add(newPrefix);
- }
- }
- }
- level = newLevel;
- l++;
- }
-
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int powerSetSize()
- {
- return isEmpty() ? 0 : (int) Math.pow(2, size()) - 1;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int powerSetSize(int min, int max)
- {
- if (min < 1 || max < min) {
- throw new IllegalArgumentException();
- }
- final int size = size();
-
- // special cases
- if (size < min) {
- return 0;
- }
- if (size == min) {
- return 1;
- }
-
- /*
- * Compute the sum of binomial coefficients ranging from (size choose
- * max) to (size choose min) using dynamic programming
- */
-
- // trivial cases
- max = Math.min(size, max);
- if (max == min && (max == 0 || max == size)) {
- return 1;
- }
-
- // compute all binomial coefficients for "n"
- int[] b = new int[size + 1];
- for (int i = 0; i <= size; i++) {
- b[i] = 1;
- }
- for (int i = 1; i <= size; i++) {
- for (int j = i - 1; j > 0; j--) {
- b[j] += b[j - 1];
- }
- }
-
- // sum binomial coefficients
- int res = 0;
- for (int i = min; i <= max; i++) {
- res += b[i];
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @SuppressWarnings("unchecked")
- @Override
- public int compareTo(ExtendedSet o)
- {
- Iterator thisIterator = this.descendingIterator();
- Iterator otherIterator = o.descendingIterator();
- while (thisIterator.hasNext() && otherIterator.hasNext()) {
- T thisItem = thisIterator.next();
- T otherItem = otherIterator.next();
- int res = ((Comparable) thisItem).compareTo(otherItem);
- if (res != 0) {
- return res;
- }
- }
- return thisIterator.hasNext() ? 1 : (otherIterator.hasNext() ? -1 : 0);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void fill(T from, T to)
- {
- ExtendedSet toAdd = empty();
- toAdd.add(to);
- toAdd.complement();
- toAdd.add(to);
-
- ExtendedSet toRemove = empty();
- toRemove.add(from);
- toRemove.complement();
-
- toAdd.removeAll(toRemove);
-
- this.addAll(toAdd);
- }
-
-
- /**
- * {@inheritDoc}
- */
- @SuppressWarnings("unchecked")
- @Override
- public void clear(T from, T to)
- {
- ExtendedIterator itr = iterator();
- itr.skipAllBefore(from);
- while (itr.hasNext()) {
- if (((Comparable) itr.next()).compareTo(to) < 0) {
- itr.remove();
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void flip(T e)
- {
- if (!add(e)) {
- remove(e);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public T get(int i)
- {
- int size = size();
- if (i < 0 || i >= size) {
- throw new IndexOutOfBoundsException();
- }
-
- Iterator itr;
- if (i < (size / 2)) {
- itr = iterator();
- for (int j = 0; j <= i - 1; j++) {
- itr.next();
- }
- } else {
- itr = descendingIterator();
- for (int j = size - 1; j >= i + 1; j--) {
- itr.next();
- }
- }
- return itr.next();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int indexOf(T e)
- {
- Iterator itr = iterator();
- int i = 0;
- while (itr.hasNext()) {
- if (itr.next().equals(e)) {
- return i;
- }
- i++;
- }
- return -1;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet unmodifiable()
- {
- return new UnmodifiableExtendedSet();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public abstract ExtendedIterator iterator();
-
- /**
- * {@inheritDoc}
- */
- @Override
- public double jaccardSimilarity(ExtendedSet other)
- {
- if (isEmpty() && other.isEmpty()) {
- return 1D;
- }
- int inters = intersectionSize(other);
- return (double) inters / (size() + other.size() - inters);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public double jaccardDistance(ExtendedSet other)
- {
- return 1D - jaccardSimilarity(other);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public double weightedJaccardSimilarity(ExtendedSet other)
- {
- if (isEmpty() && other.isEmpty()) {
- return 1D;
- }
- ExtendedSet inters = intersection(other);
- double intersSum = 0D;
- for (T t : inters) {
- if (t instanceof Integer) {
- intersSum += (Integer) t;
- } else if (t instanceof Double) {
- intersSum += (Double) t;
- } else if (t instanceof Float) {
- intersSum += (Float) t;
- } else if (t instanceof Byte) {
- intersSum += (Byte) t;
- } else if (t instanceof Long) {
- intersSum += (Long) t;
- } else if (t instanceof Short) {
- intersSum += (Short) t;
- } else {
- throw new IllegalArgumentException("A collection of numbers is required");
- }
- }
-
- ExtendedSet symmetricDiff = symmetricDifference(other);
- double symmetricDiffSum = 0D;
- for (T t : symmetricDiff) {
- if (t instanceof Integer) {
- symmetricDiffSum += (Integer) t;
- } else if (t instanceof Double) {
- symmetricDiffSum += (Double) t;
- } else if (t instanceof Float) {
- symmetricDiffSum += (Float) t;
- } else if (t instanceof Byte) {
- symmetricDiffSum += (Byte) t;
- } else if (t instanceof Long) {
- symmetricDiffSum += (Long) t;
- } else if (t instanceof Short) {
- symmetricDiffSum += (Short) t;
- } else {
- throw new IllegalArgumentException("A collection of numbers is required");
- }
- }
-
- return intersSum / (intersSum + symmetricDiffSum);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public double weightedJaccardDistance(ExtendedSet other)
- {
- return 1D - weightedJaccardSimilarity(other);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet convert(Object... e)
- {
- if (e == null) {
- return empty();
- }
- return convert(Arrays.asList(e));
- }
-
- /**
- * {@inheritDoc}
- */
- @SuppressWarnings("unchecked")
- @Override
- public ExtendedSet convert(Collection> c)
- {
- ExtendedSet res = empty();
- res.addAll((Collection extends T>) c);
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String debugInfo()
- {
- return toString();
- }
-
- /**
- * Base class for {@link ExtendedSubSet} and {@link UnmodifiableExtendedSet}
- */
- protected abstract class FilteredSet implements ExtendedSet
- {
- /**
- * @return the container instance, namely the "internal" representation
- */
- protected abstract ExtendedSet raw();
-
- /*
- * Converter methods that allows for good performances with collection
- * operations by directly working on internal representation
- */
- @Override
- public ExtendedSet convert(Collection> c)
- {
- if (c instanceof AbstractExtendedSet.FilteredSet) {
- convert(((AbstractExtendedSet.FilteredSet) c).raw());
- }
- return raw().convert(c);
- }
-
- @Override
- public ExtendedSet convert(Object... e)
- {
- return raw().convert(e);
- }
-
- /*
- * Methods that directly apply to container instance
- */
- @Override
- public ExtendedSet clone() {return AbstractExtendedSet.this.clone();}
-
- @Override
- public ExtendedSet empty() {return AbstractExtendedSet.this.empty();}
-
- @Override
- public Comparator super T> comparator() {return AbstractExtendedSet.this.comparator();}
-
- /*
- * Read-only methods
- */
- @Override
- public ExtendedSet unmodifiable() {return raw().unmodifiable();}
-
- @Override
- public ExtendedIterator iterator() {return raw().iterator();}
-
- @Override
- public ExtendedIterator descendingIterator() {return raw().descendingIterator();}
-
- @Override
- public boolean isEmpty() {return raw().isEmpty();}
-
- @Override
- public boolean equals(Object o) {return raw().equals(o);}
-
- @Override
- public int hashCode() {return raw().hashCode();}
-
- @Override
- public int compareTo(ExtendedSet o) {return raw().compareTo(o);}
-
- @Override
- public T first() {return raw().first();}
-
- @Override
- public T last() {return raw().last();}
-
- @Override
- public double bitmapCompressionRatio() {return raw().bitmapCompressionRatio();}
-
- @Override
- public double collectionCompressionRatio() {return raw().collectionCompressionRatio();}
-
- @Override
- public List extends ExtendedSet> powerSet() {return raw().powerSet();}
-
- @Override
- public List extends ExtendedSet> powerSet(int mins, int maxs) {return raw().powerSet(mins, maxs);}
-
- @Override
- public int powerSetSize() {return raw().powerSetSize();}
-
- @Override
- public int powerSetSize(int mins, int maxs) {return raw().powerSetSize(mins, maxs);}
-
- @Override
- public Object[] toArray() {return raw().toArray();}
-
- @Override
- public X[] toArray(X[] a) {return raw().toArray(a);}
-
- @Override
- public String toString() {return raw().toString();}
-
- @Override
- public ExtendedSet complemented() {return raw().complemented();}
-
- @Override
- public int complementSize() {return raw().complementSize();}
-
- @Override
- public int size() {return raw().size();}
-
- @Override
- public boolean contains(Object o) {return raw().contains(o);}
-
- @Override
- public Iterable descending() {return raw().descending();}
-
- @Override
- public String debugInfo() {return raw().debugInfo();}
-
- @Override
- public T get(int i) {return raw().get(i);}
-
- @Override
- public int indexOf(T e) {return raw().indexOf(e);}
-
- /*
- * Methods that requires a call to convert() to assure good performances
- */
- @Override
- public double jaccardDistance(ExtendedSet other) {return raw().jaccardDistance(convert(other));}
-
- @Override
- public double jaccardSimilarity(ExtendedSet other) {return raw().jaccardSimilarity(convert(other));}
-
- @Override
- public double weightedJaccardDistance(ExtendedSet other) {return raw().weightedJaccardDistance(convert(other));}
-
- @Override
- public double weightedJaccardSimilarity(ExtendedSet other) {return raw().weightedJaccardSimilarity(convert(other));}
-
- @Override
- public ExtendedSet difference(Collection extends T> other) {return raw().difference(convert(other));}
-
- @Override
- public ExtendedSet symmetricDifference(Collection extends T> other)
- {
- return raw().symmetricDifference(convert(other));
- }
-
- @Override
- public ExtendedSet intersection(Collection extends T> other) {return raw().intersection(convert(other));}
-
- @Override
- public ExtendedSet union(Collection extends T> other) {return raw().union(convert(other));}
-
- @Override
- public int intersectionSize(Collection extends T> other) {return raw().intersectionSize(convert(other));}
-
- @Override
- public int differenceSize(Collection extends T> other) {return raw().differenceSize(convert(other));}
-
- @Override
- public int unionSize(Collection extends T> other) {return raw().unionSize(convert(other));}
-
- @Override
- public int symmetricDifferenceSize(Collection extends T> other)
- {
- return raw().symmetricDifferenceSize(convert(other));
- }
-
- @Override
- public boolean containsAll(Collection> c) {return raw().containsAll(convert(c));}
-
- @Override
- public boolean containsAny(Collection extends T> other) {return raw().containsAny(convert(other));}
-
- @Override
- public boolean containsAtLeast(
- Collection extends T> other,
- int minElements
- )
- {return raw().containsAtLeast(convert(other), minElements);}
- }
-
- /**
- * Read-only view of the set.
- *
- * Note that it extends {@link AbstractExtendedSet} instead of implementing
- * {@link ExtendedSet} because of the methods {@link #tailSet(Object)},
- * {@link #headSet(Object)}, and {@link #subSet(Object, Object)}.
- */
- protected class UnmodifiableExtendedSet extends AbstractExtendedSet.FilteredSet
- {
- // exception message when writing operations are performed on {@link #unmodifiable()}
- private final static String UNSUPPORTED_MSG = "The class is read-only!";
-
- /*
- * Unsupported writing methods
- */
- @Override
- public boolean add(T e) {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
-
- @Override
- public boolean addAll(Collection extends T> c) {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
-
- @Override
- public boolean remove(Object o) {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
-
- @Override
- public boolean removeAll(Collection> c) {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
-
- @Override
- public boolean retainAll(Collection> c) {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
-
- @Override
- public void clear() {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
-
- @Override
- public void clear(T from, T to) {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
-
- @Override
- public void fill(T from, T to) {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
-
- @Override
- public void complement() {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
-
- @Override
- public void flip(T e) {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
-
- /*
- * Special purpose methods
- */
-
- // create new iterators where the remove() operation is not permitted
- @Override
- public ExtendedIterator iterator()
- {
- final ExtendedIterator itr = AbstractExtendedSet.this.iterator();
- return new ExtendedIterator()
- {
- @Override
- public boolean hasNext() {return itr.hasNext();}
-
- @Override
- public T next() {return itr.next();}
-
- @Override
- public void skipAllBefore(T element) {itr.skipAllBefore(element);}
-
- @Override
- public void remove() {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
- };
- }
-
- @Override
- public ExtendedIterator descendingIterator()
- {
- final ExtendedIterator itr = AbstractExtendedSet.this.descendingIterator();
- return new ExtendedIterator()
- {
- @Override
- public boolean hasNext() {return itr.hasNext();}
-
- @Override
- public T next() {return itr.next();}
-
- @Override
- public void skipAllBefore(T element) {itr.skipAllBefore(element);}
-
- @Override
- public void remove() {throw new UnsupportedOperationException(UNSUPPORTED_MSG);}
- };
- }
-
- /**
- * Returns a read-only subset
- */
- // TODO: There is a known bug. Indeed, this implementation does not work
- // since modifications to the read-write set are not reflected to the
- // read-only set.
- private ExtendedSet unmodifiableSubSet(T min, T max)
- {
- ExtendedSet res;
- ExtendedSet range = AbstractExtendedSet.this.empty();
- if (min != null && max != null) {
- range.fill(min, max);
- range.remove(max);
- res = AbstractExtendedSet.this.intersection(range).unmodifiable();
- } else if (max != null) {
- range.add(max);
- range.complement();
- res = AbstractExtendedSet.this.intersection(range).unmodifiable();
- } else {
- range.add(min);
- range.complement();
- res = AbstractExtendedSet.this.difference(range).unmodifiable();
- }
- return res;
- }
-
- // subset operations must be read-only
- @Override
- public ExtendedSet headSet(T toElement) {return unmodifiableSubSet(null, toElement);}
-
- @Override
- public ExtendedSet subSet(T fromElement, T toElement) {return unmodifiableSubSet(fromElement, toElement);}
-
- @Override
- public ExtendedSet tailSet(T fromElement) {return unmodifiableSubSet(fromElement, null);}
-
- @Override
- public ExtendedSet unmodifiable()
- {
- // useless to create another instance
- return this;
- }
-
- @Override
- protected ExtendedSet raw()
- {
- return AbstractExtendedSet.this;
- }
- }
-
- /**
- * Used by {@link AbstractExtendedSet#headSet(T)} , {@link AbstractExtendedSet#tailSet(T)} and {@link AbstractExtendedSet#subSet(T, T)} to offer a restricted view of the entire set
- */
- protected class ExtendedSubSet extends AbstractExtendedSet.FilteredSet
- {
- /**
- * Minimun allowed element (included) and maximum allowed element
- * (excluded)
- */
- private final T min;
-
- /**
- * Minimun allowed element (included) and maximum allowed element
- * (excluded)
- */
- private final T max;
-
- /**
- * When max != null
, it contains all elements from {@link #min} to {@link #max} - 1. Otherwise, it contains all the elements strictly below {@link #min}
- *
- * @uml.property name="range"
- * @uml.associationEnd
- */
- private final ExtendedSet range;
- /**
- * Comparator for elements of type T
- */
- private final Comparator super T> localComparator;
-
-
-
- /*
- * PRIVATE UTILITY METHODS
- */
-
- // initialize the comparator
- {
- final Comparator super T> c = AbstractExtendedSet.this.comparator();
- if (c != null) {
- localComparator = c;
- } else {
- localComparator = new Comparator()
- {
- @SuppressWarnings("unchecked")
- @Override
- public int compare(T o1, T o2)
- {
- return ((Comparable) o1).compareTo(o2);
- }
- };
- }
- }
-
- /**
- * Creates the subset
- *
- * @param min minimun allowed element (included)
- * @param max maximum allowed element (excluded)
- */
- public ExtendedSubSet(T min, T max)
- {
- if (min == null && max == null) {
- throw new IllegalArgumentException();
- }
-
- if (min != null && max != null
- && localComparator.compare(min, max) > 0) {
- throw new IllegalArgumentException("min > max");
- }
-
- this.min = min;
- this.max = max;
-
- // add all elements that are strictly less than "max"
- range = AbstractExtendedSet.this.empty();
- if (min != null && max != null) {
- range.fill(min, max);
- range.remove(max);
- } else if (max != null) {
- range.add(max);
- range.complement();
- } else {
- range.add(min);
- range.complement();
- }
- }
-
- /**
- * Checks if a given set is completely contained within {@link #min} and
- * {@link #max}
- *
- * @param other given set
- *
- * @return true
if the given set is completely contained
- * within {@link #min} and {@link #max}
- */
- private boolean isInRange(ExtendedSet other)
- {
- return other.isEmpty() ||
- ((max == null || localComparator.compare(other.last(), max) < 0)
- && (min == null || localComparator.compare(other.first(), min) >= 0));
- }
-
- /**
- * Checks if a given element is completely contained within {@link #min}
- * and {@link #max}
- *
- * @param e given element
- *
- * @return true
if the given element is completely
- * contained within {@link #min} and {@link #max}
- */
- @SuppressWarnings("unchecked")
- private boolean isInRange(Object e)
- {
- return (max == null || localComparator.compare((T) e, max) < 0)
- && (min == null || localComparator.compare((T) e, min) >= 0);
- }
-
- /**
- * Generates a set that represent a subview of the given set, namely
- * elements from {@link #min} (included) to {@link #max} (excluded)
- *
- * @param toFilter given set
- *
- * @return the subview
- */
- private ExtendedSet filter(ExtendedSet toFilter)
- {
- if (isInRange(toFilter)) {
- return toFilter;
- }
- if (max != null) {
- return toFilter.intersection(range);
- }
- return toFilter.difference(range);
- }
-
-
- @Override
- protected ExtendedSet raw()
- {
- return filter(AbstractExtendedSet.this);
- }
-
-
-
- /*
- * PUBLIC METHODS
- */
-
- @Override
- public ExtendedSet headSet(T toElement)
- {
- if (localComparator.compare(toElement, max) > 0) {
- throw new IllegalArgumentException();
- }
- return AbstractExtendedSet.this.new ExtendedSubSet(min, toElement);
- }
-
- @Override
- public ExtendedSet subSet(T fromElement, T toElement)
- {
- if (localComparator.compare(fromElement, min) < 0
- || localComparator.compare(toElement, max) > 0) {
- throw new IllegalArgumentException();
- }
- return AbstractExtendedSet.this.new ExtendedSubSet(fromElement, toElement);
- }
-
- @Override
- public ExtendedSet tailSet(T fromElement)
- {
- if (localComparator.compare(fromElement, min) < 0) {
- throw new IllegalArgumentException();
- }
- return AbstractExtendedSet.this.new ExtendedSubSet(fromElement, max);
- }
-
- @Override
- public boolean addAll(Collection extends T> c)
- {
- if (c == null) {
- return false;
- }
- ExtendedSet other = convert(c);
- if (!isInRange(other)) {
- throw new IllegalArgumentException();
- }
- return AbstractExtendedSet.this.addAll(other);
- }
-
- @Override
- public boolean removeAll(Collection> c)
- {
- if (c == null) {
- return false;
- }
- return AbstractExtendedSet.this.removeAll(filter(convert(c)));
- }
-
- @Override
- public boolean retainAll(Collection> c)
- {
- if (c == null) {
- return false;
- }
- ExtendedSet other = convert(c);
-
- if (isInRange(AbstractExtendedSet.this)) {
- return AbstractExtendedSet.this.retainAll(other);
- }
-
- int sizeBefore = AbstractExtendedSet.this.size();
- ExtendedSet res = AbstractExtendedSet.this.intersection(other);
- clear();
- AbstractExtendedSet.this.addAll(res);
- return AbstractExtendedSet.this.size() != sizeBefore;
- }
-
- @Override
- public boolean containsAll(Collection> c)
- {
- if (c == null) {
- return false;
- }
- ExtendedSet other = convert(c);
- return isInRange(other) && AbstractExtendedSet.this.containsAll(other);
- }
-
- @Override
- public boolean add(T e)
- {
- if (!isInRange(e)) {
- throw new IllegalArgumentException();
- }
- return AbstractExtendedSet.this.add(e);
- }
-
- @Override
- public void clear()
- {
- if (isInRange(AbstractExtendedSet.this)) {
- AbstractExtendedSet.this.clear();
- } else if (max != null) {
- AbstractExtendedSet.this.removeAll(range);
- } else {
- AbstractExtendedSet.this.retainAll(range);
- }
- }
-
- @Override
- public boolean contains(Object o)
- {
- return o != null && isInRange(o) && AbstractExtendedSet.this.contains(o);
- }
-
- @Override
- public boolean remove(Object o)
- {
- return o != null && isInRange(o) && AbstractExtendedSet.this.remove(o);
- }
-
- @Override
- public int size()
- {
- if (isInRange(AbstractExtendedSet.this)) {
- return AbstractExtendedSet.this.size();
- }
- if (max != null) {
- return AbstractExtendedSet.this.intersectionSize(range);
- }
- return AbstractExtendedSet.this.differenceSize(range);
- }
-
- @Override
- public void complement()
- {
- ExtendedSet c = complemented();
- clear();
- AbstractExtendedSet.this.addAll(c);
- }
-
- @Override
- public int complementSize()
- {
- return complemented().size();
- }
-
- @Override
- public ExtendedSet complemented()
- {
- return filter(raw().complemented());
- }
-
- @Override
- public String debugInfo()
- {
- return String.format("min = %s, max = %s\nmask = %s\nelements = %s",
- min.toString(), max.toString(), range.debugInfo(), AbstractExtendedSet.this.toString()
- );
- }
-
- @Override
- public void clear(T from, T to)
- {
- ExtendedSet toRemove = empty();
- toRemove.fill(from, to);
- removeAll(toRemove);
- }
-
- @Override
- public boolean containsAny(Collection extends T> other)
- {
- return AbstractExtendedSet.this.containsAny(filter(convert(other)));
- }
-
- @Override
- public boolean containsAtLeast(Collection extends T> other, int minElements)
- {
- return AbstractExtendedSet.this.containsAtLeast(filter(convert(other)), minElements);
- }
-
- @Override
- public Iterable descending()
- {
- return new Iterable()
- {
- @Override
- public Iterator iterator()
- {
- return descendingIterator();
- }
- };
- }
-
- @Override
- public void fill(T from, T to)
- {
- if (!isInRange(from) || !isInRange(to)) {
- throw new IllegalArgumentException();
- }
- AbstractExtendedSet.this.fill(from, to);
- }
-
- @Override
- public void flip(T e)
- {
- if (!isInRange(e)) {
- throw new IllegalArgumentException();
- }
- AbstractExtendedSet.this.flip(e);
- }
-
- @Override
- public T get(int i)
- {
- int minIndex = 0;
- if (min != null) {
- minIndex = AbstractExtendedSet.this.indexOf(min);
- }
- T r = AbstractExtendedSet.this.get(minIndex + i);
- if (!isInRange(r)) {
- throw new IllegalArgumentException();
- }
- return r;
- }
-
- @Override
- public int indexOf(T e)
- {
- if (!isInRange(e)) {
- throw new IllegalArgumentException();
- }
- int minIndex = 0;
- if (min != null) {
- minIndex = AbstractExtendedSet.this.indexOf(min);
- }
- return AbstractExtendedSet.this.indexOf(e) - minIndex;
- }
-
- @Override
- public ExtendedSet clone()
- {
- return raw();
- }
- }
-}
diff --git a/extendedset/src/main/java/io/druid/extendedset/ExtendedSet.java b/extendedset/src/main/java/io/druid/extendedset/ExtendedSet.java
deleted file mode 100755
index beaa52368ad..00000000000
--- a/extendedset/src/main/java/io/druid/extendedset/ExtendedSet.java
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * (c) 2010 Alessandro Colantonio
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package io.druid.extendedset;
-
-
-import io.druid.extendedset.intset.ArraySet;
-import io.druid.extendedset.intset.IntSet;
-import io.druid.extendedset.wrappers.GenericExtendedSet;
-import io.druid.extendedset.wrappers.IndexedSet;
-import io.druid.extendedset.wrappers.IntegerSet;
-import io.druid.extendedset.wrappers.LongSet;
-import io.druid.extendedset.wrappers.matrix.PairSet;
-
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.SortedSet;
-
-/**
- * An interface which extends {@link SortedSet} by adding
- * intersection/union/difference and other set operations.
- *
- * @param the type of elements maintained by this set
- *
- * @author Alessandro Colantonio
- * @version $Id: ExtendedSet.java 140 2011-02-07 21:30:29Z cocciasik $
- * @see AbstractExtendedSet
- * @see IndexedSet
- * @see GenericExtendedSet
- * @see ArraySet
- * @see IntegerSet
- * @see LongSet
- * @see PairSet
- */
-public interface ExtendedSet extends SortedSet, Cloneable, Comparable>
-{
- /**
- * Generates the intersection set
- *
- * @param other {@link ExtendedSet} instance that represents the right
- * operand
- *
- * @return the result of the operation
- *
- * @see #retainAll(java.util.Collection)
- */
- public ExtendedSet intersection(Collection extends T> other);
-
- /**
- * Generates the union set
- *
- * @param other {@link ExtendedSet} instance that represents the right
- * operand
- *
- * @return the result of the operation
- *
- * @see #addAll(java.util.Collection)
- */
- public ExtendedSet union(Collection extends T> other);
-
- /**
- * Generates the difference set
- *
- * @param other {@link ExtendedSet} instance that represents the right
- * operand
- *
- * @return the result of the operation
- *
- * @see #removeAll(java.util.Collection)
- */
- public ExtendedSet difference(Collection extends T> other);
-
- /**
- * Generates the symmetric difference set
- *
- * @param other {@link ExtendedSet} instance that represents the right
- * operand
- *
- * @return the result of the operation
- *
- * @see #flip(Object)
- */
- public ExtendedSet symmetricDifference(Collection extends T> other);
-
- /**
- * Generates the complement set. The returned set is represented by all the
- * elements strictly less than {@link #last()} that do not exist in the
- * current set.
- *
- * @return the complement set
- *
- * @see ExtendedSet#complement()
- */
- public ExtendedSet complemented();
-
- /**
- * Complements the current set. The modified set is represented by all the
- * elements strictly less than {@link #last()} that do not exist in the
- * current set.
- *
- * @see ExtendedSet#complemented()
- */
- public void complement();
-
- /**
- * Returns true
if the specified {@link Collection} instance
- * contains any elements that are also contained within this
- * {@link ExtendedSet} instance
- *
- * @param other {@link ExtendedSet} to intersect with
- *
- * @return a boolean indicating whether this {@link ExtendedSet} intersects
- * the specified {@link ExtendedSet}.
- */
- public boolean containsAny(Collection extends T> other);
-
- /**
- * Returns true
if the specified {@link Collection} instance
- * contains at least minElements
elements that are also
- * contained within this {@link ExtendedSet} instance
- *
- * @param other {@link Collection} instance to intersect with
- * @param minElements minimum number of elements to be contained within this
- * {@link ExtendedSet} instance
- *
- * @return a boolean indicating whether this {@link ExtendedSet} intersects
- * the specified {@link Collection}.
- *
- * @throws IllegalArgumentException if minElements < 1
- */
- public boolean containsAtLeast(Collection extends T> other, int minElements);
-
- /**
- * Computes the intersection set size.
- *
- * This is faster than calling {@link #intersection(Collection)} and
- * then {@link #size()}
- *
- * @param other {@link Collection} instance that represents the right
- * operand
- *
- * @return the size
- */
- public int intersectionSize(Collection extends T> other);
-
- /**
- * Computes the union set size.
- *
- * This is faster than calling {@link #union(Collection)} and then
- * {@link #size()}
- *
- * @param other {@link Collection} instance that represents the right
- * operand
- *
- * @return the size
- */
- public int unionSize(Collection extends T> other);
-
- /**
- * Computes the symmetric difference set size.
- *
- * This is faster than calling
- * {@link #symmetricDifference(Collection)} and then {@link #size()}
- *
- * @param other {@link Collection} instance that represents the right
- * operand
- *
- * @return the size
- */
- public int symmetricDifferenceSize(Collection extends T> other);
-
- /**
- * Computes the difference set size.
- *
- * This is faster than calling {@link #difference(Collection)} and
- * then {@link #size()}
- *
- * @param other {@link Collection} instance that represents the right
- * operand
- *
- * @return the size
- */
- public int differenceSize(Collection extends T> other);
-
- /**
- * Computes the complement set size.
- *
- * This is faster than calling {@link #complemented()} and then
- * {@link #size()}
- *
- * @return the size
- */
- public int complementSize();
-
- /**
- * Generates an empty set
- *
- * @return the empty set
- */
- public ExtendedSet empty();
-
- /**
- * See the clone()
of {@link Object}
- *
- * @return cloned object
- */
- public ExtendedSet clone();
-
- /**
- * Computes the compression factor of the equivalent bitmap representation
- * (1 means not compressed, namely a memory footprint similar to
- * {@link BitSet}, 2 means twice the size of {@link BitSet}, etc.)
- *
- * @return the compression factor
- */
- public double bitmapCompressionRatio();
-
- /**
- * Computes the compression factor of the equivalent integer collection (1
- * means not compressed, namely a memory footprint similar to
- * {@link ArrayList}, 2 means twice the size of {@link ArrayList}, etc.)
- *
- * @return the compression factor
- */
- public double collectionCompressionRatio();
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedIterator iterator();
-
- /**
- * Gets the descending order iterator over the elements of type
- * T
- *
- * @return descending iterator
- */
- public ExtendedIterator descendingIterator();
-
- /**
- * Allows to use the Java "for-each" statement in descending order
- *
- * @return {@link Iterable} instance to iterate items in descending
- * order
- */
- public Iterable descending();
-
- /**
- * Computes the power-set of the current set.
- *
- * It is a particular implementation of the algorithm Apriori (see:
- * Rakesh Agrawal, Ramakrishnan Srikant, Fast Algorithms for Mining
- * Association Rules in Large Databases, in Proceedings of the
- * 20th International Conference on Very Large Data Bases,
- * p.487-499, 1994). The returned power-set does not contain the
- * empty set.
- *
- * The subsets composing the powerset are returned in a list that is sorted
- * according to the lexicographical order provided by the sorted set.
- *
- * @return the power-set
- *
- * @see #powerSet(int, int)
- * @see #powerSetSize()
- */
- public List extends ExtendedSet> powerSet();
-
- /**
- * Computes a subset of the power-set of the current set, composed by those
- * subsets that have cardinality between min
and
- * max
.
- *
- * It is a particular implementation of the algorithm Apriori (see:
- * Rakesh Agrawal, Ramakrishnan Srikant, Fast Algorithms for Mining
- * Association Rules in Large Databases, in Proceedings of the
- * 20th International Conference on Very Large Data Bases,
- * p.487-499, 1994). The power-set does not contains the empty set.
- *
- * The subsets composing the powerset are returned in a list that is sorted
- * according to the lexicographical order provided by the sorted set.
- *
- * @param min minimum subset size (greater than zero)
- * @param max maximum subset size
- *
- * @return the power-set
- *
- * @see #powerSet()
- * @see #powerSetSize(int, int)
- */
- public List extends ExtendedSet> powerSet(int min, int max);
-
- /**
- * Computes the power-set size of the current set.
- *
- * The power-set does not contains the empty set.
- *
- * @return the power-set size
- *
- * @see #powerSet()
- */
- public int powerSetSize();
-
- /**
- * Computes the power-set size of the current set, composed by those subsets
- * that have cardinality between min
and max
.
- *
- * The returned power-set does not contain the empty set.
- *
- * @param min minimum subset size (greater than zero)
- * @param max maximum subset size
- *
- * @return the power-set size
- *
- * @see #powerSet(int, int)
- */
- public int powerSetSize(int min, int max);
-
- /**
- * Prints debug info about the given {@link ExtendedSet} implementation
- *
- * @return a string that describes the internal representation of the
- * instance
- */
- public String debugInfo();
-
- /**
- * Adds to the set all the elements between first
and
- * last
, both included. It supposes that there is an ordering
- * of the elements of type T
and that the universe of all
- * possible elements is known.
- *
- * @param from first element
- * @param to last element
- */
- public void fill(T from, T to);
-
- /**
- * Removes from the set all the elements between first
and
- * last
, both included. It supposes that there is an ordering
- * of the elements of type T
and that the universe of all
- * possible elements is known.
- *
- * @param from first element
- * @param to last element
- */
- public void clear(T from, T to);
-
- /**
- * Adds the element if it not existing, or removes it if existing
- *
- * @param e element to flip
- *
- * @see #symmetricDifference(Collection)
- */
- public void flip(T e);
-
- /**
- * Gets the read-only version of the current set
- *
- * @return the read-only version of the current set
- */
- public ExtendedSet unmodifiable();
-
- /**
- * Gets the i
th element of the set
- *
- * @param i position of the element in the sorted set
- *
- * @return the i
th element of the set
- *
- * @throws IndexOutOfBoundsException if i
is less than zero, or greater or equal to
- * {@link #size()}
- */
- public T get(int i);
-
- /**
- * Provides position of element within the set.
- *
- * It returns -1 if the element does not exist within the set.
- *
- * @param e element of the set
- *
- * @return the element position
- */
- public int indexOf(T e);
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet tailSet(T fromElement);
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet headSet(T toElement);
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ExtendedSet subSet(T fromElement, T toElement);
-
- /**
- * Converts a given {@link Collection} instance into an instance of the
- * current class. NOTE: when the collection is already an instance of
- * the current class, the method returns the collection itself.
- *
- * @param c collection to use to generate the new instance
- *
- * @return the converted collection
- *
- * @see #convert(Object...)
- */
- public ExtendedSet convert(Collection> c);
-
- /**
- * Converts a given integer array into an instance of the current class
- *
- * @param e objects to use to generate the new instance
- *
- * @return the converted collection
- *
- * @see #convert(Collection)
- */
- public ExtendedSet convert(Object... e);
-
- /**
- * Computes the Jaccard similarity coefficient between this set and the
- * given set.
- *
- * The coefficient is defined as
- * |A intersection B| / |A union B|
.
- *
- * @param other the other set
- *
- * @return the Jaccard similarity coefficient
- *
- * @see #jaccardDistance(ExtendedSet)
- */
- public double jaccardSimilarity(ExtendedSet other);
-
- /**
- * Computes the Jaccard distance between this set and the given set.
- *
- * The coefficient is defined as
- * 1 -
{@link #jaccardSimilarity(ExtendedSet)}.
- *
- * @param other the other set
- *
- * @return the Jaccard distance
- *
- * @see #jaccardSimilarity(ExtendedSet)
- */
- public double jaccardDistance(ExtendedSet other);
-
- /**
- * Computes the weighted version of the Jaccard similarity coefficient
- * between this set and the given set.
- *
- * The coefficient is defined as
- * sum of min(A_i, B_i) / sum of max(A_i, B_i)
.
- *
- * NOTE: T
must be a number, namely one of
- * {@link Integer}, {@link Double}, {@link Float}, {@link Byte},
- * {@link Long}, {@link Short}.
- *
- * @param other the other set
- *
- * @return the weighted Jaccard similarity coefficient
- *
- * @throws IllegalArgumentException if T
is not a number
- * @see #weightedJaccardDistance(ExtendedSet)
- */
- public double weightedJaccardSimilarity(ExtendedSet other);
-
- /**
- * Computes the weighted version of the Jaccard distance between this set
- * and the given set.
- *
- * The coefficient is defined as 1 -
- * {@link #weightedJaccardSimilarity(ExtendedSet)}.
- *
- * NOTE: T
must be a number, namely one of
- * {@link Integer}, {@link Double}, {@link Float}, {@link Byte},
- * {@link Long}, {@link Short}.
- *
- * @param other the other set
- *
- * @return the weighted Jaccard distance
- *
- * @throws IllegalArgumentException if T
is not a number
- * @see #weightedJaccardSimilarity(ExtendedSet)
- */
- public double weightedJaccardDistance(ExtendedSet other);
-
- /**
- * Compares this object with the specified object for order. Returns a
- * negative integer, zero, or a positive integer as this object is less
- * than, equal to, or greater than the specified object. An {@link IntSet}
- * instance A
is less than another {@link IntSet} instance
- * B
if B-A
(that is, the elements in
- * B
that are not contained in A
) contains at
- * least one element that is greater than all the elements in
- * A-B
.
- *
- *
- * The implementor must ensure sgn(x.compareTo(y)) ==
- * -sgn(y.compareTo(x)) for all x and y. (This
- * implies that x.compareTo(y) must throw an exception iff
- * y.compareTo(x) throws an exception.)
- *
- *
- * The implementor must also ensure that the relation is transitive:
- * (x.compareTo(y)>0 && y.compareTo(z)>0) implies
- * x.compareTo(z)>0.
- *
- *
- * Finally, the implementor must ensure that x.compareTo(y)==0
- * implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all
- * z.
- *
- *
- * It is strongly recommended, but not strictly required that
- * (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any
- * class that implements the Comparable interface and violates this
- * condition should clearly indicate this fact. The recommended language is
- * "Note: this class has a natural ordering that is inconsistent with
- * equals."
- *
- *
- * In the foregoing description, the notation sgn(expression
- * ) designates the mathematical signum function, which is
- * defined to return one of -1, 0, or 1 according
- * to whether the value of expression is negative, zero or positive.
- *
- * @param o the object to be compared.
- *
- * @return a negative integer, zero, or a positive integer as this object is
- * less than, equal to, or greater than the specified object.
- *
- * @throws ClassCastException if the specified object's type prevents it from being
- * compared to this object.
- */
- @Override
- public int compareTo(ExtendedSet o);
-
- /**
- * Extended version of the {@link Iterator} interface that allows to "skip"
- * some elements of the set
- *
- * @param the type of elements maintained by this set
- */
- public interface ExtendedIterator extends Iterator
- {
- /**
- * Skips all the elements before the the specified element, so that
- * {@link Iterator#next()} gives the given element or, if it does not
- * exist, the element immediately after according to the sorting
- * provided by this {@link SortedSet} instance.
- *
- * If element
is less than the next element, it does
- * nothing
- *
- * @param element first element to not skip
- */
- public void skipAllBefore(X element);
- }
-}
-
-
diff --git a/extendedset/src/main/java/io/druid/extendedset/intset/ArraySet.java b/extendedset/src/main/java/io/druid/extendedset/intset/ArraySet.java
deleted file mode 100755
index aee867240a9..00000000000
--- a/extendedset/src/main/java/io/druid/extendedset/intset/ArraySet.java
+++ /dev/null
@@ -1,1157 +0,0 @@
-/*
- * (c) 2010 Alessandro Colantonio
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package io.druid.extendedset.intset;
-
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.SortedSet;
-
-/**
- * {@link IntSet}-based class internally managed by a sorted array of
- * int
s.
- *
- * @author Alessandro Colantonio
- * @version $Id: ArraySet.java 156 2011-09-01 00:13:57Z cocciasik $
- */
-public class ArraySet extends AbstractIntSet
-{
- /**
- * elements of the set
- */
- private int[] elements;
-
- /**
- * set cardinality
- */
- private int size;
-
- /**
- * Empty-set constructor
- */
- public ArraySet()
- {
- size = 0;
- elements = null;
- }
-
- /**
- * Replace the content of the current instance with the content of another
- * instance
- *
- * @param other
- */
- private void replaceWith(ArraySet other)
- {
- size = other.size;
- elements = other.elements;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public double bitmapCompressionRatio()
- {
- if (isEmpty()) {
- return 0D;
- }
- return size() / Math.ceil(elements[size - 1] / 32D);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public double collectionCompressionRatio()
- {
- return isEmpty() ? 0D : 1D;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ArraySet empty()
- {
- return new ArraySet();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IntIterator iterator()
- {
- return new IntIterator()
- {
- int next = 0;
-
- @Override
- public void skipAllBefore(int e)
- {
- if (e <= elements[next]) {
- return;
- }
- next = Arrays.binarySearch(elements, next + 1, size, e);
- if (next < 0) {
- next = -(next + 1);
- }
- }
-
- @Override
- public boolean hasNext()
- {
- return next < size;
- }
-
- @Override
- public int next()
- {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- return elements[next++];
- }
-
- @Override
- public void remove()
- {
- next--;
- size--;
- System.arraycopy(elements, next + 1, elements, next, size - next);
- compact();
- }
-
- @Override
- public IntIterator clone()
- {
- throw new UnsupportedOperationException();
- }
- };
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IntIterator descendingIterator()
- {
- return new IntIterator()
- {
- int next = size - 1;
-
- @Override
- public void skipAllBefore(int e)
- {
- if (e >= elements[next]) {
- return;
- }
- next = Arrays.binarySearch(elements, 0, next, e);
- if (next < 0) {
- next = -(next + 1) - 1;
- }
- }
-
- @Override
- public boolean hasNext()
- {
- return next >= 0;
- }
-
- @Override
- public int next()
- {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- return elements[next--];
- }
-
- @Override
- public void remove()
- {
- next++;
- size--;
- System.arraycopy(elements, next + 1, elements, next, size - next);
- compact();
- }
-
- @Override
- public IntIterator clone()
- {
- throw new UnsupportedOperationException();
- }
- };
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ArraySet clone()
- {
- // NOTE: do not use super.clone() since it is 10 times slower!
- ArraySet c = empty();
- if (!isEmpty()) {
- c.elements = Arrays.copyOf(elements, elements.length);
- c.size = size;
- }
- return c;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String debugInfo()
- {
- return toString();
- }
-
- /**
- * Assures that the size of {@link #elements} is sufficient to contain
- * {@link #size} elements.
- */
- private void ensureCapacity()
- {
- int capacity = elements == null ? 0 : elements.length;
- if (capacity >= size) {
- return;
- }
- capacity = Math.max(capacity << 1, size);
-
- if (elements == null) {
- // nothing to copy
- elements = new int[capacity];
- return;
- }
- elements = Arrays.copyOf(elements, capacity);
- }
-
- /**
- * Removes unused allocated words at the end of {@link #words} only when they
- * are more than twice of the needed space
- */
- private void compact()
- {
- if (size == 0) {
- elements = null;
- return;
- }
- if (elements != null && (size << 1) < elements.length) {
- elements = Arrays.copyOf(elements, size);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean add(int element)
- {
- // append
- if (isEmpty() || elements[size - 1] < element) {
- size++;
- ensureCapacity();
- elements[size - 1] = element;
- return true;
- }
-
- // insert
- int pos = Arrays.binarySearch(elements, 0, size, element);
- if (pos >= 0) {
- return false;
- }
-
- size++;
- ensureCapacity();
- pos = -(pos + 1);
- System.arraycopy(elements, pos, elements, pos + 1, size - pos - 1);
- elements[pos] = element;
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean remove(int element)
- {
- if (element < 0) {
- return false;
- }
-
- int pos = Arrays.binarySearch(elements, 0, size, element);
- if (pos < 0) {
- return false;
- }
-
- size--;
- System.arraycopy(elements, pos + 1, elements, pos, size - pos);
- compact();
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void flip(int element)
- {
- // first
- if (isEmpty()) {
- size++;
- ensureCapacity();
- elements[size - 1] = element;
- return;
- }
-
- int pos = Arrays.binarySearch(elements, 0, size, element);
-
- // add
- if (pos < 0) {
- size++;
- ensureCapacity();
- pos = -(pos + 1);
- System.arraycopy(elements, pos, elements, pos + 1, size - pos - 1);
- elements[pos] = element;
- return;
- }
-
- // remove
- size--;
- System.arraycopy(elements, pos + 1, elements, pos, size - pos);
- compact();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean contains(int element)
- {
- if (isEmpty()) {
- return false;
- }
- return Arrays.binarySearch(elements, 0, size, element) >= 0;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsAll(IntSet c)
- {
- if (c == null || c.isEmpty() || c == this) {
- return true;
- }
- if (isEmpty()) {
- return false;
- }
-
- final ArraySet o = convert(c);
- final int[] thisElements = elements; // faster
- final int[] otherElements = o.elements; // faster
- int otherSize = o.size;
- int thisIndex = -1;
- int otherIndex = -1;
- while (thisIndex < (size - 1) && otherIndex < (otherSize - 1)) {
- thisIndex++;
- otherIndex++;
- while (thisElements[thisIndex] < otherElements[otherIndex]) {
- if (thisIndex == size - 1) {
- return false;
- }
- thisIndex++;
- }
- if (thisElements[thisIndex] > otherElements[otherIndex]) {
- return false;
- }
- }
- return otherIndex == otherSize - 1;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsAny(IntSet other)
- {
- if (other == null || other.isEmpty() || other == this) {
- return true;
- }
- if (isEmpty()) {
- return false;
- }
-
- final ArraySet o = convert(other);
- final int[] thisElements = elements; // faster
- final int[] otherElements = o.elements; // faster
- int otherSize = o.size;
- int thisIndex = -1;
- int otherIndex = -1;
- while (thisIndex < (size - 1) && otherIndex < (otherSize - 1)) {
- thisIndex++;
- otherIndex++;
- while (thisElements[thisIndex] != otherElements[otherIndex]) {
- while (thisElements[thisIndex] > otherElements[otherIndex]) {
- if (otherIndex == otherSize - 1) {
- return false;
- }
- otherIndex++;
- }
- if (thisElements[thisIndex] == otherElements[otherIndex]) {
- break;
- }
- while (thisElements[thisIndex] < otherElements[otherIndex]) {
- if (thisIndex == size - 1) {
- return false;
- }
- thisIndex++;
- }
- }
- return true;
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsAtLeast(IntSet other, int minElements)
- {
- if (minElements < 1) {
- throw new IllegalArgumentException();
- }
- if ((size >= 0 && size < minElements) || other == null || other.isEmpty() || isEmpty()) {
- return false;
- }
- if (this == other) {
- return size() >= minElements;
- }
-
- final ArraySet o = convert(other);
- final int[] thisElements = elements; // faster
- final int[] otherElements = o.elements; // faster
- int otherSize = o.size;
- int thisIndex = -1;
- int otherIndex = -1;
- int res = 0;
- while (thisIndex < (size - 1) && otherIndex < (otherSize - 1)) {
- thisIndex++;
- otherIndex++;
- while (thisElements[thisIndex] != otherElements[otherIndex]) {
- while (thisElements[thisIndex] > otherElements[otherIndex]) {
- if (otherIndex == otherSize - 1) {
- return false;
- }
- otherIndex++;
- }
- if (thisElements[thisIndex] == otherElements[otherIndex]) {
- break;
- }
- while (thisElements[thisIndex] < otherElements[otherIndex]) {
- if (thisIndex == size - 1) {
- return false;
- }
- thisIndex++;
- }
- }
- res++;
- if (res >= minElements) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean addAll(IntSet c)
- {
- ArraySet res = union(c);
- boolean r = !equals(res);
- replaceWith(res);
- return r;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean retainAll(IntSet c)
- {
- ArraySet res = intersection(c);
- boolean r = !equals(res);
- replaceWith(res);
- return r;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean removeAll(IntSet c)
- {
- ArraySet res = difference(c);
- boolean r = !equals(res);
- replaceWith(res);
- return r;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int hashCode()
- {
- if (isEmpty()) {
- return 0;
- }
- final int[] thisElements = elements; // faster
- int h = 1;
- for (int i = 0; i < size; i++) {
- h = (h << 5) - h + thisElements[i];
- }
- return h;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof ArraySet)) {
- return super.equals(obj);
- }
- final ArraySet other = (ArraySet) obj;
- if (size != other.size) {
- return false;
- }
- final int[] thisElements = elements; // faster
- final int[] otherElements = other.elements; // faster
- for (int i = 0; i < size; i++) {
- if (thisElements[i] != otherElements[i]) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int size()
- {
- return size;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean isEmpty()
- {
- return size == 0;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void clear()
- {
- elements = null;
- size = 0;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int first()
- {
- if (isEmpty()) {
- throw new NoSuchElementException();
- }
- return elements[0];
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int last()
- {
- if (isEmpty()) {
- throw new NoSuchElementException();
- }
- return elements[size - 1];
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int intersectionSize(IntSet other)
- {
- if (isEmpty() || other == null || other.isEmpty()) {
- return 0;
- }
- if (this == other) {
- return size();
- }
-
- final ArraySet o = convert(other);
- final int[] thisElements = elements; // faster
- final int[] otherElements = o.elements; // faster
- int otherSize = o.size;
- int thisIndex = -1;
- int otherIndex = -1;
- int res = 0;
- while (thisIndex < (size - 1) && otherIndex < (otherSize - 1)) {
- thisIndex++;
- otherIndex++;
- while (thisElements[thisIndex] != otherElements[otherIndex]) {
- while (thisElements[thisIndex] > otherElements[otherIndex]) {
- if (otherIndex == otherSize - 1) {
- return res;
- }
- otherIndex++;
- }
- if (thisElements[thisIndex] == otherElements[otherIndex]) {
- break;
- }
- while (thisElements[thisIndex] < otherElements[otherIndex]) {
- if (thisIndex == size - 1) {
- return res;
- }
- thisIndex++;
- }
- }
- res++;
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ArraySet intersection(IntSet other)
- {
- if (isEmpty() || other == null || other.isEmpty()) {
- return empty();
- }
- if (this == other) {
- return clone();
- }
-
- final ArraySet o = convert(other);
- int otherSize = o.size;
- int thisIndex = -1;
- int otherIndex = -1;
- int resSize = 0;
- final int[] thisElements = elements; // faster
- final int[] otherElements = o.elements; // faster
- final int[] resElements = new int[Math.min(size, otherSize)];
- while (thisIndex < (size - 1) && otherIndex < (otherSize - 1)) {
- thisIndex++;
- otherIndex++;
- while (thisElements[thisIndex] != otherElements[otherIndex]) {
- while (thisElements[thisIndex] > otherElements[otherIndex]) {
- if (otherIndex == otherSize - 1) {
- ArraySet res = empty();
- res.elements = resElements;
- res.size = resSize;
- res.compact();
- return res;
- }
- otherIndex++;
- }
- if (thisElements[thisIndex] == otherElements[otherIndex]) {
- break;
- }
- while (thisElements[thisIndex] < otherElements[otherIndex]) {
- if (thisIndex == size - 1) {
- ArraySet res = empty();
- res.elements = resElements;
- res.size = resSize;
- res.compact();
- return res;
- }
- thisIndex++;
- }
- }
- resElements[resSize++] = thisElements[thisIndex];
- }
-
- ArraySet res = empty();
- res.elements = resElements;
- res.size = resSize;
- res.compact();
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ArraySet union(IntSet other)
- {
- if (this == other || other == null || other.isEmpty()) {
- return clone();
- }
- if (isEmpty()) {
- ArraySet cloned = convert(other);
- if (cloned == other) {
- cloned = cloned.clone();
- }
- return cloned;
- }
-
- final ArraySet o = convert(other);
- int otherSize = o.size;
- int thisIndex = -1;
- int otherIndex = -1;
- int resSize = 0;
- final int[] thisElements = elements; // faster
- final int[] otherElements = o.elements; // faster
- final int[] resElements = new int[size + otherSize];
-mainLoop:
- while (thisIndex < (size - 1) && otherIndex < (otherSize - 1)) {
- thisIndex++;
- otherIndex++;
- while (thisElements[thisIndex] != otherElements[otherIndex]) {
- while (thisElements[thisIndex] > otherElements[otherIndex]) {
- resElements[resSize++] = otherElements[otherIndex];
- if (otherIndex == otherSize - 1) {
- resElements[resSize++] = thisElements[thisIndex];
- break mainLoop;
- }
- otherIndex++;
- }
- if (thisElements[thisIndex] == otherElements[otherIndex]) {
- break;
- }
- while (thisElements[thisIndex] < otherElements[otherIndex]) {
- resElements[resSize++] = thisElements[thisIndex];
- if (thisIndex == size - 1) {
- resElements[resSize++] = otherElements[otherIndex];
- break mainLoop;
- }
- thisIndex++;
- }
- }
- resElements[resSize++] = thisElements[thisIndex];
- }
- while (thisIndex < size - 1) {
- resElements[resSize++] = thisElements[++thisIndex];
- }
- while (otherIndex < otherSize - 1) {
- resElements[resSize++] = otherElements[++otherIndex];
- }
-
- ArraySet res = empty();
- res.elements = resElements;
- res.size = resSize;
- res.compact();
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ArraySet difference(IntSet other)
- {
- if (isEmpty() || this == other) {
- return empty();
- }
- if (other == null || other.isEmpty()) {
- return clone();
- }
-
- final ArraySet o = convert(other);
- int otherSize = o.size;
- int thisIndex = -1;
- int otherIndex = -1;
- int resSize = 0;
- final int[] thisElements = elements; // faster
- final int[] otherElements = o.elements; // faster
- final int[] resElements = new int[size];
-mainLoop:
- while (thisIndex < (size - 1) && otherIndex < (otherSize - 1)) {
- thisIndex++;
- otherIndex++;
- while (thisElements[thisIndex] != otherElements[otherIndex]) {
- while (thisElements[thisIndex] > otherElements[otherIndex]) {
- if (otherIndex == otherSize - 1) {
- resElements[resSize++] = thisElements[thisIndex];
- break mainLoop;
- }
- otherIndex++;
- }
- if (thisElements[thisIndex] == otherElements[otherIndex]) {
- break;
- }
- while (thisElements[thisIndex] < otherElements[otherIndex]) {
- resElements[resSize++] = thisElements[thisIndex];
- if (thisIndex == size - 1) {
- break mainLoop;
- }
- thisIndex++;
- }
- }
- }
- while (thisIndex < size - 1) {
- resElements[resSize++] = thisElements[++thisIndex];
- }
-
- ArraySet res = empty();
- res.elements = resElements;
- res.size = resSize;
- res.compact();
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ArraySet symmetricDifference(IntSet other)
- {
- if (this == other || other == null || other.isEmpty()) {
- return clone();
- }
- if (isEmpty()) {
- return convert(other).clone();
- }
-
- final ArraySet o = convert(other);
- int otherSize = o.size;
- int thisIndex = -1;
- int otherIndex = -1;
- int resSize = 0;
- final int[] thisElements = elements; // faster
- final int[] otherElements = o.elements; // faster
- final int[] resElements = new int[size + otherSize];
-mainLoop:
- while (thisIndex < (size - 1) && otherIndex < (otherSize - 1)) {
- thisIndex++;
- otherIndex++;
- while (thisElements[thisIndex] != otherElements[otherIndex]) {
- while (thisElements[thisIndex] > otherElements[otherIndex]) {
- resElements[resSize++] = otherElements[otherIndex];
- if (otherIndex == otherSize - 1) {
- resElements[resSize++] = thisElements[thisIndex];
- break mainLoop;
- }
- otherIndex++;
- }
- if (thisElements[thisIndex] == otherElements[otherIndex]) {
- break;
- }
- while (thisElements[thisIndex] < otherElements[otherIndex]) {
- resElements[resSize++] = thisElements[thisIndex];
- if (thisIndex == size - 1) {
- resElements[resSize++] = otherElements[otherIndex];
- break mainLoop;
- }
- thisIndex++;
- }
- }
- }
- while (thisIndex < size - 1) {
- resElements[resSize++] = thisElements[++thisIndex];
- }
- while (otherIndex < otherSize - 1) {
- resElements[resSize++] = otherElements[++otherIndex];
- }
-
- ArraySet res = empty();
- res.elements = resElements;
- res.size = resSize;
- res.compact();
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void complement()
- {
- if (isEmpty()) {
- return;
- }
-
- IntIterator thisItr = clone().iterator(); // avoid concurrency
- elements = new int[complementSize()];
- final int[] thisElements = elements; // faster
- size = 0;
- int u = -1;
- while (thisItr.hasNext()) {
- int c = thisItr.next();
- while (++u < c) {
- thisElements[size++] = u;
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void fill(int from, int to)
- {
- if (from > to) {
- throw new IndexOutOfBoundsException("from: " + from + " > to: " + to);
- }
- if (from == to) {
- add(from);
- return;
- }
-
- int[] thisElements = elements; // faster
-
- if (isEmpty()) {
- size = to - from + 1;
- ensureCapacity();
- thisElements = elements;
- for (int i = 0; i < size; i++) {
- thisElements[i] = from++;
- }
- return;
- }
-
- // increase capacity, if necessary
- int posFrom = Arrays.binarySearch(thisElements, 0, size, from);
- boolean fromMissing = posFrom < 0;
- if (fromMissing) {
- posFrom = -posFrom - 1;
- }
-
- int posTo = Arrays.binarySearch(thisElements, posFrom, size, to);
- boolean toMissing = posTo < 0;
- if (toMissing) {
- posTo = -posTo - 1;
- }
-
- int delta = 0;
- if (toMissing || (fromMissing && (posFrom == posTo + 1))) {
- delta = 1;
- }
-
- int gap = to - from;
- delta += gap - (posTo - posFrom);
- if (delta > 0) {
- size += delta;
- ensureCapacity();
- thisElements = elements;
- System.arraycopy(thisElements, posTo, thisElements, posTo + delta, size - delta - posTo);
- posTo = posFrom + gap;
-
- // set values
- for (int i = posFrom; i <= posTo; i++) {
- thisElements[i] = from++;
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void clear(int from, int to)
- {
- if (isEmpty()) {
- return;
- }
- if (from > to) {
- throw new IndexOutOfBoundsException("from: " + from + " > to: " + to);
- }
- if (from == to) {
- remove(from);
- return;
- }
-
- int posFrom = Arrays.binarySearch(elements, 0, size, from);
- if (posFrom < 0) {
- posFrom = -posFrom - 1;
- }
- if (posFrom >= size) {
- return;
- }
- int posTo = Arrays.binarySearch(elements, posFrom, size, to);
- if (posTo >= 0) {
- posTo++;
- } else {
- posTo = -posTo - 1;
- }
- if (posFrom == posTo) {
- return;
- }
- System.arraycopy(elements, posTo, elements, posFrom, size - posTo);
- size -= posTo - posFrom;
- }
-
- /**
- * Convert a generic {@link IntSet} instance to an {@link ArraySet} instance
- *
- * @param c
- *
- * @return
- */
- private ArraySet convert(IntSet c)
- {
- if (c instanceof ArraySet) {
- return (ArraySet) c;
- }
-
- int[] resElements = new int[c.size()];
- int resSize = 0;
- IntIterator itr = c.iterator();
- while (itr.hasNext()) {
- resElements[resSize++] = itr.next();
- }
-
- ArraySet res = empty();
- res.elements = resElements;
- res.size = resSize;
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ArraySet convert(int... a)
- {
- int[] resElements = null;
- int resSize = 0;
- int last = -1;
- if (a != null) {
- resElements = new int[a.length];
- a = Arrays.copyOf(a, a.length);
- Arrays.sort(a);
- if (a[0] < 0) {
- throw new ArrayIndexOutOfBoundsException(Integer.toString(a[0]));
- }
- for (int i : a) {
- if (last != i) {
- resElements[resSize++] = last = i;
- }
- }
- }
-
- ArraySet res = empty();
- res.elements = resElements;
- res.size = resSize;
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ArraySet convert(Collection c)
- {
- Collection sorted;
- int[] resElements = null;
- int resSize = 0;
- int last = -1;
- if (c != null) {
- resElements = new int[c.size()];
- if (c instanceof SortedSet> && ((SortedSet>) c).comparator() == null) {
- sorted = c;
- } else {
- sorted = new ArrayList(c);
- Collections.sort((List) sorted);
- int first = ((ArrayList) sorted).get(0).intValue();
- if (first < 0) {
- throw new ArrayIndexOutOfBoundsException(Integer.toString(first));
- }
- }
- for (int i : sorted) {
- if (last != i) {
- resElements[resSize++] = last = i;
- }
- }
- }
-
- ArraySet res = empty();
- res.elements = resElements;
- res.size = resSize;
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ArraySet complemented()
- {
- ArraySet res = clone();
- res.complement();
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int get(int i)
- {
- if (i < 0 || i >= size) {
- throw new IndexOutOfBoundsException(Integer.toString(i));
- }
- return elements[i];
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int indexOf(int e)
- {
- if (e < 0) {
- throw new IllegalArgumentException("positive integer expected: " + Integer.toString(e));
- }
- int pos = Arrays.binarySearch(elements, 0, size, e);
- if (pos < 0) {
- return -1;
- }
- return pos;
- }
-}
diff --git a/extendedset/src/main/java/io/druid/extendedset/intset/BitIterator.java b/extendedset/src/main/java/io/druid/extendedset/intset/BitIterator.java
new file mode 100644
index 00000000000..7b76026361b
--- /dev/null
+++ b/extendedset/src/main/java/io/druid/extendedset/intset/BitIterator.java
@@ -0,0 +1,288 @@
+/*
+ * Licensed to Metamarkets Group Inc. (Metamarkets) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. Metamarkets licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.druid.extendedset.intset;
+
+import java.util.NoSuchElementException;
+
+// Based on the ConciseSet implementation by Alessandro Colantonio
+public final class BitIterator implements IntSet.IntIterator
+{
+ private final ImmutableConciseSet immutableConciseSet;
+
+ private boolean literalAndZeroFill;
+ private int nextIndex = 0;
+ private int nextOffset = 0;
+ private int next = -1;
+
+ BitIterator(ImmutableConciseSet immutableConciseSet)
+ {
+ this.immutableConciseSet = immutableConciseSet;
+ nextWord();
+ next = advance();
+ }
+
+ private BitIterator(
+ ImmutableConciseSet immutableConciseSet,
+ boolean literalAndZeroFill,
+ int nextIndex,
+ int nextOffset,
+ int next,
+ int literalAndZeroFillLen,
+ int literalAndZeroFillCurrent,
+ int oneFillFirstInt,
+ int oneFillLastInt,
+ int oneFillCurrent,
+ int oneFillException
+ )
+ {
+ this.immutableConciseSet = immutableConciseSet;
+ this.literalAndZeroFill = literalAndZeroFill;
+ this.nextIndex = nextIndex;
+ this.nextOffset = nextOffset;
+ this.next = next;
+ this.literalAndZeroFillLen = literalAndZeroFillLen;
+ this.literalAndZeroFillCurrent = literalAndZeroFillCurrent;
+ this.oneFillFirstInt = oneFillFirstInt;
+ this.oneFillLastInt = oneFillLastInt;
+ this.oneFillCurrent = oneFillCurrent;
+ this.oneFillException = oneFillException;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return next >= 0;
+ }
+
+ private int advance()
+ {
+ int wordExpanderNext;
+ while ((wordExpanderNext = wordExpanderAdvance()) < 0) {
+ if (nextIndex > immutableConciseSet.lastWordIndex) {
+ return -1;
+ }
+ nextWord();
+ }
+ return wordExpanderNext;
+ }
+
+ @Override
+ public int next()
+ {
+ int prev = next;
+ if (prev >= 0) {
+ next = advance();
+ return prev;
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void skipAllBefore(int element)
+ {
+ if (element <= next) {
+ return;
+ }
+ while (true) {
+ wordExpanderSkipAllBefore(element);
+ int wordExpanderNext = wordExpanderAdvance();
+ if (wordExpanderNext >= 0) {
+ next = wordExpanderNext;
+ return;
+ }
+ if (nextIndex > immutableConciseSet.lastWordIndex) {
+ next = -1;
+ return;
+ }
+ nextWord();
+ }
+ }
+
+ @Override
+ public IntSet.IntIterator clone()
+ {
+ BitIterator clone = new BitIterator(
+ immutableConciseSet,
+ literalAndZeroFill,
+ nextIndex,
+ nextOffset,
+ next,
+ literalAndZeroFillLen,
+ literalAndZeroFillCurrent,
+ oneFillFirstInt,
+ oneFillLastInt,
+ oneFillCurrent,
+ oneFillException
+ );
+ System.arraycopy(
+ literalAndZeroFillBuffer,
+ 0,
+ clone.literalAndZeroFillBuffer,
+ 0,
+ literalAndZeroFillBuffer.length
+ );
+ return clone;
+ }
+
+ private void nextWord()
+ {
+ final int word = immutableConciseSet.words.get(nextIndex++);
+ literalAndZeroFill = wordExpanderReset(nextOffset, word);
+
+ // prepare next offset
+ if (ConciseSetUtils.isLiteral(word)) {
+ nextOffset += ConciseSetUtils.MAX_LITERAL_LENGTH;
+ } else {
+ nextOffset += ConciseSetUtils.maxLiteralLengthMultiplication(ConciseSetUtils.getSequenceCount(word) + 1);
+ }
+ }
+
+ private int wordExpanderAdvance()
+ {
+ return literalAndZeroFill ? literalAndZeroFillAdvance() : oneFillAdvance();
+ }
+
+ private void wordExpanderSkipAllBefore(int i)
+ {
+ if (literalAndZeroFill) {
+ literalAndZeroFillSkipAllBefore(i);
+ } else {
+ oneFillSkipAllBefore(i);
+ }
+ }
+
+ private boolean wordExpanderReset(int offset, int word)
+ {
+ if (ConciseSetUtils.isLiteral(word)) {
+ literalAndZeroFillResetLiteral(offset, word);
+ return true;
+ } else if (ConciseSetUtils.isZeroSequence(word)) {
+ literalAndZeroFillResetZeroSequence(offset, word);
+ return true;
+ } else {
+ // one sequence
+ oneFillReset(offset, word);
+ return false;
+ }
+ }
+
+ private final int[] literalAndZeroFillBuffer = new int[ConciseSetUtils.MAX_LITERAL_LENGTH];
+ private int literalAndZeroFillLen = 0;
+ private int literalAndZeroFillCurrent = 0;
+
+ private int literalAndZeroFillAdvance()
+ {
+ if (literalAndZeroFillCurrent < literalAndZeroFillLen) {
+ return literalAndZeroFillBuffer[literalAndZeroFillCurrent++];
+ } else {
+ return -1;
+ }
+ }
+
+ private void literalAndZeroFillSkipAllBefore(int i)
+ {
+ while (literalAndZeroFillCurrent < literalAndZeroFillLen &&
+ literalAndZeroFillBuffer[literalAndZeroFillCurrent] < i) {
+ literalAndZeroFillCurrent++;
+ }
+ }
+
+ private void literalAndZeroFillResetZeroSequence(int offset, int word)
+ {
+ if (ConciseSetUtils.isSequenceWithNoBits(word)) {
+ literalAndZeroFillLen = 0;
+ literalAndZeroFillCurrent = 0;
+ } else {
+ literalAndZeroFillLen = 1;
+ literalAndZeroFillBuffer[0] = offset + ((0x3FFFFFFF & word) >>> 25) - 1;
+ literalAndZeroFillCurrent = 0;
+ }
+ }
+
+ private void literalAndZeroFillResetLiteral(int offset, int word)
+ {
+ literalAndZeroFillLen = 0;
+ for (int i = 0; i < ConciseSetUtils.MAX_LITERAL_LENGTH; i++) {
+ if ((word & (1 << i)) != 0) {
+ literalAndZeroFillBuffer[literalAndZeroFillLen++] = offset + i;
+ }
+ }
+ literalAndZeroFillCurrent = 0;
+ }
+
+ private int oneFillFirstInt = 1;
+ private int oneFillLastInt = -1;
+ private int oneFillCurrent = 0;
+ private int oneFillException = -1;
+
+ private int oneFillAdvance()
+ {
+ int oneFillCurrent = this.oneFillCurrent;
+ if (oneFillCurrent < oneFillLastInt) {
+ return oneFillDoAdvance(oneFillCurrent);
+ } else {
+ return -1;
+ }
+ }
+
+ private int oneFillDoAdvance(int oneFillCurrent)
+ {
+ oneFillCurrent++;
+ if (oneFillCurrent == oneFillException) {
+ oneFillCurrent++;
+ }
+ this.oneFillCurrent = oneFillCurrent;
+ return oneFillCurrent;
+ }
+
+ private void oneFillSkipAllBefore(int i)
+ {
+ if (i <= oneFillCurrent) {
+ return;
+ }
+ oneFillCurrent = i - 1;
+ }
+
+ private void oneFillReset(int offset, int word)
+ {
+ if (!ConciseSetUtils.isOneSequence(word)) {
+ throw new RuntimeException("NOT a sequence of ones!");
+ }
+ oneFillFirstInt = offset;
+ oneFillLastInt = offset + ConciseSetUtils.maxLiteralLengthMultiplication(ConciseSetUtils.getSequenceCount(word) + 1) - 1;
+
+ oneFillException = offset + ((0x3FFFFFFF & word) >>> 25) - 1;
+ if (oneFillException == oneFillFirstInt) {
+ oneFillFirstInt++;
+ }
+ if (oneFillException == oneFillLastInt) {
+ oneFillLastInt--;
+ }
+
+ oneFillCurrent = oneFillFirstInt - 1;
+ }
+}
diff --git a/extendedset/src/main/java/io/druid/extendedset/intset/ConciseSet.java b/extendedset/src/main/java/io/druid/extendedset/intset/ConciseSet.java
index b3f3d87bc0c..208f02affc6 100755
--- a/extendedset/src/main/java/io/druid/extendedset/intset/ConciseSet.java
+++ b/extendedset/src/main/java/io/druid/extendedset/intset/ConciseSet.java
@@ -20,8 +20,6 @@
package io.druid.extendedset.intset;
-import io.druid.extendedset.utilities.BitCount;
-
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
@@ -71,11 +69,6 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
* true
if the class must simulate the behavior of WAH
*/
private final boolean simulateWAH;
- /**
- * User for fail-fast iterator. It counts the number of operations
- * that do modify {@link #words}
- */
- protected transient volatile int modCount = 0;
/**
* This is the compressed bitmap, that is a collection of words. For each
* word:
@@ -317,7 +310,7 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
*/
private static int getLiteralBitCount(int word)
{
- return BitCount.count(getLiteralBits(word));
+ return Integer.bitCount(getLiteralBits(word));
}
/**
@@ -371,7 +364,6 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
*/
private void reset()
{
- modCount++;
words = null;
last = -1;
size = 0;
@@ -392,7 +384,6 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
ConciseSet res = empty();
res.last = last;
res.lastWordIndex = lastWordIndex;
- res.modCount = 0;
res.size = size;
res.words = Arrays.copyOf(words, lastWordIndex + 1);
return res;
@@ -994,7 +985,7 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
if ((w & (1 << bitPosition)) == 0) {
return -1;
}
- return index + BitCount.count(w & ~(0xFFFFFFFF << bitPosition));
+ return index + Integer.bitCount(w & ~(0xFFFFFFFF << bitPosition));
}
blockIndex--;
index += getLiteralBitCount(w);
@@ -1011,7 +1002,7 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
if ((l & (1 << bitPosition)) == 0) {
return -1;
}
- return index + BitCount.count(l & ~(0xFFFFFFFF << bitPosition));
+ return index + Integer.bitCount(l & ~(0xFFFFFFFF << bitPosition));
}
// if we are in the middle of a sequence of 1's, the bit already exist
@@ -1116,7 +1107,6 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
@Override
public void complement()
{
- modCount++;
if (isEmpty()) {
return;
@@ -1214,23 +1204,7 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
public IntIterator iterator()
{
if (isEmpty()) {
- return new IntIterator()
- {
- @Override
- public void skipAllBefore(int element) {/*empty*/}
-
- @Override
- public boolean hasNext() {return false;}
-
- @Override
- public int next() {throw new NoSuchElementException();}
-
- @Override
- public void remove() {throw new UnsupportedOperationException();}
-
- @Override
- public IntIterator clone() {throw new UnsupportedOperationException();}
- };
+ return EmptyIntIterator.instance();
}
return new BitIterator();
}
@@ -1242,23 +1216,7 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
public IntIterator descendingIterator()
{
if (isEmpty()) {
- return new IntIterator()
- {
- @Override
- public void skipAllBefore(int element) {/*empty*/}
-
- @Override
- public boolean hasNext() {return false;}
-
- @Override
- public int next() {throw new NoSuchElementException();}
-
- @Override
- public void remove() {throw new UnsupportedOperationException();}
-
- @Override
- public IntIterator clone() {throw new UnsupportedOperationException();}
- };
+ return EmptyIntIterator.instance();
}
return new ReverseBitIterator();
}
@@ -1380,7 +1338,6 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
this.size = other.size;
this.last = other.last;
this.lastWordIndex = other.lastWordIndex;
- this.modCount++;
return true;
}
@@ -1390,7 +1347,6 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
@Override
public boolean add(int e)
{
- modCount++;
// range check
if (e < ConciseSetUtils.MIN_ALLOWED_SET_BIT || e > ConciseSetUtils.MAX_ALLOWED_INTEGER) {
@@ -1487,7 +1443,6 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
@Override
public boolean remove(int o)
{
- modCount++;
if (isEmpty()) {
return false;
@@ -1918,7 +1873,6 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
@Override
public boolean retainAll(IntSet c)
{
- modCount++;
if (isEmpty() || c == this) {
return false;
@@ -1949,7 +1903,6 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
@Override
public boolean addAll(IntSet c)
{
- modCount++;
if (c == null || c.isEmpty() || this == c) {
return false;
}
@@ -1968,7 +1921,6 @@ public class ConciseSet extends AbstractIntSet implements java.io.Serializable
@Override
public boolean removeAll(IntSet c)
{
- modCount++;
if (c == null || c.isEmpty() || isEmpty()) {
return false;
diff --git a/extendedset/src/main/java/io/druid/extendedset/intset/ConciseSetUtils.java b/extendedset/src/main/java/io/druid/extendedset/intset/ConciseSetUtils.java
index b9465d9dc3d..add784c904c 100755
--- a/extendedset/src/main/java/io/druid/extendedset/intset/ConciseSetUtils.java
+++ b/extendedset/src/main/java/io/druid/extendedset/intset/ConciseSetUtils.java
@@ -1,9 +1,5 @@
package io.druid.extendedset.intset;
-import io.druid.extendedset.utilities.BitCount;
-
-import java.util.NoSuchElementException;
-
/**
*/
public class ConciseSetUtils
@@ -108,7 +104,7 @@ public class ConciseSetUtils
*/
public static int maxLiteralLengthMultiplication(int n)
{
- return (n << 5) - n;
+ return n * 31;
}
/**
@@ -132,9 +128,8 @@ public class ConciseSetUtils
*/
public static boolean isLiteral(int word)
{
- // "word" must be 1*
- // NOTE: this is faster than "return (word & 0x80000000) == 0x80000000"
- return (word & 0x80000000) != 0;
+ // the highest one bit should be 1, which means the word as a number is negative
+ return word < 0;
}
/**
@@ -173,7 +168,7 @@ public class ConciseSetUtils
* @param word word to check
*
* @return true
if the given word is a sequence of 0's or 1's
- * but with no (un)set bit
+ * but with no (un)set bit
*/
public static boolean isSequenceWithNoBits(int word)
{
@@ -205,7 +200,7 @@ public class ConciseSetUtils
* @param word word to check
*
* @return the sequence corresponding to the given sequence and with no
- * (un)set bits
+ * (un)set bits
*/
public static int getSequenceWithNoBits(int word)
{
@@ -224,7 +219,7 @@ public class ConciseSetUtils
* @param word word to check
*
* @return the literal contained within the given word, with the most
- * significant bit set to 1.
+ * significant bit set to 1.
*/
public static int getLiteral(int word, boolean simulateWAH)
{
@@ -273,7 +268,7 @@ public class ConciseSetUtils
* @param word sequence word to check
*
* @return the position of the set bit, from 0 to 31. If the sequence has no
- * set/unset bit, returns -1.
+ * set/unset bit, returns -1.
*/
public static int getFlippedBit(int word)
{
@@ -284,7 +279,7 @@ public class ConciseSetUtils
public static int flipBitAsBinaryString(int flipBit)
{
- return ((Number) Math.pow(2, flipBit)).intValue();
+ return 1 << flipBit;
}
/**
@@ -296,7 +291,7 @@ public class ConciseSetUtils
*/
public static int getLiteralBitCount(int word)
{
- return BitCount.count(getLiteralBits(word));
+ return Integer.bitCount(getLiteralBits(word));
}
/**
@@ -313,17 +308,19 @@ public class ConciseSetUtils
public static boolean isAllOnesLiteral(int word)
{
- return (word & -1) == -1;
+ return word == -1;
}
public static boolean isAllZerosLiteral(int word)
{
- return (word | 0x80000000) == 0x80000000;
+ // Either 0x80000000 ("all zeros literal" as it is) or 0, that is "zero sequence of 1 block" = 31 bits,
+ // i. e. semantically equivalent to "all zeros literal".
+ return (word & ALL_ONES_WITHOUT_MSB) == 0;
}
public static boolean isLiteralWithSingleZeroBit(int word)
{
- return isLiteral(word) && (Integer.bitCount(~word) == 1);
+ return isLiteral(word) && Integer.bitCount(word) == 31;
}
public static boolean isLiteralWithSingleOneBit(int word)
@@ -338,226 +335,6 @@ public class ConciseSetUtils
public static int onesUntil(int bit)
{
- return 0x80000000 | ((1 << bit) - 1);
- }
-
- public static LiteralAndZeroFillExpander newLiteralAndZeroFillExpander()
- {
- return new LiteralAndZeroFillExpander();
- }
-
- public static OneFillExpander newOneFillExpander()
- {
- return new OneFillExpander();
- }
-
- public interface WordExpander
- {
- public boolean hasNext();
-
- public boolean hasPrevious();
-
- public int next();
-
- public int previous();
-
- public void skipAllAfter(int i);
-
- public void skipAllBefore(int i);
-
- public void reset(int offset, int word, boolean fromBeginning);
-
- public WordExpander clone();
- }
-
- /**
- * Iterator over the bits of literal and zero-fill words
- */
- public static class LiteralAndZeroFillExpander implements WordExpander
- {
- final int[] buffer = new int[MAX_LITERAL_LENGTH];
- int len = 0;
- int current = 0;
-
- @Override
- public boolean hasNext()
- {
- return current < len;
- }
-
- @Override
- public boolean hasPrevious()
- {
- return current > 0;
- }
-
- @Override
- public int next()
- {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- return buffer[current++];
- }
-
- @Override
- public int previous()
- {
- if (!hasPrevious()) {
- throw new NoSuchElementException();
- }
- return buffer[--current];
- }
-
- @Override
- public void skipAllAfter(int i)
- {
- while (hasPrevious() && buffer[current - 1] > i) {
- current--;
- }
- }
-
- @Override
- public void skipAllBefore(int i)
- {
- while (hasNext() && buffer[current] < i) {
- current++;
- }
- }
-
- @Override
- public void reset(int offset, int word, boolean fromBeginning)
- {
- if (isLiteral(word)) {
- len = 0;
- for (int i = 0; i < MAX_LITERAL_LENGTH; i++) {
- if ((word & (1 << i)) != 0) {
- buffer[len++] = offset + i;
- }
- }
- current = fromBeginning ? 0 : len;
- } else {
- if (isZeroSequence(word)) {
- if (isSequenceWithNoBits(word)) {
- len = 0;
- current = 0;
- } else {
- len = 1;
- buffer[0] = offset + ((0x3FFFFFFF & word) >>> 25) - 1;
- current = fromBeginning ? 0 : 1;
- }
- } else {
- throw new RuntimeException("sequence of ones!");
- }
- }
- }
-
- @Override
- public WordExpander clone()
- {
- LiteralAndZeroFillExpander retVal = new LiteralAndZeroFillExpander();
- System.arraycopy(buffer, 0, retVal.buffer, 0, buffer.length);
- retVal.len = len;
- retVal.current = current;
- return retVal;
- }
- }
-
- /**
- * Iterator over the bits of one-fill words
- */
- public static class OneFillExpander implements WordExpander
- {
- int firstInt = 1;
- int lastInt = -1;
- int current = 0;
- int exception = -1;
-
- @Override
- public boolean hasNext()
- {
- return current < lastInt;
- }
-
- @Override
- public boolean hasPrevious()
- {
- return current > firstInt;
- }
-
- @Override
- public int next()
- {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- current++;
- if (current == exception) {
- current++;
- }
- return current;
- }
-
- @Override
- public int previous()
- {
- if (!hasPrevious()) {
- throw new NoSuchElementException();
- }
- current--;
- if (current == exception) {
- current--;
- }
- return current;
- }
-
- @Override
- public void skipAllAfter(int i)
- {
- if (i >= current) {
- return;
- }
- current = i + 1;
- }
-
- @Override
- public void skipAllBefore(int i)
- {
- if (i <= current) {
- return;
- }
- current = i - 1;
- }
-
- @Override
- public void reset(int offset, int word, boolean fromBeginning)
- {
- if (!isOneSequence(word)) {
- throw new RuntimeException("NOT a sequence of ones!");
- }
- firstInt = offset;
- lastInt = offset + maxLiteralLengthMultiplication(getSequenceCount(word) + 1) - 1;
-
- exception = offset + ((0x3FFFFFFF & word) >>> 25) - 1;
- if (exception == firstInt) {
- firstInt++;
- }
- if (exception == lastInt) {
- lastInt--;
- }
-
- current = fromBeginning ? (firstInt - 1) : (lastInt + 1);
- }
-
- @Override
- public WordExpander clone()
- {
- OneFillExpander retVal = new OneFillExpander();
- retVal.firstInt = firstInt;
- retVal.lastInt = lastInt;
- retVal.current = current;
- retVal.exception = exception;
- return retVal;
- }
+ return 0x80000000 | ((1<
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package io.druid.extendedset.intset;
-
-
-import io.druid.extendedset.utilities.BitCount;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.Formatter;
-import java.util.Locale;
-import java.util.NoSuchElementException;
-
-/**
- * An {@link IntSet} implementation, representing a set of integers, based on an
- * uncompressed bitmap.
- *
- * It actually is an extension of {@link BitSet}. More specifically, union and
- * intersection operations are mainly derived from the code of {@link BitSet} to
- * provide bitwise "or" and "and".
- *
- * The iterator implemented for this class allows for modifications during the
- * iteration, that is it is possible to add/remove elements through
- * {@link #add(int)}, {@link #remove(int)}, {@link #addAll(IntSet)},
- * {@link #removeAll(IntSet)}, {@link #retainAll(IntSet)}, etc.. In this case,
- * {@link IntIterator#next()} returns the first integral greater than the last
- * visited one.
- *
- * @author Alessandro Colantonio
- * @version $Id$
- */
-public class FastSet extends AbstractIntSet implements java.io.Serializable
-{
- /**
- * generated serial ID
- */
- private static final long serialVersionUID = 6519808981110513440L;
-
- /**
- * number of bits within each word
- */
- private final static int WORD_SIZE = 32;
-
- /**
- * 32-bit string of all 1's
- */
- private static final int ALL_ONES_WORD = 0xFFFFFFFF;
-
- /**
- * all bits, grouped in blocks of length 32
- */
- private int[] words;
-
- /**
- * index of the first empty word, that is the number of words in the logical
- * size of this {@link FastSet}
- */
- private transient int firstEmptyWord;
-
- /**
- * cached set size (only for fast size() call). When -1, the cache is invalid
- */
- private transient int size;
-
- /**
- * Creates a new, empty set.
- */
- public FastSet()
- {
- clear();
- }
-
- /**
- * Creates a new, empty set. It preallocates the space for
- * maxWordsInUse
words.
- */
- private FastSet(int wordsToAllocate)
- {
- firstEmptyWord = 0;
- size = 0;
- words = new int[wordsToAllocate];
- }
-
- /**
- * Given a number, it returns the multiplication by the number of bits for each block
- */
- private static int multiplyByWordSize(int i)
- {
- return i << 5; // i * WORD_SIZE;
- }
-
- /**
- * Given a bit index, it returns the index of the word containing it
- */
- private static int wordIndex(int bitIndex)
- {
- if (bitIndex < 0) {
- throw new IndexOutOfBoundsException("index < 0: " + bitIndex);
- }
- return bitIndex >> 5;
- }
-
- /**
- * Given a bit index, it returns the index of the word containing it
- */
- private static int wordIndexNoCheck(int bitIndex)
- {
- return bitIndex >> 5;
- }
-
- /**
- * Generates the 32-bit binary representation of a given word (debug only)
- *
- * @param word word to represent
- *
- * @return 32-character string that represents the given word
- */
- private static String toBinaryString(int word)
- {
- String lsb = Integer.toBinaryString(word);
- StringBuilder pad = new StringBuilder();
- for (int i = lsb.length(); i < 32; i++) {
- pad.append('0');
- }
- return pad.append(lsb).toString();
- }
-
- /**
- * Sets the field {@link #firstEmptyWord} with the logical size in words of the
- * bit set.
- */
- private void fixFirstEmptyWord()
- {
- int i = firstEmptyWord - 1;
- final int[] localWords = words; // faster
- while (i >= 0 && localWords[i] == 0) {
- i--;
- }
- firstEmptyWord = i + 1;
- }
-
- /**
- * Ensures that the {@link FastSet} can hold enough words.
- *
- * @param wordsRequired the minimum acceptable number of words.
- */
- private void ensureCapacity(int wordsRequired)
- {
- if (words.length >= wordsRequired) {
- return;
- }
- int newLength = Math.max(words.length << 1, wordsRequired);
- words = Arrays.copyOf(words, newLength);
- }
-
- /**
- * Ensures that the {@link FastSet} can accommodate a given word index
- *
- * @param wordIndex the index to be accommodated.
- */
- private void expandTo(int wordIndex)
- {
- int wordsRequired = wordIndex + 1;
- if (firstEmptyWord < wordsRequired) {
- ensureCapacity(wordsRequired);
- firstEmptyWord = wordsRequired;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public FastSet clone()
- {
- // NOTE: do not use super.clone() since it is 10 times slower!
- FastSet res = new FastSet();
- res.firstEmptyWord = firstEmptyWord;
- res.size = size;
- res.words = Arrays.copyOf(words, firstEmptyWord);
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int hashCode()
- {
- int h = 1;
- final int[] localWords = words; // faster
- for (int i = 0; i < firstEmptyWord; i++) {
- h = (h << 5) - h + localWords[i];
- }
- return h;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof FastSet)) {
- return super.equals(obj);
- }
-
- final FastSet other = (FastSet) obj;
- if (firstEmptyWord != other.firstEmptyWord) {
- return false;
- }
- final int[] localWords = words; // faster
- final int[] localOtherWords = other.words; // faster
- for (int i = 0; i < firstEmptyWord; i++) {
- if (localWords[i] != localOtherWords[i]) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean isEmpty()
- {
- return firstEmptyWord == 0;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int size()
- {
- // check if the cached size is invalid
- if (size < 0) {
- size = BitCount.count(words, firstEmptyWord);
- }
- return size;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean add(int i)
- {
- int wordIndex = wordIndex(i);
- expandTo(wordIndex);
- int before = words[wordIndex];
- words[wordIndex] |= (1 << i);
- if (before != words[wordIndex]) {
- if (size >= 0) {
- size++;
- }
- return true;
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean remove(int i)
- {
- if (i < 0) {
- return false;
- }
-
- int wordIndex = wordIndex(i);
- if (wordIndex >= firstEmptyWord) {
- return false;
- }
- int before = words[wordIndex];
- words[wordIndex] &= ~(1 << i);
- if (before != words[wordIndex]) {
- if (size >= 0) {
- size--;
- }
- fixFirstEmptyWord();
- return true;
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean addAll(IntSet c)
- {
- if (c == null || c.isEmpty() || this == c) {
- return false;
- }
-
- final FastSet other = convert(c);
-
- int wordsInCommon = Math.min(firstEmptyWord, other.firstEmptyWord);
-
- boolean modified = false;
- if (firstEmptyWord < other.firstEmptyWord) {
- modified = true;
- ensureCapacity(other.firstEmptyWord);
- firstEmptyWord = other.firstEmptyWord;
- }
-
- final int[] localWords = words; // faster
- final int[] localOtherWords = other.words; // faster
-
- // Perform logical OR on words in common
- for (int i = 0; i < wordsInCommon; i++) {
- int before = localWords[i];
- localWords[i] |= localOtherWords[i];
- modified = modified || before != localWords[i];
- }
-
- // Copy any remaining words
- if (wordsInCommon < other.firstEmptyWord) {
- modified = true;
- System.arraycopy(
- other.words, wordsInCommon, words,
- wordsInCommon, firstEmptyWord - wordsInCommon
- );
- }
- if (modified) {
- size = -1;
- }
- return modified;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean removeAll(IntSet c)
- {
- if (c == null || c.isEmpty() || isEmpty()) {
- return false;
- }
- if (c == this) {
- clear();
- return true;
- }
-
- final FastSet other = convert(c);
- final int[] localWords = words; // faster
- final int[] localOtherWords = other.words; // faster
-
- // Perform logical (a & !b) on words in common
- boolean modified = false;
- for (int i = Math.min(firstEmptyWord, other.firstEmptyWord) - 1; i >= 0; i--) {
- int before = localWords[i];
- localWords[i] &= ~localOtherWords[i];
- modified = modified || before != localWords[i];
- }
- if (modified) {
- fixFirstEmptyWord();
- size = -1;
- }
- return modified;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean retainAll(IntSet c)
- {
- if (isEmpty() || c == this) {
- return false;
- }
- if (c == null || c.isEmpty()) {
- clear();
- return true;
- }
-
- final FastSet other = convert(c);
- final int[] localWords = words; // faster
- final int[] localOtherWords = other.words; // faster
-
- boolean modified = false;
- if (firstEmptyWord > other.firstEmptyWord) {
- modified = true;
- while (firstEmptyWord > other.firstEmptyWord) {
- localWords[--firstEmptyWord] = 0;
- }
- }
-
- // Perform logical AND on words in common
- for (int i = 0; i < firstEmptyWord; i++) {
- int before = localWords[i];
- localWords[i] &= localOtherWords[i];
- modified = modified || before != localWords[i];
- }
- if (modified) {
- fixFirstEmptyWord();
- size = -1;
- }
- return modified;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void clear()
- {
- words = new int[10];
- firstEmptyWord = 0;
- size = 0;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean contains(int i)
- {
- if (isEmpty() || i < 0) {
- return false;
- }
- int wordIndex = wordIndexNoCheck(i);
- return (wordIndex < firstEmptyWord)
- && ((words[wordIndex] & (1 << i)) != 0);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsAll(IntSet c)
- {
- if (c == null || c.isEmpty() || c == this) {
- return true;
- }
- if (isEmpty()) {
- return false;
- }
-
- final FastSet other = convert(c);
-
- if (other.firstEmptyWord > firstEmptyWord) {
- return false;
- }
-
- final int[] localWords = words; // faster
- final int[] localOtherWords = other.words; // faster
- for (int i = 0; i < other.firstEmptyWord; i++) {
- int o = localOtherWords[i];
- if ((localWords[i] & o) != o) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsAtLeast(IntSet c, int minElements)
- {
- if (minElements < 1) {
- throw new IllegalArgumentException();
- }
- if ((size >= 0 && size < minElements) || c == null || c.isEmpty() || isEmpty()) {
- return false;
- }
- if (this == c) {
- return size() >= minElements;
- }
-
- final FastSet other = convert(c);
- final int[] localWords = words; // faster
- final int[] localOtherWords = other.words; // faster
-
- int count = 0;
- for (int i = Math.min(firstEmptyWord, other.firstEmptyWord) - 1; i >= 0; i--) {
- count += BitCount.count(localWords[i] & localOtherWords[i]);
- if (count >= minElements) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsAny(IntSet c)
- {
- if (c == null || c.isEmpty() || c == this) {
- return true;
- }
- if (isEmpty()) {
- return false;
- }
-
- final FastSet other = convert(c);
- final int[] localWords = words; // faster
- final int[] localOtherWords = other.words; // faster
-
- for (int i = Math.min(firstEmptyWord, other.firstEmptyWord) - 1; i >= 0; i--) {
- if ((localWords[i] & localOtherWords[i]) != 0) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int intersectionSize(IntSet c)
- {
- if (c == null || c.isEmpty()) {
- return 0;
- }
- if (c == this) {
- return size();
- }
- if (isEmpty()) {
- return 0;
- }
-
- final FastSet other = convert(c);
- final int[] localWords = words; // faster
- final int[] localOtherWords = other.words; // faster
-
- int count = 0;
- for (int i = Math.min(firstEmptyWord, other.firstEmptyWord) - 1; i >= 0; i--) {
- count += BitCount.count(localWords[i] & localOtherWords[i]);
- }
- return count;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IntIterator iterator()
- {
- return new BitIterator();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IntIterator descendingIterator()
- {
- return new ReverseBitIterator();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int last()
- {
- if (isEmpty()) {
- throw new NoSuchElementException();
- }
- return multiplyByWordSize(firstEmptyWord - 1)
- + (WORD_SIZE - Integer.numberOfLeadingZeros(words[firstEmptyWord - 1])) - 1;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void complement()
- {
- if (isEmpty()) {
- return;
- }
- if (size > 0) {
- size = last() - size + 1;
- }
- int lastWordMask = ALL_ONES_WORD >>> Integer.numberOfLeadingZeros(words[firstEmptyWord - 1]);
- final int[] localWords = words; // faster
- for (int i = 0; i < firstEmptyWord - 1; i++) {
- localWords[i] ^= ALL_ONES_WORD;
- }
- localWords[firstEmptyWord - 1] ^= lastWordMask;
- fixFirstEmptyWord();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public FastSet complemented()
- {
- FastSet clone = clone();
- clone.complement();
- return clone;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public FastSet empty()
- {
- return new FastSet();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public double bitmapCompressionRatio()
- {
- if (isEmpty()) {
- return 0D;
- }
- return 1D;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public double collectionCompressionRatio()
- {
- if (isEmpty()) {
- return 0D;
- }
- return (double) firstEmptyWord / size();
- }
-
- /**
- * Convert a given collection to a {@link FastSet} instance
- */
- private FastSet convert(IntSet c)
- {
- if (c instanceof FastSet) {
- return (FastSet) c;
- }
- if (c == null) {
- return new FastSet();
- }
-
- FastSet res = new FastSet();
- IntIterator itr = c.iterator();
- while (itr.hasNext()) {
- res.add(itr.next());
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public FastSet convert(Collection c)
- {
- FastSet res = empty();
- if (c != null) {
- for (int i : c) {
- res.add(i);
- }
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public FastSet convert(int... a)
- {
- FastSet res = new FastSet();
- if (a != null) {
- for (int i : a) {
- res.add(i);
- }
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void fill(int fromIndex, int toIndex)
- {
- if (fromIndex > toIndex) {
- throw new IndexOutOfBoundsException(
- "fromIndex: " + fromIndex
- + " > toIndex: " + toIndex
- );
- }
- if (fromIndex == toIndex) {
- add(fromIndex);
- return;
- }
-
- // Increase capacity if necessary
- int startWordIndex = wordIndex(fromIndex);
- int endWordIndex = wordIndex(toIndex);
- expandTo(endWordIndex);
-
- final int[] localWords = words; // faster
-
- boolean modified = false;
- int firstWordMask = ALL_ONES_WORD << fromIndex;
- int lastWordMask = ALL_ONES_WORD >>> -(toIndex + 1);
- if (startWordIndex == endWordIndex) {
- // Case 1: One word
- int before = localWords[startWordIndex];
- localWords[startWordIndex] |= (firstWordMask & lastWordMask);
- modified = localWords[startWordIndex] != before;
- } else {
- // Case 2: Multiple words
- // Handle first word
- int before = localWords[startWordIndex];
- localWords[startWordIndex] |= firstWordMask;
- modified = localWords[startWordIndex] != before;
-
- // Handle intermediate words, if any
- for (int i = startWordIndex + 1; i < endWordIndex; i++) {
- modified = modified || localWords[i] != ALL_ONES_WORD;
- localWords[i] = ALL_ONES_WORD;
- }
-
- // Handle last word
- before = localWords[endWordIndex];
- localWords[endWordIndex] |= lastWordMask;
- modified = modified || localWords[endWordIndex] != before;
- }
- if (modified) {
- size = -1;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void clear(int fromIndex, int toIndex)
- {
- if (fromIndex > toIndex) {
- throw new IndexOutOfBoundsException(
- "fromIndex: " + fromIndex
- + " > toIndex: " + toIndex
- );
- }
- if (fromIndex == toIndex) {
- remove(fromIndex);
- return;
- }
-
- int startWordIndex = wordIndex(fromIndex);
- if (startWordIndex >= firstEmptyWord) {
- return;
- }
-
- int endWordIndex = wordIndex(toIndex);
- if (endWordIndex >= firstEmptyWord) {
- toIndex = last();
- endWordIndex = firstEmptyWord - 1;
- }
-
- final int[] localWords = words; // faster
-
- boolean modified = false;
- int firstWordMask = ALL_ONES_WORD << fromIndex;
- int lastWordMask = ALL_ONES_WORD >>> -(toIndex + 1);
- if (startWordIndex == endWordIndex) {
- // Case 1: One word
- int before = localWords[startWordIndex];
- localWords[startWordIndex] &= ~(firstWordMask & lastWordMask);
- modified = localWords[startWordIndex] != before;
- } else {
- // Case 2: Multiple words
- // Handle first word
- int before = localWords[startWordIndex];
- localWords[startWordIndex] &= ~firstWordMask;
- modified = localWords[startWordIndex] != before;
-
- // Handle intermediate words, if any
- for (int i = startWordIndex + 1; i < endWordIndex; i++) {
- modified = modified || localWords[i] != 0;
- localWords[i] = 0;
- }
-
- // Handle last word
- before = localWords[endWordIndex];
- localWords[endWordIndex] &= ~lastWordMask;
- modified = modified || localWords[endWordIndex] != before;
- }
- if (modified) {
- fixFirstEmptyWord();
- size = -1;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void flip(int e)
- {
- int wordIndex = wordIndex(e);
- expandTo(wordIndex);
- int mask = (1 << e);
- words[wordIndex] ^= mask;
- fixFirstEmptyWord();
- if (size >= 0) {
- if ((words[wordIndex] & mask) == 0) {
- size--;
- } else {
- size++;
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int compareTo(IntSet o)
- {
- // empty set cases
- if (this.isEmpty() && o.isEmpty()) {
- return 0;
- }
- if (this.isEmpty()) {
- return -1;
- }
- if (o.isEmpty()) {
- return 1;
- }
-
- final FastSet other = convert(o);
- final int[] localWords = words; // faster
- final int[] localOtherWords = other.words; // faster
-
- if (firstEmptyWord > other.firstEmptyWord) {
- return 1;
- }
- if (firstEmptyWord < other.firstEmptyWord) {
- return -1;
- }
- for (int i = firstEmptyWord - 1; i >= 0; i--) {
- long w1 = localWords[i] & 0xFFFFFFFFL;
- long w2 = localOtherWords[i] & 0xFFFFFFFFL;
- int res = w1 < w2 ? -1 : (w1 > w2 ? 1 : 0);
- if (res != 0) {
- return res;
- }
- }
- return 0;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int get(int index)
- {
- if (index < 0) {
- throw new IndexOutOfBoundsException();
- }
-
- int count = 0;
- final int[] localWords = words; // faster
- for (int j = 0; j < firstEmptyWord; j++) {
- int w = localWords[j];
- int current = BitCount.count(w);
- if (index < count + current) {
- int bit = -1;
- for (int skip = index - count; skip >= 0; skip--) {
- bit = Integer.numberOfTrailingZeros(w & (ALL_ONES_WORD << (bit + 1)));
- }
- return multiplyByWordSize(j) + bit;
- }
- count += current;
- }
- throw new NoSuchElementException();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int indexOf(int e)
- {
- if (e < 0) {
- throw new IllegalArgumentException("positive integer expected: " + Integer.toString(e));
- }
- if (isEmpty()) {
- return -1;
- }
-
- int index = wordIndex(e);
- if (index >= firstEmptyWord || (words[index] & (1 << e)) == 0) {
- return -1;
- }
- int count = BitCount.count(words, index);
- count += BitCount.count(words[index] & ~(ALL_ONES_WORD << e));
- return count;
-
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public FastSet intersection(IntSet other)
- {
- if (isEmpty() || other == null || other.isEmpty()) {
- return empty();
- }
- if (other == this) {
- return clone();
- }
-
- final FastSet o = convert(other);
- FastSet res = new FastSet(Math.min(firstEmptyWord, o.firstEmptyWord));
- res.firstEmptyWord = res.words.length;
-
- final int[] localWords = words; // faster
- final int[] localOtherWords = o.words; // faster
- final int[] localResWords = res.words; // faster
-
- for (int i = 0; i < res.firstEmptyWord; i++) {
- localResWords[i] = localWords[i] & localOtherWords[i];
- }
- res.fixFirstEmptyWord();
- res.size = -1;
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public FastSet union(IntSet other)
- {
- if (other == null || other.isEmpty() || this == other) {
- return clone();
- }
-
- final FastSet o = convert(other);
- if (isEmpty()) {
- return o.clone();
- }
-
- FastSet res = new FastSet(Math.max(firstEmptyWord, o.firstEmptyWord));
- res.firstEmptyWord = res.words.length;
- final int wordsInCommon = Math.min(firstEmptyWord, o.firstEmptyWord);
-
- final int[] localWords = words; // faster
- final int[] localOtherWords = o.words; // faster
- final int[] localResWords = res.words; // faster
-
- for (int i = 0; i < wordsInCommon; i++) {
- localResWords[i] = localWords[i] | localOtherWords[i];
- }
-
- if (wordsInCommon < firstEmptyWord) {
- System.arraycopy(
- localWords, wordsInCommon, localResWords, wordsInCommon,
- res.firstEmptyWord - wordsInCommon
- );
- }
- if (wordsInCommon < o.firstEmptyWord) {
- System.arraycopy(
- localOtherWords, wordsInCommon, localResWords, wordsInCommon,
- res.firstEmptyWord - wordsInCommon
- );
- }
- res.size = -1;
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public FastSet difference(IntSet other)
- {
- if (other == null || other.isEmpty()) {
- return clone();
- }
- if (other == this || isEmpty()) {
- return empty();
- }
-
- final FastSet o = convert(other);
- FastSet res = new FastSet(firstEmptyWord);
- res.firstEmptyWord = firstEmptyWord;
-
- final int[] localWords = words; // faster
- final int[] localOtherWords = o.words; // faster
- final int[] localResWords = res.words; // faster
-
- int i = 0;
- final int m = Math.min(firstEmptyWord, o.firstEmptyWord);
- for (; i < m; i++) {
- localResWords[i] = localWords[i] & ~localOtherWords[i];
- }
- if (i < firstEmptyWord) {
- System.arraycopy(localWords, i, localResWords, i, firstEmptyWord - i);
- } else {
- res.fixFirstEmptyWord();
- }
- res.size = -1;
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public FastSet symmetricDifference(IntSet other)
- {
- if (other == null || other.isEmpty()) {
- return clone();
- }
- if (other == this) {
- return empty();
- }
-
- final FastSet o = convert(other);
- if (isEmpty()) {
- return o.clone();
- }
-
- FastSet res = new FastSet(Math.max(firstEmptyWord, o.firstEmptyWord));
- res.firstEmptyWord = res.words.length;
- final int wordsInCommon = Math.min(firstEmptyWord, o.firstEmptyWord);
-
- final int[] localWords = words; // faster
- final int[] localOtherWords = o.words; // faster
- final int[] localResWords = res.words; // faster
-
- for (int i = 0; i < wordsInCommon; i++) {
- localResWords[i] = localWords[i] ^ localOtherWords[i];
- }
-
- if (wordsInCommon < firstEmptyWord) {
- System.arraycopy(
- localWords, wordsInCommon, localResWords, wordsInCommon,
- res.firstEmptyWord - wordsInCommon
- );
- } else if (wordsInCommon < o.firstEmptyWord) {
- System.arraycopy(
- localOtherWords, wordsInCommon, localResWords, wordsInCommon,
- res.firstEmptyWord - wordsInCommon
- );
- } else {
- res.fixFirstEmptyWord();
- }
- res.size = -1;
- return res;
- }
-
- /**
- * Save the state of the {@link ConciseSet}instance to a stream
- */
- private void writeObject(ObjectOutputStream s) throws IOException
- {
- assert words != null;
- if (firstEmptyWord < words.length) {
- words = Arrays.copyOf(words, firstEmptyWord);
- }
- s.defaultWriteObject();
- }
-
- /**
- * Reconstruct the {@link ConciseSet} instance from a stream
- */
- private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException
- {
- s.defaultReadObject();
- firstEmptyWord = words.length;
- size = -1;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String debugInfo()
- {
- final StringBuilder s = new StringBuilder("INTERNAL REPRESENTATION:\n");
- final Formatter f = new Formatter(s, Locale.ENGLISH);
-
- if (isEmpty()) {
- return s.append("null\n").toString();
- }
-
- // elements
- f.format("Elements: %s\n", toString());
-
- // raw representation of words
- for (int i = 0; i < firstEmptyWord; i++) {
- f.format(
- "words[%d] = %s (from %d to %d)\n",
- Integer.valueOf(i),
- toBinaryString(words[i]),
- Integer.valueOf(multiplyByWordSize(i)),
- Integer.valueOf(multiplyByWordSize(i + 1) - 1)
- );
- }
-
- // object attributes
- f.format("wordsInUse: %d\n", firstEmptyWord);
- f.format("size: %s\n", (size == -1 ? "invalid" : Integer.toString(size)));
- f.format("words.length: %d\n", words.length);
-
- // compression
- f.format("bitmap compression: %.2f%%\n", 100D * bitmapCompressionRatio());
- f.format("collection compression: %.2f%%\n", 100D * collectionCompressionRatio());
-
- return s.toString();
- }
-
- /**
- * Iterates over bits
- *
- * This iterator allows for modifications during the iteration, that is it
- * is possible to add/remove elements through {@link #add(int)},
- * {@link #remove(int)}, {@link #addAll(IntSet)}, {@link #removeAll(IntSet)}, {@link #retainAll(IntSet)}, etc.. In this case,
- * {@link IntIterator#next()} returns the first integral greater than the
- * last visited one.
- */
- private class BitIterator implements IntIterator
- {
- private int nextIndex;
- private int nextBit;
- private int last;
-
- /**
- * identify the first bit
- */
- private BitIterator()
- {
- nextIndex = 0;
- if (isEmpty()) {
- return;
- }
-
- last = -1; // unused!
-
- // find the first non-empty word
- while (words[nextIndex] == 0) {
- nextIndex++;
- }
-
- // find the first set bit
- nextBit = Integer.numberOfTrailingZeros(words[nextIndex]);
- }
-
- /**
- * find the first set bit after nextIndex + nextBit
- */
- void prepareNext()
- {
- // find the next set bit within the current word
- int w = words[nextIndex];
- while ((++nextBit < WORD_SIZE)) {
- if ((w & (1 << nextBit)) != 0) {
- return;
- }
- }
-
- // find the first non-empty word
- do {
- if (++nextIndex == firstEmptyWord) {
- return;
- }
- } while ((w = words[nextIndex]) == 0);
- nextBit = Integer.numberOfTrailingZeros(w);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean hasNext()
- {
- return nextIndex < firstEmptyWord;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int next()
- {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- last = multiplyByWordSize(nextIndex) + nextBit;
- prepareNext();
- return last;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void skipAllBefore(int element)
- {
- if (element <= 0 || element <= last) {
- return;
- }
-
- // identify where the element is
- int newNextIndex = wordIndexNoCheck(element);
- int newNextBit = element & (WORD_SIZE - 1);
- if (newNextIndex < nextIndex || (newNextIndex == nextIndex && newNextBit <= nextBit)) {
- return;
- }
-
- // "element" is the next item to return, unless it does not exist
- nextIndex = newNextIndex;
- if (nextIndex >= firstEmptyWord) {
- return;
- }
- nextBit = newNextBit;
- if ((words[nextIndex] & (1 << nextBit)) == 0) {
- prepareNext();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void remove()
- {
- FastSet.this.remove(last);
- }
-
- @Override
- public IntIterator clone()
- {
- BitIterator retVal = new BitIterator();
- retVal.nextIndex = nextIndex;
- retVal.nextBit = nextBit;
- retVal.last = last;
- return retVal;
- }
- }
-
- /**
- * Iterates over bits in reverse order
- *
- * This iterator allows for modifications during the iteration, that is it
- * is possible to add/remove elements through {@link #add(int)},
- * {@link #remove(int)}, {@link #addAll(IntSet)}, {@link #removeAll(IntSet)}, {@link #retainAll(IntSet)}, etc.. In this case,
- * {@link IntIterator#next()} returns the first integral greater than the
- * last visited one.
- */
- private class ReverseBitIterator implements IntIterator
- {
- private int nextIndex;
- private int nextBit;
- private int last;
-
- /**
- * identify the first bit
- */
- private ReverseBitIterator()
- {
- nextIndex = firstEmptyWord - 1;
- if (isEmpty()) {
- return;
- }
-
- last = Integer.MAX_VALUE; // unused!
- nextBit = WORD_SIZE - Integer.numberOfLeadingZeros(words[nextIndex]) - 1;
- }
-
- /**
- * find the first set bit after nextIndex + nextBit
- */
- void prepareNext()
- {
- // find the next set bit within the current word
- int w = words[nextIndex];
- while ((--nextBit >= 0)) {
- if ((w & (1 << nextBit)) != 0) {
- return;
- }
- }
-
- // find the first non-empty word
- do {
- if (--nextIndex == -1) {
- return;
- }
- } while ((w = words[nextIndex]) == 0);
- nextBit = WORD_SIZE - Integer.numberOfLeadingZeros(w) - 1;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean hasNext()
- {
- return nextIndex >= 0;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int next()
- {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- last = multiplyByWordSize(nextIndex) + nextBit;
- prepareNext();
- return last;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void skipAllBefore(int element)
- {
- if (element < 0) {
- nextIndex = -1;
- return;
- }
- if (element >= last) {
- return;
- }
-
- // identify where the element is
- int newNextIndex = wordIndexNoCheck(element);
- int newNextBit = element & (WORD_SIZE - 1);
- if (newNextIndex > nextIndex || (newNextIndex == nextIndex && newNextBit >= nextBit)) {
- return;
- }
-
- // "element" is the next item to return, unless it does not exist
- nextIndex = newNextIndex;
- nextBit = newNextBit;
- if ((words[nextIndex] & (1 << nextBit)) == 0) {
- prepareNext();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void remove()
- {
- FastSet.this.remove(last);
- }
-
- @Override
- public IntIterator clone()
- {
- BitIterator retVal = new BitIterator();
- retVal.nextIndex = nextIndex;
- retVal.nextBit = nextBit;
- retVal.last = last;
- return retVal;
- }
- }
-}
diff --git a/extendedset/src/main/java/io/druid/extendedset/intset/HashIntSet.java b/extendedset/src/main/java/io/druid/extendedset/intset/HashIntSet.java
deleted file mode 100755
index e81434a890b..00000000000
--- a/extendedset/src/main/java/io/druid/extendedset/intset/HashIntSet.java
+++ /dev/null
@@ -1,1012 +0,0 @@
-/*
- * (c) 2010 Alessandro Colantonio
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.druid.extendedset.intset;
-
-// update CompactIdentityHashSet.java, UniqueSet.java and
-// SoftHashMapIndex.java accordingly.
-
-import io.druid.extendedset.utilities.IntHashCode;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.ConcurrentModificationException;
-import java.util.NoSuchElementException;
-
-/**
- * Implements a fast hash-set.
- *
- * Inspired by http://code.google.com/p/ontopia/source/browse/trunk/ontopia/src/java/net/
- * ontopia/utils/CompactHashSet.java
- *
- * @author Alessandro Colantonio
- * @version $Id: HashIntSet.java 156 2011-09-01 00:13:57Z cocciasik $
- */
-public class HashIntSet extends AbstractIntSet
-{
- protected final static int INITIAL_SIZE = 3;
- protected final static double LOAD_FACTOR = 0.75D;
-
- /**
- * empty cell
- */
- protected final static int EMPTY = -1;
-
- /**
- * When an object is deleted this object is put into the hashtable in its
- * place, so that other objects with the same key (collisions) further down
- * the hashtable are not lost after we delete an object in the collision
- * chain.
- */
- protected final static int REMOVED = -2;
-
- /**
- * number of elements
- */
- protected int size;
-
- /**
- * This is the number of empty cells. It's not necessarily the same as
- * objects.length - elements, because some cells may contain REMOVED.
- */
- protected int freecells;
-
- /**
- * cells
- */
- protected int[] cells;
-
- /**
- * concurrent modification during iteration
- */
- protected int modCount;
-
- /**
- * Constructs a new, empty set.
- */
- public HashIntSet()
- {
- this(INITIAL_SIZE);
- }
-
- /**
- * Constructs a new, empty set.
- *
- * @param initialSize
- */
- public HashIntSet(int initialSize)
- {
- if (initialSize <= 0) {
- throw new IllegalArgumentException();
- }
- cells = new int[initialSize];
- modCount = 0;
- clear();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IntIterator iterator()
- {
- return new SortedIterator();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public IntIterator descendingIterator()
- {
- return new DescendingSortedIterator();
- }
-
- /**
- * Similar to {@link #iterator()}, but with no particular order
- *
- * @return iterator with no sorting
- */
- public IntIterator unsortedIterator()
- {
- return new UnsortedIterator();
- }
-
- /**
- * Returns the number of elements in this set (its cardinality).
- */
- @Override
- public int size()
- {
- return size;
- }
-
- /**
- * Returns true if this set contains no elements.
- */
- @Override
- public boolean isEmpty()
- {
- return size == 0;
- }
-
- /**
- * Compute the index of the element
- *
- * @param o element to search
- *
- * @return index of the element in {@link #cells}
- */
- private final int toIndex(int o)
- {
- return (o & 0x7FFFFFFF) % cells.length;
- }
-
- /**
- * Find position of the integer in {@link #cells}. If not found, returns the
- * first empty cell.
- *
- * @param element element to search
- *
- * @return if returned value >=0
, it returns the index of the
- * element; if returned value <0
, the index of the
- * first empty cell is -(returned value - 1)
- */
- private int findElementOrEmpty(int element)
- {
- assert element >= 0;
- int index = toIndex(IntHashCode.hashCode(element));
- int offset = 1;
-
- while (cells[index] != EMPTY) {
- // element found!
- if (cells[index] == element) {
- return index;
- }
-
- // compute the next index to check
- index = toIndex(index + offset);
- offset <<= 1;
- offset++;
- if (offset < 0) {
- offset = 2;
- }
- }
-
- // element not found!
- return -(index + 1);
- }
-
- /**
- * Find position of the integer in {@link #cells}. If not found, returns the
- * first removed cell.
- *
- * @param element element to search
- *
- * @return if returned value >=0
, it returns the index of the
- * element; if returned value <0
, the index of the
- * first empty cell is -(returned value - 1)
- */
- private int findElementOrRemoved(int element)
- {
- assert element >= 0;
- int index = toIndex(IntHashCode.hashCode(element));
- int offset = 1;
- int removed = -1;
-
- while (cells[index] != EMPTY) {
- // element found!
- if (cells[index] == element) {
- return index;
- }
-
- // remember the last removed cell if we don't find the element
- if (cells[index] == REMOVED) {
- removed = index;
- }
-
- index = toIndex(index + offset);
- offset <<= 1;
- offset++;
- if (offset < 0) {
- offset = 2;
- }
- }
- if (removed >= 0) {
- return -(removed + 1);
- }
- return index;
- }
-
- /**
- * Returns true if this set contains the specified element.
- *
- * @param element element whose presence in this set is to be tested.
- *
- * @return true if this set contains the specified element.
- */
- @Override
- public boolean contains(int element)
- {
- if (element < 0) {
- throw new IndexOutOfBoundsException("element < 0: " + element);
- }
- if (isEmpty()) {
- return false;
- }
- return findElementOrEmpty(element) >= 0;
- }
-
- /**
- * Adds the specified element to this set if it is not already present.
- *
- * @param element element to be added to this set.
- *
- * @return true if the set did not already contain the specified
- * element.
- */
- @Override
- public boolean add(int element)
- {
- if (element < 0) {
- throw new IndexOutOfBoundsException("element < 0: " + element);
- }
- int index = findElementOrRemoved(element);
- if (index >= 0) {
- if (cells[index] == element) {
- return false;
- }
- freecells--;
- } else {
- index = -(index + 1);
- }
-
- modCount++;
- size++;
-
- // set the integer
- cells[index] = element;
-
- // do we need to rehash?
- if (1 - ((double) freecells / cells.length) > LOAD_FACTOR) {
- rehash();
- }
- return true;
- }
-
- /**
- * Removes the specified element from the set.
- */
- @Override
- public boolean remove(int element)
- {
- if (element < 0) {
- throw new IndexOutOfBoundsException("element < 0: " + element);
- }
- int index = findElementOrEmpty(element);
- if (index < 0) {
- return false;
- }
-
- cells[index] = REMOVED;
- modCount++;
- size--;
- return true;
- }
-
- /**
- * Removes all of the elements from this set.
- */
- @Override
- public void clear()
- {
- size = 0;
- Arrays.fill(cells, EMPTY);
- freecells = cells.length;
- modCount++;
- }
-
- /**
- * Figures out correct size for rehashed set, then does the rehash.
- */
- protected void rehash()
- {
- // do we need to increase capacity, or are there so many
- // deleted objects hanging around that rehashing to the same
- // size is sufficient? if 5% (arbitrarily chosen number) of
- // cells can be freed up by a rehash, we do it.
-
- int gargagecells = cells.length - (size + freecells);
- if ((double) gargagecells / cells.length > 0.05D)
- // rehash with same size
- {
- rehash(cells.length);
- } else
- // rehash with increased capacity
- {
- rehash((cells.length << 1) + 1);
- }
- }
-
- /**
- * Rehashes to a bigger size.
- */
- protected void rehash(int newCapacity)
- {
- HashIntSet rehashed = new HashIntSet(newCapacity);
- @SuppressWarnings("hiding")
- int[] cells = rehashed.cells;
- for (int element : this.cells) {
- if (element < 0)
- // removed or empty
- {
- continue;
- }
-
- // add the element
- cells[-(rehashed.findElementOrEmpty(element) + 1)] = element;
- }
- this.cells = cells;
- freecells = newCapacity - size;
- modCount++;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean addAll(IntSet c)
- {
- if (c == null || c.isEmpty()) {
- return false;
- }
- IntIterator itr;
- if (c instanceof HashIntSet) {
- itr = ((HashIntSet) c).unsortedIterator();
- } else {
- itr = c.iterator();
- }
- boolean res = false;
- while (itr.hasNext()) {
- res |= add(itr.next());
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean removeAll(IntSet c)
- {
- if (c == null || c.isEmpty()) {
- return false;
- }
- IntIterator itr;
- if (c instanceof HashIntSet) {
- itr = ((HashIntSet) c).unsortedIterator();
- } else {
- itr = c.iterator();
- }
- boolean res = false;
- while (itr.hasNext()) {
- res |= remove(itr.next());
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean retainAll(IntSet c)
- {
- if (c == null || c.isEmpty()) {
- return false;
- }
- boolean res = false;
- for (int i = 0; i < cells.length; i++) {
- if (cells[i] >= 0 && !c.contains(cells[i])) {
- cells[i] = REMOVED;
- res = true;
- size--;
- }
- }
- if (res) {
- modCount++;
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public HashIntSet clone()
- {
- HashIntSet cloned = new HashIntSet(cells.length);
- System.arraycopy(cells, 0, cloned.cells, 0, cells.length);
- cloned.freecells = freecells;
- cloned.size = size;
- cloned.modCount = 0;
- return cloned;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public double bitmapCompressionRatio()
- {
- if (isEmpty()) {
- return 0D;
- }
- return cells.length / Math.ceil(last() / 32D);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public double collectionCompressionRatio()
- {
- return isEmpty() ? 0D : (double) cells.length / size();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public HashIntSet complemented()
- {
- return (HashIntSet) super.complemented();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsAll(IntSet c)
- {
- IntIterator itr;
- if (c instanceof HashIntSet) {
- itr = ((HashIntSet) c).unsortedIterator();
- } else {
- itr = c.iterator();
- }
- boolean res = true;
- while (res && itr.hasNext()) {
- res &= contains(itr.next());
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsAny(IntSet c)
- {
- IntIterator itr;
- if (c instanceof HashIntSet) {
- itr = ((HashIntSet) c).unsortedIterator();
- } else {
- itr = c.iterator();
- }
- boolean res = true;
- while (res && itr.hasNext()) {
- if (contains(itr.next())) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsAtLeast(IntSet c, int minElements)
- {
- IntIterator itr;
- if (c instanceof HashIntSet) {
- itr = ((HashIntSet) c).unsortedIterator();
- } else {
- itr = c.iterator();
- }
- while (minElements > 0 && itr.hasNext()) {
- if (contains(itr.next())) {
- minElements--;
- }
- }
- return minElements == 0;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public HashIntSet convert(int... a)
- {
- HashIntSet res = new HashIntSet((int) (a.length / LOAD_FACTOR) + 1);
- for (int e : a) {
- res.add(e);
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public HashIntSet convert(Collection c)
- {
- HashIntSet res = new HashIntSet((int) (c.size() / LOAD_FACTOR) + 1);
- for (int e : c) {
- res.add(e);
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String debugInfo()
- {
- return "size: " + size + ", freecells: " + freecells + ", "
- + Arrays.toString(cells);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public HashIntSet symmetricDifference(IntSet c)
- {
- HashIntSet res = clone();
- IntIterator itr;
- if (c instanceof HashIntSet) {
- itr = ((HashIntSet) c).unsortedIterator();
- } else {
- itr = c.iterator();
- }
- while (itr.hasNext()) {
- res.flip(itr.next());
- }
- return res;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public HashIntSet union(IntSet other)
- {
- return (HashIntSet) super.union(other);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public HashIntSet difference(IntSet other)
- {
- return (HashIntSet) super.difference(other);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public HashIntSet intersection(IntSet other)
- {
- return (HashIntSet) super.intersection(other);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public HashIntSet empty()
- {
- return new HashIntSet();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void flip(int element)
- {
- if (element < 0) {
- throw new IndexOutOfBoundsException("element < 0: " + element);
- }
- modCount++;
- int index = findElementOrRemoved(element);
- if (index >= 0) {
- // REMOVE
- if (cells[index] == element) {
- cells[index] = REMOVED;
- size--;
- return;
- }
- freecells--;
- } else {
- index = -(index + 1);
- }
-
- // ADD
- cells[index] = element;
- size++;
-
- // do we need to rehash?
- if (1 - ((double) freecells / cells.length) > LOAD_FACTOR) {
- rehash();
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int get(int i)
- {
- return toArray()[i];
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int indexOf(int e)
- {
- if (e < 0) {
- throw new IllegalArgumentException("positive integer expected: " + Integer.toString(e));
- }
- return Arrays.binarySearch(toArray(), e);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int intersectionSize(IntSet c)
- {
- int res = 0;
- IntIterator itr;
- if (c instanceof HashIntSet) {
- itr = ((HashIntSet) c).unsortedIterator();
- } else {
- itr = c.iterator();
- }
- while (itr.hasNext()) {
- if (contains(itr.next())) {
- res++;
- }
- }
- return res;
-
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int last()
- {
- if (isEmpty()) {
- throw new NoSuchElementException();
- }
- int max = 0;
- for (int element : cells) {
- if (max < element) {
- max = element;
- }
- }
- return max;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int first()
- {
- if (isEmpty()) {
- throw new NoSuchElementException();
- }
- int min = Integer.MAX_VALUE;
- for (int element : cells) {
- if (element >= 0 && min > element) {
- min = element;
- }
- }
- return min;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int[] toArray(int[] a)
- {
- if (a.length < size) {
- throw new IllegalArgumentException();
- }
- if (isEmpty()) {
- return a;
- }
- int i = 0;
- for (int element : this.cells) {
- if (element < 0)
- // removed or empty
- {
- continue;
- }
-
- // copy the element
- a[i++] = element;
- }
- Arrays.sort(a, 0, size);
- return a;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString()
- {
- return Arrays.toString(toArray());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int hashCode()
- {
- if (isEmpty()) {
- return 0;
- }
- int h = 1;
- for (int e : cells) {
- if (e >= 0) {
- h ^= IntHashCode.hashCode(e);
- }
- }
- return h;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof HashIntSet)) {
- return super.equals(obj);
- }
- final HashIntSet other = (HashIntSet) obj;
- if (size != other.size) {
- return false;
- }
- for (int e : other.cells) {
- if (e >= 0 && !contains(e)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Iterates over the hashset, with no sorting
- */
- private class UnsortedIterator implements IntIterator
- {
- private int nextIndex = 0;
- private int current = -1;
- private int expectedModCount = modCount;
-
- public UnsortedIterator()
- {
- nextIndex = 0;
- skipEmpty();
- expectedModCount = modCount;
- }
-
- void skipEmpty()
- {
- while (nextIndex < cells.length
- && (cells[nextIndex] == EMPTY || cells[nextIndex] == REMOVED)) {
- nextIndex++;
- }
- }
-
- @Override
- public boolean hasNext()
- {
- return nextIndex < cells.length;
- }
-
- @Override
- public int next()
- {
- if (modCount != expectedModCount) {
- throw new ConcurrentModificationException();
- }
- if (nextIndex >= cells.length) {
- throw new NoSuchElementException();
- }
-
- current = nextIndex;
- nextIndex++;
- skipEmpty();
- return cells[current];
- }
-
- @Override
- public void remove()
- {
- if (modCount != expectedModCount) {
- throw new ConcurrentModificationException();
- }
- if (current < 0) {
- throw new IllegalStateException();
- }
- // delete object
- cells[current] = REMOVED;
- size--;
- modCount++;
- expectedModCount = modCount; // this is expected!
- current = -1;
- }
-
- @Override
- public void skipAllBefore(int element)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public IntIterator clone()
- {
- UnsortedIterator retVal = new UnsortedIterator();
- retVal.nextIndex = nextIndex;
- retVal.current = current;
- retVal.expectedModCount = expectedModCount;
- return retVal;
- }
- }
-
- /**
- * Iterates over the hashset, with no sorting
- */
- private class SortedIterator implements IntIterator
- {
- int[] elements = toArray();
- int next = 0;
-
- @Override
- public boolean hasNext()
- {
- return next < size;
- }
-
- @Override
- public int next()
- {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- return elements[next++];
- }
-
- @Override
- public void remove()
- {
- if (elements[next - 1] == REMOVED) {
- throw new IllegalStateException();
- }
- HashIntSet.this.remove(elements[next - 1]);
- elements[next - 1] = REMOVED;
- }
-
- @Override
- public void skipAllBefore(int element)
- {
- if (element <= elements[next]) {
- return;
- }
- next = Arrays.binarySearch(elements, next + 1, size, element);
- if (next < 0) {
- next = -(next + 1);
- }
- }
-
- @Override
- public IntIterator clone()
- {
- SortedIterator retVal = new SortedIterator();
- retVal.next = next;
- retVal.elements = elements.clone();
- return retVal;
- }
- }
-
- /**
- * Iterates over the hashset, with no sorting
- */
- private class DescendingSortedIterator implements IntIterator
- {
- int[] elements = toArray();
- int next = size - 1;
-
- @Override
- public boolean hasNext()
- {
- return next >= 0;
- }
-
- @Override
- public int next()
- {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- return elements[next--];
- }
-
- @Override
- public void remove()
- {
- if (elements[next + 1] == REMOVED) {
- throw new IllegalStateException();
- }
- HashIntSet.this.remove(elements[next + 1]);
- elements[next + 1] = REMOVED;
- }
-
- @Override
- public void skipAllBefore(int element)
- {
- if (element >= elements[next]) {
- return;
- }
- next = Arrays.binarySearch(elements, 0, next, element);
- if (next < 0) {
- next = -(next + 1) - 1;
- }
- }
-
- @Override
- public IntIterator clone()
- {
- DescendingSortedIterator retVal = new DescendingSortedIterator();
- retVal.elements = elements.clone();
- retVal.next = next;
- return retVal;
- }
- }
-}
diff --git a/extendedset/src/main/java/io/druid/extendedset/intset/ImmutableConciseSet.java b/extendedset/src/main/java/io/druid/extendedset/intset/ImmutableConciseSet.java
index 6dbf8bb1d0d..c2a54da2b9d 100755
--- a/extendedset/src/main/java/io/druid/extendedset/intset/ImmutableConciseSet.java
+++ b/extendedset/src/main/java/io/druid/extendedset/intset/ImmutableConciseSet.java
@@ -18,47 +18,108 @@ package io.druid.extendedset.intset;
import com.google.common.collect.Iterators;
-import com.google.common.collect.Lists;
-import com.google.common.collect.MinMaxPriorityQueue;
import com.google.common.collect.UnmodifiableIterator;
import com.google.common.primitives.Ints;
import io.druid.extendedset.utilities.IntList;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
-import java.util.NoSuchElementException;
+import java.util.PriorityQueue;
public class ImmutableConciseSet
{
private final static int CHUNK_SIZE = 10000;
- private final IntBuffer words;
- private final int lastWordIndex;
- private final int size;
- public ImmutableConciseSet()
+ private static final Comparator UNION_COMPARATOR = new Comparator()
{
- this.words = null;
- this.lastWordIndex = -1;
- this.size = 0;
- }
+ // Comparison is first by index, then one fills < literals < zero fills
+ // one fills are sorted by length (longer one fills have priority)
+ // similarily, shorter zero fills have priority
+ @Override
+ public int compare(WordIterator i1, WordIterator i2)
+ {
+ int s1 = i1.startIndex;
+ int s2 = i2.startIndex;
- public ImmutableConciseSet(ByteBuffer byteBuffer)
- {
- this.words = byteBuffer.asIntBuffer();
- this.lastWordIndex = words.capacity() - 1;
- this.size = calcSize();
- }
+ if (s1 != s2) {
+ return Integer.compare(s1, s2);
+ }
- public ImmutableConciseSet(IntBuffer buffer)
+ int w1 = i1.getWord();
+ int w2 = i2.getWord();
+
+ if (ConciseSetUtils.isLiteral(w1)) {
+ if (ConciseSetUtils.isLiteral(w2)) {
+ return 0;
+ } else if (ConciseSetUtils.isZeroSequence(w2)) {
+ return -1;
+ } else {
+ assert ConciseSetUtils.isOneSequence(w2);
+ return 1;
+ }
+ } else if (ConciseSetUtils.isZeroSequence(w1)) {
+ if (!ConciseSetUtils.isZeroSequence(w2)) {
+ return 1;
+ }
+ return Integer.compare(ConciseSetUtils.getSequenceNumWords(w1), ConciseSetUtils.getSequenceNumWords(w2));
+ } else {
+ assert ConciseSetUtils.isOneSequence(w1);
+ if (ConciseSetUtils.isOneSequence(w2)) {
+ // reverse
+ return Integer.compare(ConciseSetUtils.getSequenceNumWords(w2), ConciseSetUtils.getSequenceNumWords(w1));
+ }
+ return -1;
+ }
+ }
+ };
+
+ private static final Comparator INTERSECTION_COMPARATOR = new Comparator()
{
- this.words = buffer;
- this.lastWordIndex = (words == null || buffer.capacity() == 0) ? -1 : words.capacity() - 1;
- this.size = calcSize();
- }
+ // Comparison is first by index, then zero fills < literals < one fills
+ // zero fills are sorted by length (longer zero fills have priority)
+ // similarily, shorter one fills have priority
+ @Override
+ public int compare(WordIterator i1, WordIterator i2)
+ {
+ int s1 = i1.startIndex;
+ int s2 = i2.startIndex;
+
+ if (s1 != s2) {
+ return Integer.compare(s1, s2);
+ }
+
+ int w1 = i1.getWord();
+ int w2 = i2.getWord();
+
+ if (ConciseSetUtils.isLiteral(w1)) {
+ if (ConciseSetUtils.isLiteral(w2)) {
+ return 0;
+ } else if (ConciseSetUtils.isZeroSequence(w2)) {
+ return 1;
+ } else {
+ assert ConciseSetUtils.isOneSequence(w2);
+ return -1;
+ }
+ } else if (ConciseSetUtils.isZeroSequence(w1)) {
+ if (ConciseSetUtils.isZeroSequence(w2)) {
+ // reverse
+ return Integer.compare(ConciseSetUtils.getSequenceNumWords(w2), ConciseSetUtils.getSequenceNumWords(w1));
+ }
+ return -1;
+ } else {
+ assert ConciseSetUtils.isOneSequence(w1);
+ if (!ConciseSetUtils.isOneSequence(w2)) {
+ return 1;
+ }
+ return Integer.compare(ConciseSetUtils.getSequenceNumWords(w1), ConciseSetUtils.getSequenceNumWords(w2));
+ }
+ }
+ };
public static ImmutableConciseSet newImmutableFromMutable(ConciseSet conciseSet)
{
@@ -68,11 +129,6 @@ public class ImmutableConciseSet
return new ImmutableConciseSet(IntBuffer.wrap(conciseSet.getWords()));
}
- public static int compareInts(int x, int y)
- {
- return (x < y) ? -1 : ((x == y) ? 0 : 1);
- }
-
public static ImmutableConciseSet union(ImmutableConciseSet... sets)
{
return union(Arrays.asList(sets));
@@ -230,23 +286,33 @@ public class ImmutableConciseSet
int last = set.get(length - 1);
int newWord = 0;
- if (ConciseSetUtils.isAllOnesLiteral(last)) {
- if (ConciseSetUtils.isAllOnesLiteral(wordToAdd)) {
- newWord = 0x40000001;
- } else if (ConciseSetUtils.isOneSequence(wordToAdd) && ConciseSetUtils.getFlippedBit(wordToAdd) == -1) {
- newWord = wordToAdd + 1;
- }
- } else if (ConciseSetUtils.isOneSequence(last)) {
- if (ConciseSetUtils.isAllOnesLiteral(wordToAdd)) {
- newWord = last + 1;
- } else if (ConciseSetUtils.isOneSequence(wordToAdd) && ConciseSetUtils.getFlippedBit(wordToAdd) == -1) {
- newWord = last + ConciseSetUtils.getSequenceNumWords(wordToAdd);
- }
- } else if (ConciseSetUtils.isAllZerosLiteral(last)) {
- if (ConciseSetUtils.isAllZerosLiteral(wordToAdd)) {
- newWord = 0x00000001;
- } else if (ConciseSetUtils.isZeroSequence(wordToAdd) && ConciseSetUtils.getFlippedBit(wordToAdd) == -1) {
- newWord = wordToAdd + 1;
+ if (ConciseSetUtils.isLiteral(last)) {
+ if (ConciseSetUtils.isLiteralWithSingleOneBit(last)) {
+ int position = Integer.numberOfTrailingZeros(last) + 1;
+ if (ConciseSetUtils.isAllZerosLiteral(wordToAdd)) {
+ newWord = 0x00000001 | (position << 25);
+ } else if (ConciseSetUtils.isZeroSequence(wordToAdd) && ConciseSetUtils.getFlippedBit(wordToAdd) == -1) {
+ newWord = (wordToAdd + 1) | (position << 25);
+ }
+ } else if (ConciseSetUtils.isAllZerosLiteral(last)) {
+ if (ConciseSetUtils.isAllZerosLiteral(wordToAdd)) {
+ newWord = 0x00000001;
+ } else if (ConciseSetUtils.isZeroSequence(wordToAdd) && ConciseSetUtils.getFlippedBit(wordToAdd) == -1) {
+ newWord = wordToAdd + 1;
+ }
+ } else if (ConciseSetUtils.isLiteralWithSingleZeroBit(last)) {
+ int position = Integer.numberOfTrailingZeros(~last) + 1;
+ if (ConciseSetUtils.isAllOnesLiteral(wordToAdd)) {
+ newWord = 0x40000001 | (position << 25);
+ } else if (ConciseSetUtils.isOneSequence(wordToAdd) && ConciseSetUtils.getFlippedBit(wordToAdd) == -1) {
+ newWord = (wordToAdd + 1) | (position << 25);
+ }
+ } else if (ConciseSetUtils.isAllOnesLiteral(last)) {
+ if (ConciseSetUtils.isAllOnesLiteral(wordToAdd)) {
+ newWord = 0x40000001;
+ } else if (ConciseSetUtils.isOneSequence(wordToAdd) && ConciseSetUtils.getFlippedBit(wordToAdd) == -1) {
+ newWord = wordToAdd + 1;
+ }
}
} else if (ConciseSetUtils.isZeroSequence(last)) {
if (ConciseSetUtils.isAllZerosLiteral(wordToAdd)) {
@@ -254,19 +320,12 @@ public class ImmutableConciseSet
} else if (ConciseSetUtils.isZeroSequence(wordToAdd) && ConciseSetUtils.getFlippedBit(wordToAdd) == -1) {
newWord = last + ConciseSetUtils.getSequenceNumWords(wordToAdd);
}
- } else if (ConciseSetUtils.isLiteralWithSingleOneBit(last)) {
- int position = Integer.numberOfTrailingZeros(last) + 1;
- if (ConciseSetUtils.isAllZerosLiteral(wordToAdd)) {
- newWord = 0x00000001 | (position << 25);
- } else if (ConciseSetUtils.isZeroSequence(wordToAdd) && ConciseSetUtils.getFlippedBit(wordToAdd) == -1) {
- newWord = (wordToAdd + 1) | (position << 25);
- }
- } else if (ConciseSetUtils.isLiteralWithSingleZeroBit(last)) {
- int position = Integer.numberOfTrailingZeros(~last) + 1;
+ } else {
+ assert ConciseSetUtils.isOneSequence(last);
if (ConciseSetUtils.isAllOnesLiteral(wordToAdd)) {
- newWord = 0x40000001 | (position << 25);
+ newWord = last + 1;
} else if (ConciseSetUtils.isOneSequence(wordToAdd) && ConciseSetUtils.getFlippedBit(wordToAdd) == -1) {
- newWord = (wordToAdd + 1) | (position << 25);
+ newWord = last + ConciseSetUtils.getSequenceNumWords(wordToAdd);
}
}
@@ -280,47 +339,11 @@ public class ImmutableConciseSet
private static ImmutableConciseSet doUnion(Iterator sets)
{
IntList retVal = new IntList();
-
- // lhs = current word position, rhs = the iterator
- // Comparison is first by index, then one fills > literals > zero fills
- // one fills are sorted by length (longer one fills have priority)
- // similarily, shorter zero fills have priority
- MinMaxPriorityQueue theQ = MinMaxPriorityQueue.orderedBy(
- new Comparator()
- {
- @Override
- public int compare(WordHolder h1, WordHolder h2)
- {
- int w1 = h1.getWord();
- int w2 = h2.getWord();
- int s1 = h1.getIterator().startIndex;
- int s2 = h2.getIterator().startIndex;
-
- if (s1 != s2) {
- return compareInts(s1, s2);
- }
-
- if (ConciseSetUtils.isOneSequence(w1)) {
- if (ConciseSetUtils.isOneSequence(w2)) {
- return -compareInts(ConciseSetUtils.getSequenceNumWords(w1), ConciseSetUtils.getSequenceNumWords(w2));
- }
- return -1;
- } else if (ConciseSetUtils.isLiteral(w1)) {
- if (ConciseSetUtils.isOneSequence(w2)) {
- return 1;
- } else if (ConciseSetUtils.isLiteral(w2)) {
- return 0;
- }
- return -1;
- } else {
- if (!ConciseSetUtils.isZeroSequence(w2)) {
- return 1;
- }
- return compareInts(ConciseSetUtils.getSequenceNumWords(w1), ConciseSetUtils.getSequenceNumWords(w2));
- }
- }
- }
- ).create();
+ // Use PriorityQueue, because sometimes as much as 20k of bitsets are unified, and the asymptotic complexity of
+ // keeping bitsets in a sorted array (n^2), as in doIntersection(), becomes more important factor than PriorityQueue
+ // inefficiency.
+ // Need to specify initial capacity because JDK 7 doesn't have Comparator-only constructor of PriorityQueue
+ PriorityQueue theQ = new PriorityQueue<>(11, UNION_COMPARATOR);
// populate priority queue
while (sets.hasNext()) {
@@ -328,20 +351,19 @@ public class ImmutableConciseSet
if (set != null && !set.isEmpty()) {
WordIterator itr = set.newWordIterator();
- theQ.add(new WordHolder(itr.next(), itr));
+ itr.word = itr.next();
+ theQ.add(itr);
}
}
int currIndex = 0;
- while (!theQ.isEmpty()) {
- // create a temp list to hold everything that will get pushed back into the priority queue after each run
- List wordsToAdd = Lists.newArrayList();
+ List changedIterators = new ArrayList<>();
+ while (!theQ.isEmpty()) {
// grab the top element from the priority queue
- WordHolder curr = theQ.poll();
- int word = curr.getWord();
- WordIterator itr = curr.getIterator();
+ WordIterator itr = theQ.poll();
+ int word = itr.getWord();
// if the next word in the queue starts at a different point than where we ended off we need to create a zero gap
// to fill the space
@@ -350,35 +372,90 @@ public class ImmutableConciseSet
currIndex = itr.startIndex;
}
- if (ConciseSetUtils.isOneSequence(word)) {
+ if (ConciseSetUtils.isLiteral(word)) {
+ // advance all other literals
+ while (!theQ.isEmpty() && theQ.peek().startIndex == itr.startIndex) {
+ WordIterator i = theQ.poll();
+ int w = i.getWord();
+
+ // if we still have zero fills with flipped bits, OR them here
+ if (ConciseSetUtils.isLiteral(w)) {
+ word |= w;
+ } else {
+ int flipBitLiteral = ConciseSetUtils.getLiteralFromZeroSeqFlipBit(w);
+ if (flipBitLiteral != ConciseSetUtils.ALL_ZEROS_LITERAL) {
+ word |= flipBitLiteral;
+ i.advanceTo(itr.wordsWalked);
+ }
+ }
+
+ if (i.hasNext()) {
+ i.word = i.next();
+ changedIterators.add(i);
+ }
+ }
+
+ // advance the set with the current literal forward and push result back to priority queue
+ addAndCompact(retVal, word);
+ currIndex++;
+
+ if (itr.hasNext()) {
+ itr.word = itr.next();
+ changedIterators.add(itr);
+ }
+ } else if (ConciseSetUtils.isZeroSequence(word)) {
+ int flipBitLiteral;
+ while (!theQ.isEmpty() && theQ.peek().startIndex == itr.startIndex) {
+ WordIterator i = theQ.poll();
+ int w = i.getWord();
+
+ flipBitLiteral = ConciseSetUtils.getLiteralFromZeroSeqFlipBit(w);
+ if (flipBitLiteral != ConciseSetUtils.ALL_ZEROS_LITERAL) {
+ i.word = flipBitLiteral;
+ changedIterators.add(i);
+ } else if (i.hasNext()) {
+ i.word = i.next();
+ changedIterators.add(i);
+ }
+ }
+
+ // check if a literal needs to be created from the flipped bits of this sequence
+ flipBitLiteral = ConciseSetUtils.getLiteralFromZeroSeqFlipBit(word);
+ if (flipBitLiteral != ConciseSetUtils.ALL_ZEROS_LITERAL) {
+ itr.word = flipBitLiteral;
+ changedIterators.add(itr);
+ } else if (itr.hasNext()) {
+ itr.word = itr.next();
+ changedIterators.add(itr);
+ }
+ } else {
+ assert ConciseSetUtils.isOneSequence(word);
// extract a literal from the flip bits of the one sequence
int flipBitLiteral = ConciseSetUtils.getLiteralFromOneSeqFlipBit(word);
// advance everything past the longest ones sequence
- WordHolder nextVal = theQ.peek();
- while (nextVal != null &&
- nextVal.getIterator().startIndex < itr.wordsWalked) {
- WordHolder entry = theQ.poll();
- int w = entry.getWord();
- WordIterator i = entry.getIterator();
+ while (!theQ.isEmpty() && theQ.peek().startIndex < itr.wordsWalked) {
+ WordIterator i = theQ.poll();
+ int w = i.getWord();
if (i.startIndex == itr.startIndex) {
// if a literal was created from a flip bit, OR it with other literals or literals from flip bits in the same
// position
- if (ConciseSetUtils.isOneSequence(w)) {
- flipBitLiteral |= ConciseSetUtils.getLiteralFromOneSeqFlipBit(w);
- } else if (ConciseSetUtils.isLiteral(w)) {
+ if (ConciseSetUtils.isLiteral(w)) {
flipBitLiteral |= w;
- } else {
+ } else if (ConciseSetUtils.isZeroSequence(w)) {
flipBitLiteral |= ConciseSetUtils.getLiteralFromZeroSeqFlipBit(w);
+ } else {
+ assert ConciseSetUtils.isOneSequence(w);
+ flipBitLiteral |= ConciseSetUtils.getLiteralFromOneSeqFlipBit(w);
}
}
i.advanceTo(itr.wordsWalked);
if (i.hasNext()) {
- wordsToAdd.add(new WordHolder(i.next(), i));
+ i.word = i.next();
+ changedIterators.add(i);
}
- nextVal = theQ.peek();
}
// advance longest one literal forward and push result back to priority queue
@@ -393,73 +470,13 @@ public class ImmutableConciseSet
currIndex = itr.wordsWalked;
if (itr.hasNext()) {
- wordsToAdd.add(new WordHolder(itr.next(), itr));
- }
- } else if (ConciseSetUtils.isLiteral(word)) {
- // advance all other literals
- WordHolder nextVal = theQ.peek();
- while (nextVal != null &&
- nextVal.getIterator().startIndex == itr.startIndex) {
-
- WordHolder entry = theQ.poll();
- int w = entry.getWord();
- WordIterator i = entry.getIterator();
-
- // if we still have zero fills with flipped bits, OR them here
- if (ConciseSetUtils.isLiteral(w)) {
- word |= w;
- } else {
- int flipBitLiteral = ConciseSetUtils.getLiteralFromZeroSeqFlipBit(w);
- if (flipBitLiteral != ConciseSetUtils.ALL_ZEROS_LITERAL) {
- word |= flipBitLiteral;
- i.advanceTo(itr.wordsWalked);
- }
- }
-
- if (i.hasNext()) {
- wordsToAdd.add(new WordHolder(i.next(), i));
- }
-
- nextVal = theQ.peek();
- }
-
- // advance the set with the current literal forward and push result back to priority queue
- addAndCompact(retVal, word);
- currIndex++;
-
- if (itr.hasNext()) {
- wordsToAdd.add(new WordHolder(itr.next(), itr));
- }
- } else { // zero fills
- int flipBitLiteral;
- WordHolder nextVal = theQ.peek();
-
- while (nextVal != null &&
- nextVal.getIterator().startIndex == itr.startIndex) {
- // check if literal can be created flip bits of other zero sequences
- WordHolder entry = theQ.poll();
- int w = entry.getWord();
- WordIterator i = entry.getIterator();
-
- flipBitLiteral = ConciseSetUtils.getLiteralFromZeroSeqFlipBit(w);
- if (flipBitLiteral != ConciseSetUtils.ALL_ZEROS_LITERAL) {
- wordsToAdd.add(new WordHolder(flipBitLiteral, i));
- } else if (i.hasNext()) {
- wordsToAdd.add(new WordHolder(i.next(), i));
- }
- nextVal = theQ.peek();
- }
-
- // check if a literal needs to be created from the flipped bits of this sequence
- flipBitLiteral = ConciseSetUtils.getLiteralFromZeroSeqFlipBit(word);
- if (flipBitLiteral != ConciseSetUtils.ALL_ZEROS_LITERAL) {
- wordsToAdd.add(new WordHolder(flipBitLiteral, itr));
- } else if (itr.hasNext()) {
- wordsToAdd.add(new WordHolder(itr.next(), itr));
+ itr.word = itr.next();
+ changedIterators.add(itr);
}
}
- theQ.addAll(wordsToAdd);
+ theQ.addAll(changedIterators);
+ changedIterators.clear();
}
if (retVal.isEmpty()) {
@@ -472,47 +489,7 @@ public class ImmutableConciseSet
{
IntList retVal = new IntList();
- // lhs = current word position, rhs = the iterator
- // Comparison is first by index, then zero fills > literals > one fills
- // zero fills are sorted by length (longer zero fills have priority)
- // similarily, shorter one fills have priority
- MinMaxPriorityQueue theQ = MinMaxPriorityQueue.orderedBy(
- new Comparator()
- {
- @Override
- public int compare(WordHolder h1, WordHolder h2)
- {
- int w1 = h1.getWord();
- int w2 = h2.getWord();
- int s1 = h1.getIterator().startIndex;
- int s2 = h2.getIterator().startIndex;
-
- if (s1 != s2) {
- return compareInts(s1, s2);
- }
-
- if (ConciseSetUtils.isZeroSequence(w1)) {
- if (ConciseSetUtils.isZeroSequence(w2)) {
- return -compareInts(ConciseSetUtils.getSequenceNumWords(w1), ConciseSetUtils.getSequenceNumWords(w2));
- }
- return -1;
- } else if (ConciseSetUtils.isLiteral(w1)) {
- if (ConciseSetUtils.isZeroSequence(w2)) {
- return 1;
- } else if (ConciseSetUtils.isLiteral(w2)) {
- return 0;
- }
- return -1;
- } else {
- if (!ConciseSetUtils.isOneSequence(w2)) {
- return 1;
- }
- return compareInts(ConciseSetUtils.getSequenceNumWords(w1), ConciseSetUtils.getSequenceNumWords(w2));
- }
- }
- }
- ).create();
-
+ ArrayList iterators = new ArrayList<>();
// populate priority queue
while (sets.hasNext()) {
ImmutableConciseSet set = sets.next();
@@ -522,20 +499,25 @@ public class ImmutableConciseSet
}
WordIterator itr = set.newWordIterator();
- theQ.add(new WordHolder(itr.next(), itr));
+ itr.word = itr.next();
+ iterators.add(itr);
}
+ // Keep iterators in a sorted array, because usually only a few bitsets are intersected, very rarely - a few dozens.
+ // Sorted array approach was benchmarked and proven to be faster than PriorityQueue (as in doUnion()) up to 100
+ // bitsets.
+ WordIterator[] theQ = iterators.toArray(new WordIterator[0]);
+ int qSize = theQ.length;
+ partialSort(theQ, qSize - 1, qSize, INTERSECTION_COMPARATOR);
int currIndex = 0;
int wordsWalkedAtSequenceEnd = Integer.MAX_VALUE;
- while (!theQ.isEmpty()) {
- // create a temp list to hold everything that will get pushed back into the priority queue after each run
- List wordsToAdd = Lists.newArrayList();
+ while (qSize > 0) {
+ int maxChangedIndex = -1;
// grab the top element from the priority queue
- WordHolder curr = theQ.poll();
- int word = curr.getWord();
- WordIterator itr = curr.getIterator();
+ WordIterator itr = theQ[0];
+ int word = itr.getWord();
// if a sequence has ended, we can break out because of Boolean logic
if (itr.startIndex >= wordsWalkedAtSequenceEnd) {
@@ -550,63 +532,14 @@ public class ImmutableConciseSet
currIndex = itr.startIndex;
}
- if (ConciseSetUtils.isZeroSequence(word)) {
- // extract a literal from the flip bits of the zero sequence
- int flipBitLiteral = ConciseSetUtils.getLiteralFromZeroSeqFlipBit(word);
-
- // advance everything past the longest zero sequence
- WordHolder nextVal = theQ.peek();
- while (nextVal != null &&
- nextVal.getIterator().startIndex < itr.wordsWalked) {
- WordHolder entry = theQ.poll();
- int w = entry.getWord();
- WordIterator i = entry.getIterator();
-
- if (i.startIndex == itr.startIndex) {
- // if a literal was created from a flip bit, AND it with other literals or literals from flip bits in the same
- // position
- if (ConciseSetUtils.isZeroSequence(w)) {
- flipBitLiteral &= ConciseSetUtils.getLiteralFromZeroSeqFlipBit(w);
- } else if (ConciseSetUtils.isLiteral(w)) {
- flipBitLiteral &= w;
- } else {
- flipBitLiteral &= ConciseSetUtils.getLiteralFromOneSeqFlipBit(w);
- }
- }
-
- i.advanceTo(itr.wordsWalked);
- if (i.hasNext()) {
- wordsToAdd.add(new WordHolder(i.next(), i));
- } else {
- wordsWalkedAtSequenceEnd = Math.min(i.wordsWalked, wordsWalkedAtSequenceEnd);
- }
- nextVal = theQ.peek();
- }
-
- // advance longest zero literal forward and push result back to priority queue
- // if a flip bit is still needed, put it in the correct position
- int newWord = word & 0xC1FFFFFF;
- if (flipBitLiteral != ConciseSetUtils.ALL_ZEROS_LITERAL) {
- int position = Integer.numberOfTrailingZeros(flipBitLiteral) + 1;
- newWord = (word & 0xC1FFFFFF) | (position << 25);
- }
- addAndCompact(retVal, newWord);
- currIndex = itr.wordsWalked;
-
- if (itr.hasNext()) {
- wordsToAdd.add(new WordHolder(itr.next(), itr));
- } else {
- wordsWalkedAtSequenceEnd = Math.min(itr.wordsWalked, wordsWalkedAtSequenceEnd);
- }
- } else if (ConciseSetUtils.isLiteral(word)) {
+ if (ConciseSetUtils.isLiteral(word)) {
// advance all other literals
- WordHolder nextVal = theQ.peek();
- while (nextVal != null &&
- nextVal.getIterator().startIndex == itr.startIndex) {
+ int qIndex = 1;
+ while (qIndex < qSize &&
+ theQ[qIndex].startIndex == itr.startIndex) {
- WordHolder entry = theQ.poll();
- int w = entry.getWord();
- WordIterator i = entry.getIterator();
+ WordIterator i = theQ[qIndex];
+ int w = i.getWord();
// if we still have one fills with flipped bits, AND them here
if (ConciseSetUtils.isLiteral(w)) {
@@ -620,12 +553,14 @@ public class ImmutableConciseSet
}
if (i.hasNext()) {
- wordsToAdd.add(new WordHolder(i.next(), i));
+ i.word = i.next();
+ maxChangedIndex = qIndex;
+ qIndex++;
} else {
+ removeElement(theQ, qIndex, qSize);
+ qSize--;
wordsWalkedAtSequenceEnd = Math.min(i.wordsWalked, wordsWalkedAtSequenceEnd);
}
-
- nextVal = theQ.peek();
}
// advance the set with the current literal forward and push result back to priority queue
@@ -633,45 +568,111 @@ public class ImmutableConciseSet
currIndex++;
if (itr.hasNext()) {
- wordsToAdd.add(new WordHolder(itr.next(), itr));
+ itr.word = itr.next();
+ maxChangedIndex = Math.max(maxChangedIndex, 0);
} else {
+ removeElement(theQ, 0, qSize);
+ qSize--;
wordsWalkedAtSequenceEnd = Math.min(itr.wordsWalked, wordsWalkedAtSequenceEnd);
}
- } else { // one fills
- int flipBitLiteral;
- WordHolder nextVal = theQ.peek();
+ } else if (ConciseSetUtils.isZeroSequence(word)) {
+ // extract a literal from the flip bits of the zero sequence
+ int flipBitLiteral = ConciseSetUtils.getLiteralFromZeroSeqFlipBit(word);
- while (nextVal != null &&
- nextVal.getIterator().startIndex == itr.startIndex) {
+ // advance everything past the longest zero sequence
+ int qIndex = 1;
+ while (qIndex < qSize &&
+ theQ[qIndex].startIndex < itr.wordsWalked) {
+ WordIterator i = theQ[qIndex];
+ int w = i.getWord();
+
+ if (i.startIndex == itr.startIndex) {
+ // if a literal was created from a flip bit, AND it with other literals or literals from flip bits in the
+ // same position
+ if (ConciseSetUtils.isLiteral(w)) {
+ flipBitLiteral &= w;
+ } else if (ConciseSetUtils.isZeroSequence(w)) {
+ flipBitLiteral &= ConciseSetUtils.getLiteralFromZeroSeqFlipBit(w);
+ } else {
+ assert ConciseSetUtils.isOneSequence(w);
+ flipBitLiteral &= ConciseSetUtils.getLiteralFromOneSeqFlipBit(w);
+ }
+ }
+
+ i.advanceTo(itr.wordsWalked);
+ if (i.hasNext()) {
+ i.word = i.next();
+ maxChangedIndex = qIndex;
+ qIndex++;
+ } else {
+ removeElement(theQ, qIndex, qSize);
+ qSize--;
+ wordsWalkedAtSequenceEnd = Math.min(i.wordsWalked, wordsWalkedAtSequenceEnd);
+ }
+ }
+
+ // advance longest zero literal forward and push result back to priority queue
+ // if a flip bit is still needed, put it in the correct position
+ int newWord = word & 0xC1FFFFFF;
+ if (flipBitLiteral != ConciseSetUtils.ALL_ZEROS_LITERAL) {
+ int position = Integer.numberOfTrailingZeros(flipBitLiteral) + 1;
+ newWord = (word & 0xC1FFFFFF) | (position << 25);
+ }
+ addAndCompact(retVal, newWord);
+ currIndex = itr.wordsWalked;
+
+ if (itr.hasNext()) {
+ itr.word = itr.next();
+ maxChangedIndex = Math.max(maxChangedIndex, 0);
+ } else {
+ removeElement(theQ, 0, qSize);
+ qSize--;
+ wordsWalkedAtSequenceEnd = Math.min(itr.wordsWalked, wordsWalkedAtSequenceEnd);
+ }
+ } else {
+ assert ConciseSetUtils.isOneSequence(word);
+ int flipBitLiteral;
+ int qIndex = 1;
+ while (qIndex < qSize &&
+ theQ[qIndex].startIndex == itr.startIndex) {
// check if literal can be created flip bits of other one sequences
- WordHolder entry = theQ.poll();
- int w = entry.getWord();
- WordIterator i = entry.getIterator();
+ WordIterator i = theQ[qIndex];
+ int w = i.getWord();
flipBitLiteral = ConciseSetUtils.getLiteralFromOneSeqFlipBit(w);
if (flipBitLiteral != ConciseSetUtils.ALL_ONES_LITERAL) {
- wordsToAdd.add(new WordHolder(flipBitLiteral, i));
+ i.word = flipBitLiteral;
+ maxChangedIndex = qIndex;
+ qIndex++;
} else if (i.hasNext()) {
- wordsToAdd.add(new WordHolder(i.next(), i));
+ i.word = i.next();
+ maxChangedIndex = qIndex;
+ qIndex++;
} else {
+ removeElement(theQ, qIndex, qSize);
+ qSize--;
wordsWalkedAtSequenceEnd = Math.min(i.wordsWalked, wordsWalkedAtSequenceEnd);
}
-
- nextVal = theQ.peek();
}
// check if a literal needs to be created from the flipped bits of this sequence
flipBitLiteral = ConciseSetUtils.getLiteralFromOneSeqFlipBit(word);
if (flipBitLiteral != ConciseSetUtils.ALL_ONES_LITERAL) {
- wordsToAdd.add(new WordHolder(flipBitLiteral, itr));
+ itr.word = flipBitLiteral;
+ maxChangedIndex = Math.max(maxChangedIndex, 0);
} else if (itr.hasNext()) {
- wordsToAdd.add(new WordHolder(itr.next(), itr));
+ itr.word = itr.next();
+ maxChangedIndex = Math.max(maxChangedIndex, 0);
} else {
+ removeElement(theQ, 0, qSize);
+ qSize--;
wordsWalkedAtSequenceEnd = Math.min(itr.wordsWalked, wordsWalkedAtSequenceEnd);
}
}
- theQ.addAll(wordsToAdd);
+ if (maxChangedIndex >= 0) {
+ partialSort(theQ, maxChangedIndex, qSize, INTERSECTION_COMPARATOR);
+ }
}
// fill in any missing one sequences
@@ -685,6 +686,35 @@ public class ImmutableConciseSet
return new ImmutableConciseSet(IntBuffer.wrap(retVal.toArray()));
}
+ /**
+ * Variation of insertion sort, elements [maxChangedIndex + 1, size) are sorted, elements [0, maxChangedIndex] should
+ * be inserted into that sorted range.
+ */
+ private static void partialSort(
+ final WordIterator[] a,
+ final int maxChangedIndex,
+ final int size,
+ final Comparator comp
+ )
+ {
+ for (int i = maxChangedIndex; i >= 0; i--) {
+ WordIterator it = a[i];
+ for (int j = i + 1; j < size; j++) {
+ WordIterator it2 = a[j];
+ if (comp.compare(it, it2) <= 0) {
+ break;
+ }
+ a[j - 1] = it2;
+ a[j] = it;
+ }
+ }
+ }
+
+ private static void removeElement(WordIterator[] q, int qIndex, int qSize)
+ {
+ System.arraycopy(q, qIndex + 1, q, qIndex, qSize - qIndex - 1);
+ }
+
public static ImmutableConciseSet doComplement(ImmutableConciseSet set)
{
if (set == null || set.isEmpty()) {
@@ -750,6 +780,31 @@ public class ImmutableConciseSet
} while (true);
}
+ final IntBuffer words;
+ final int lastWordIndex;
+ private final int size;
+
+ public ImmutableConciseSet()
+ {
+ this.words = null;
+ this.lastWordIndex = -1;
+ this.size = 0;
+ }
+
+ public ImmutableConciseSet(ByteBuffer byteBuffer)
+ {
+ this.words = byteBuffer.asIntBuffer();
+ this.lastWordIndex = words.capacity() - 1;
+ this.size = calcSize();
+ }
+
+ public ImmutableConciseSet(IntBuffer buffer)
+ {
+ this.words = buffer;
+ this.lastWordIndex = (words == null || buffer.capacity() == 0) ? -1 : words.capacity() - 1;
+ this.size = calcSize();
+ }
+
public byte[] toBytes()
{
if (words == null) {
@@ -935,25 +990,9 @@ public class ImmutableConciseSet
public IntSet.IntIterator iterator()
{
if (isEmpty()) {
- return new IntSet.IntIterator()
- {
- @Override
- public void skipAllBefore(int element) {/*empty*/}
-
- @Override
- public boolean hasNext() {return false;}
-
- @Override
- public int next() {throw new NoSuchElementException();}
-
- @Override
- public void remove() {throw new UnsupportedOperationException();}
-
- @Override
- public IntSet.IntIterator clone() {throw new UnsupportedOperationException();}
- };
+ return EmptyIntIterator.instance();
}
- return new BitIterator();
+ return new BitIterator(this);
}
public WordIterator newWordIterator()
@@ -961,131 +1000,7 @@ public class ImmutableConciseSet
return new WordIterator();
}
- private static class WordHolder
- {
- private final int word;
- private final WordIterator iterator;
-
- public WordHolder(
- int word,
- WordIterator iterator
- )
- {
- this.word = word;
- this.iterator = iterator;
- }
-
- public int getWord()
- {
- return word;
- }
-
- public WordIterator getIterator()
- {
- return iterator;
- }
- }
-
- // Based on the ConciseSet implementation by Alessandro Colantonio
- private class BitIterator implements IntSet.IntIterator
- {
- final ConciseSetUtils.LiteralAndZeroFillExpander litExp;
- final ConciseSetUtils.OneFillExpander oneExp;
-
- ConciseSetUtils.WordExpander exp;
- int nextIndex = 0;
- int nextOffset = 0;
-
- private BitIterator()
- {
- litExp = ConciseSetUtils.newLiteralAndZeroFillExpander();
- oneExp = ConciseSetUtils.newOneFillExpander();
-
- nextWord();
- }
-
- private BitIterator(
- ConciseSetUtils.LiteralAndZeroFillExpander litExp,
- ConciseSetUtils.OneFillExpander oneExp,
- ConciseSetUtils.WordExpander exp,
- int nextIndex,
- int nextOffset
- )
- {
- this.litExp = litExp;
- this.oneExp = oneExp;
- this.exp = exp;
- this.nextIndex = nextIndex;
- this.nextOffset = nextOffset;
- }
-
- @Override
- public boolean hasNext()
- {
- while (!exp.hasNext()) {
- if (nextIndex > lastWordIndex) {
- return false;
- }
- nextWord();
- }
- return true;
- }
-
- @Override
- public int next()
- {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- return exp.next();
- }
-
- @Override
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void skipAllBefore(int element)
- {
- while (true) {
- exp.skipAllBefore(element);
- if (exp.hasNext() || nextIndex > lastWordIndex) {
- return;
- }
- nextWord();
- }
- }
-
- @Override
- public IntSet.IntIterator clone()
- {
- return new BitIterator(
- (ConciseSetUtils.LiteralAndZeroFillExpander) litExp.clone(),
- (ConciseSetUtils.OneFillExpander) oneExp.clone(),
- exp.clone(),
- nextIndex,
- nextOffset
- );
- }
-
- private void nextWord()
- {
- final int word = words.get(nextIndex++);
- exp = ConciseSetUtils.isOneSequence(word) ? oneExp : litExp;
- exp.reset(nextOffset, word, true);
-
- // prepare next offset
- if (ConciseSetUtils.isLiteral(word)) {
- nextOffset += ConciseSetUtils.MAX_LITERAL_LENGTH;
- } else {
- nextOffset += ConciseSetUtils.maxLiteralLengthMultiplication(ConciseSetUtils.getSequenceCount(word) + 1);
- }
- }
- }
-
- public class WordIterator implements Iterator
+ public class WordIterator implements org.roaringbitmap.IntIterator, Cloneable
{
private int startIndex;
private int wordsWalked;
@@ -1093,7 +1008,11 @@ public class ImmutableConciseSet
private int nextWord;
private int currRow;
- private volatile boolean hasNextWord = false;
+ // Probably this is identical to currWord, or nextWord, or could be derived from one of those fields,
+ // but this is uncertain
+ int word;
+
+ private boolean hasNextWord = false;
WordIterator()
{
@@ -1129,12 +1048,12 @@ public class ImmutableConciseSet
}
@Override
- public Integer next()
+ public int next()
{
if (hasNextWord) {
currWord = nextWord;
hasNextWord = false;
- return new Integer(currWord);
+ return currWord;
}
currWord = words.get(++currRow);
@@ -1145,13 +1064,23 @@ public class ImmutableConciseSet
wordsWalked += ConciseSetUtils.getSequenceNumWords(currWord);
}
- return new Integer(currWord);
+ return currWord;
+ }
+
+ int getWord()
+ {
+ return word;
}
@Override
- public void remove()
+ public WordIterator clone()
{
- throw new UnsupportedOperationException();
+ try {
+ return (WordIterator) super.clone();
+ }
+ catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
}
}
}
diff --git a/extendedset/src/main/java/io/druid/extendedset/intset/IntSet.java b/extendedset/src/main/java/io/druid/extendedset/intset/IntSet.java
index 3f15daeb828..a3a1f8bf961 100755
--- a/extendedset/src/main/java/io/druid/extendedset/intset/IntSet.java
+++ b/extendedset/src/main/java/io/druid/extendedset/intset/IntSet.java
@@ -19,8 +19,6 @@
package io.druid.extendedset.intset;
-import io.druid.extendedset.ExtendedSet;
-
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
@@ -29,15 +27,8 @@ import java.util.List;
import java.util.NoSuchElementException;
/**
- * Very similar to {@link ExtendedSet} but for the primitive int
- * type.
- *
* @author Alessandro Colantonio
* @version $Id: IntSet.java 135 2011-01-04 15:54:48Z cocciasik $
- * @see ArraySet
- * @see ConciseSet
- * @see FastSet
- * @see HashIntSet
*/
public interface IntSet extends Cloneable, Comparable
{
@@ -609,7 +600,7 @@ public interface IntSet extends Cloneable, Comparable
* An {@link Iterator}-like interface that allows to "skip" some elements of
* the set
*/
- public interface IntIterator
+ public interface IntIterator extends org.roaringbitmap.IntIterator
{
/**
* @return true if the iterator has more elements.
diff --git a/extendedset/src/main/java/io/druid/extendedset/utilities/ArrayMap.java b/extendedset/src/main/java/io/druid/extendedset/utilities/ArrayMap.java
deleted file mode 100755
index 3026fdf2590..00000000000
--- a/extendedset/src/main/java/io/druid/extendedset/utilities/ArrayMap.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * (c) 2010 Alessandro Colantonio
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package io.druid.extendedset.utilities;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.util.AbstractMap;
-import java.util.AbstractSet;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-/**
- * A {@link Map} backed by an array, where keys are the indices of the array,
- * and values are the elements of the array.
- *
- * Modifications to the map (i.e., through {@link #put(Integer, Object)} and
- * {@link java.util.Map.Entry#setValue(Object)}) are reflected to the original array.
- * However, the map has a fixed length, that is the length of the array.
- *
- * @param the type of elements represented by columns
- *
- * @author Alessandro Colantonio
- * @version $Id$
- */
-public class ArrayMap extends AbstractMap implements java.io.Serializable
-{
- /**
- * generated serial ID
- */
- private static final long serialVersionUID = -578029467093308343L;
-
- /**
- * array backed by this map
- */
- private final T[] array;
- /**
- * first index of the map
- */
- private final int indexShift;
- /**
- * {@link Set} instance to iterate over #array
- */
- private transient Set> entrySet;
-
- /**
- * Initializes the map
- *
- * @param array array to manipulate
- * @param indexShift first index of the map
- */
- ArrayMap(T[] array, int indexShift)
- {
- this.array = array;
- this.indexShift = indexShift;
- entrySet = null;
- }
-
- /**
- * Initializes the map
- *
- * @param array array to manipulate
- */
- ArrayMap(T[] array)
- {
- this(array, 0);
- }
-
- /**
- * Test
- *
- * @param args
- */
- public static void main(String[] args)
- {
- ArrayMap am = new ArrayMap(new String[]{"Three", "Four", "Five"}, 3);
- System.out.println(am);
- am.put(5, "FIVE");
- System.out.println(am);
- System.out.println(am.get(5));
- System.out.println(am.containsKey(2));
- System.out.println(am.containsKey(3));
- System.out.println(am.containsValue("THREE"));
- System.out.println(am.keySet());
- System.out.println(am.values());
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Set> entrySet()
- {
- if (entrySet == null) {
- // create an entry for each element
- final List entries = new ArrayList(array.length);
- for (int i = 0; i < array.length; i++) {
- entries.add(new SimpleEntry(i));
- }
-
- // create the Set instance
- entrySet = new AbstractSet>()
- {
- @Override
- public Iterator> iterator()
- {
- return new Iterator>()
- {
- int curr = 0;
-
- @Override
- public boolean hasNext()
- {
- return curr < entries.size();
- }
-
- @Override
- public Entry next()
- {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- return entries.get(curr++);
- }
-
- @Override
- public void remove()
- {
- throw new IllegalArgumentException();
- }
- };
- }
-
- @Override
- public int size()
- {
- return entries.size();
- }
- };
- }
- return entrySet;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int size()
- {
- return array.length;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean containsKey(Object key)
- {
- int index = (Integer) key - indexShift;
- return (index >= 0) && (index < array.length);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public T get(Object key)
- {
- return array[(Integer) key - indexShift];
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public T put(Integer key, T value)
- {
- int actualIndex = key - indexShift;
- T old = array[actualIndex];
- array[actualIndex] = value;
- return old;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int hashCode()
- {
- return Arrays.hashCode(array);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj) {
- return true;
- }
- if (!super.equals(obj)) {
- return false;
- }
- if (!(obj instanceof ArrayMap>)) {
- return false;
- }
- return Arrays.equals(array, ((ArrayMap>) obj).array);
- }
-
- /**
- * Reconstruct the instance from a stream
- */
- private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException
- {
- s.defaultReadObject();
- entrySet = null;
- }
-
- /**
- * Entry of the map
- */
- private class SimpleEntry implements Entry
- {
- /**
- * index of {@link ArrayMap#array}
- */
- final int actualIndex;
-
- /**
- * Creates an entry
- *
- * @param index index of {@link ArrayMap#array}
- */
- private SimpleEntry(int index)
- {
- this.actualIndex = index;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Integer getKey()
- {
- return actualIndex + indexShift;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public T getValue()
- {
- return array[actualIndex];
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public T setValue(T value)
- {
- T old = array[actualIndex];
- array[actualIndex] = value;
- return old;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString()
- {
- return (actualIndex + indexShift) + "=" + array[actualIndex];
- }
- }
-}
diff --git a/extendedset/src/main/java/io/druid/extendedset/utilities/BitCount.java b/extendedset/src/main/java/io/druid/extendedset/utilities/BitCount.java
index 306a2e1e510..b6c7fa9b869 100755
--- a/extendedset/src/main/java/io/druid/extendedset/utilities/BitCount.java
+++ b/extendedset/src/main/java/io/druid/extendedset/utilities/BitCount.java
@@ -33,23 +33,6 @@ import java.util.Random;
*/
public class BitCount
{
- /**
- * Population count
- *
- * It counts a single word
- *
- * @param word word to count
- *
- * @return population count
- */
- public static int count(int word)
- {
- word -= ((word >>> 1) & 0x55555555);
- word = (word & 0x33333333) + ((word >>> 2) & 0x33333333);
- word = (word + (word >>> 4)) & 0x0F0F0F0F;
- return (word * 0x01010101) >>> 24;
- }
-
/**
* Population count
*
@@ -132,7 +115,7 @@ public class BitCount
{
int cnt = 0;
for (; x < n; x++) {
- cnt += count(data[x]);
+ cnt += Integer.bitCount(data[x]);
}
return cnt;
}
@@ -219,7 +202,7 @@ public class BitCount
{
int cnt = 0;
for (x++; x < n; x += 2) {
- cnt += count(data[x]);
+ cnt += Integer.bitCount(data[x]);
}
return cnt;
}
@@ -247,7 +230,7 @@ public class BitCount
int size1 = 0;
for (int j = 0; j < x.length; j++) {
- size1 += count(x[j]);
+ size1 += Integer.bitCount(x[j]);
}
int size2 = count(x);
@@ -256,7 +239,7 @@ public class BitCount
System.out.println("ERRORE!");
System.out.println(size1 + ", " + size2);
for (int j = 0; j < x.length; j++) {
- System.out.format("x[%d] = %d --> %d\n", j, x[j], count(x[j]));
+ System.out.format("x[%d] = %d --> %d\n", j, x[j], Integer.bitCount(x[j]));
}
return;
}
@@ -273,7 +256,7 @@ public class BitCount
int size1 = 0;
for (int j = 1; j < x.length; j += 2) {
- size1 += count(x[j]);
+ size1 += Integer.bitCount(x[j]);
}
int size2 = count_2(x);
@@ -282,7 +265,7 @@ public class BitCount
System.out.println("ERRORE!");
System.out.println(size1 + ", " + size2);
for (int j = 1; j < x.length; j += 2) {
- System.out.format("x[%d] = %d --> %d\n", j, x[j], count(x[j]));
+ System.out.format("x[%d] = %d --> %d\n", j, x[j], Integer.bitCount(x[j]));
}
return;
}
@@ -301,7 +284,7 @@ public class BitCount
@SuppressWarnings("unused")
int size = 0;
for (int j = 0; j < x.length; j++) {
- size += count(x[j]);
+ size += Integer.bitCount(x[j]);
}
}
System.out.println(System.currentTimeMillis() - t);
@@ -330,7 +313,7 @@ public class BitCount
@SuppressWarnings("unused")
int size = 0;
for (int j = 1; j < x.length; j += 2) {
- size += count(x[j]);
+ size += Integer.bitCount(x[j]);
}
}
System.out.println(System.currentTimeMillis() - t);
diff --git a/extendedset/src/main/java/io/druid/extendedset/utilities/CollectionMap.java b/extendedset/src/main/java/io/druid/extendedset/utilities/CollectionMap.java
deleted file mode 100755
index ec38ce38b99..00000000000
--- a/extendedset/src/main/java/io/druid/extendedset/utilities/CollectionMap.java
+++ /dev/null
@@ -1,317 +0,0 @@
-package io.druid.extendedset.utilities;
-
-import io.druid.extendedset.ExtendedSet;
-import io.druid.extendedset.intset.ConciseSet;
-import io.druid.extendedset.wrappers.IntegerSet;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.SortedSet;
-
-/**
- * This class implements a {@link Map} from a key of type K
to a
- * collection contains instances of I
.
- *
- * @param key type
- * @param item type
- * @param {@link Collection} subclass used to collect items
- *
- * @author Alessandro Colantonio
- * @version $Id: CollectionMap.java 152 2011-03-30 11:18:18Z cocciasik $
- */
-public class CollectionMap> extends LinkedHashMap
-{
- private static final long serialVersionUID = -2613391212228461025L;
-
- /**
- * empty collection
- */
- private final C emptySet;
-
- /**
- * Initializes the map by providing an instance of the empty collection
- *
- * @param emptySet the empty collection
- */
- public CollectionMap(C emptySet)
- {
- this.emptySet = emptySet;
- }
-
- /**
- * Generates a new {@link CollectionMap} instance. It is an alternative to
- * the constructor {@link #CollectionMap(Collection)} that reduces the code
- * to write.
- *
- * @param key type
- * @param item type
- * @param {@link Collection} subclass used to collect items
- * @param empty subset type
- * @param emptySet the empty collection
- *
- * @return the new instance of {@link CollectionMap}
- */
- public static , EX extends CX>
- CollectionMap newCollectionMap(EX emptySet)
- {
- return new CollectionMap(emptySet);
- }
-
- /**
- * Test procedure
- *
- * Expected output:
- *
- * {}
- * {A=[1]}
- * {A=[1, 2]}
- * {A=[1, 2], B=[3]}
- * {A=[1, 2], B=[3, 4, 5, 6]}
- * true
- * true
- * false
- * {A=[1], B=[3, 4, 5, 6]}
- * {A=[1], B=[3, 4, 5, 6]}
- * {A=[1], B=[6]}
- *
- *
- * @param args
- */
- public static void main(String[] args)
- {
- CollectionMap map = newCollectionMap(new IntegerSet(new ConciseSet()));
- System.out.println(map);
-
- map.putItem("A", 1);
- System.out.println(map);
-
- map.putItem("A", 2);
- System.out.println(map);
-
- map.putItem("B", 3);
- System.out.println(map);
-
- map.putAllItems("B", Arrays.asList(4, 5, 6));
- System.out.println(map);
-
- System.out.println(map.containsItem(1));
- System.out.println(map.containsItem(6));
- System.out.println(map.containsItem(7));
-
- map.removeItem("A", 2);
- System.out.println(map);
-
- map.removeItem("A", 3);
- System.out.println(map);
-
- map.removeAllItems("B", Arrays.asList(1, 2, 3, 4, 5));
- System.out.println(map);
- }
-
- /**
- * {@inheritDoc}
- */
- @SuppressWarnings("unchecked")
- @Override
- public CollectionMap clone()
- {
- // result
- CollectionMap cloned = new CollectionMap(emptySet);
-
- // clone all the entries
- cloned.putAll(this);
-
- // clone all the values
- if (emptySet instanceof Cloneable) {
- for (Entry e : cloned.entrySet()) {
- try {
- e.setValue((C) e.getValue().getClass().getMethod("clone").invoke(e.getValue()));
- }
- catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
- } else {
- for (Entry e : cloned.entrySet()) {
- C copy = cloneEmptySet();
- copy.addAll(e.getValue());
- e.setValue(copy);
- }
- }
- return cloned;
- }
-
- /**
- * Generates an empty {@link CollectionMap} instance with the same
- * collection type for values
- *
- * @return the empty {@link CollectionMap} instance
- */
- public CollectionMap empty()
- {
- return new CollectionMap(emptySet);
- }
-
- /**
- * Populates the current instance with the data from another map. In
- * particular, it creates the list of keys associated to each value.
- *
- * @param map the input map
- */
- public void mapValueToKeys(Map map)
- {
- for (Entry e : map.entrySet()) {
- putItem(e.getValue(), e.getKey());
- }
- }
-
- /**
- * Generates a clone of the empty set
- *
- * @return a clone of the empty set
- */
- @SuppressWarnings("unchecked")
- private C cloneEmptySet()
- {
- try {
- if (emptySet instanceof Cloneable) {
- return (C) emptySet.getClass().getMethod("clone").invoke(emptySet);
- }
- return (C) emptySet.getClass().newInstance();
- }
- catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Checks if there are some collections that contain the given item
- *
- * @param item item to check
- *
- * @return true
if the item exists within some collections
- */
- public boolean containsItem(I item)
- {
- for (Entry e : entrySet()) {
- if (e.getValue().contains(item)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Adds an item to the collection corresponding to the given key
- *
- * @param key the key for the identification of the collection
- * @param item item to add
- *
- * @return the updated collection of items for the given key
- */
- public C putItem(K key, I item)
- {
- C items = get(key);
- if (items == null) {
- put(key, items = cloneEmptySet());
- }
- items.add(item);
- return items;
- }
-
- /**
- * Adds a collection of items to the collection corresponding to the given key
- *
- * @param key the key for the identification of the collection
- * @param c items to add
- *
- * @return the updated collection of items for the given key
- */
- public C putAllItems(K key, Collection extends I> c)
- {
- C items = get(key);
- if (c == null) {
- put(key, items = cloneEmptySet());
- }
- items.addAll(c);
- return items;
- }
-
- /**
- * Removes the item from the collection corresponding to the given key
- *
- * @param key the key for the identification of the collection
- * @param item item to remove
- *
- * @return the updated collection of items for the given key
- */
- public C removeItem(K key, I item)
- {
- C items = get(key);
- if (items == null) {
- return null;
- }
- items.remove(item);
- if (items.isEmpty()) {
- remove(key);
- }
- return items;
- }
-
- /**
- * Removes a collection of items from the collection corresponding to the given key
- *
- * @param key the key for the identification of the collection
- * @param c items to remove
- *
- * @return the updated collection of items for the given key
- */
- public C removeAllItems(K key, Collection extends I> c)
- {
- C items = get(key);
- if (items == null) {
- return null;
- }
- items.removeAll(c);
- if (items.isEmpty()) {
- remove(key);
- }
- return items;
- }
-
- /**
- * Makes all collections read-only
- */
- @SuppressWarnings("unchecked")
- public void makeAllCollectionsUnmodifiable()
- {
- if (emptySet instanceof ExtendedSet) {
- for (Entry e : entrySet()) {
- e.setValue((C) ((ExtendedSet) e.getValue()).unmodifiable());
- }
- } else if (emptySet instanceof List) {
- for (Entry e : entrySet()) {
- e.setValue((C) (Collections.unmodifiableList((List) e.getValue())));
- }
- } else if (emptySet instanceof Set) {
- for (Entry e : entrySet()) {
- e.setValue((C) (Collections.unmodifiableSet((Set) e.getValue())));
- }
- } else if (emptySet instanceof SortedSet) {
- for (Entry e : entrySet()) {
- e.setValue((C) (Collections.unmodifiableSortedSet((SortedSet) e.getValue())));
- }
- } else {
- for (Entry e : entrySet()) {
- e.setValue((C) (Collections.unmodifiableCollection(e.getValue())));
- }
- }
-
- }
-}
diff --git a/extendedset/src/main/java/io/druid/extendedset/utilities/IntHashCode.java b/extendedset/src/main/java/io/druid/extendedset/utilities/IntHashCode.java
deleted file mode 100755
index 1aaa06bdbe1..00000000000
--- a/extendedset/src/main/java/io/druid/extendedset/utilities/IntHashCode.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * (c) 2010 Alessandro Colantonio
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.druid.extendedset.utilities;
-
-/**
- * Hash functions for integers and integer arrays.
- *
- * @author Alessandro Colantonio
- * @version $Id: IntHashCode.java 127 2010-12-21 20:22:12Z cocciasik $
- */
-public class IntHashCode
-{
- /**
- * Computes a hashcode for an integer
- *
- * Inspired by Thomas Wang's function, described at http://www.concentric.net/~ttwang/tech/inthash.htm
- *
- * @param key the given integer
- *
- * @return the hashcode
- */
- public static int hashCode(int key)
- {
- key = ~key + (key << 15);
- key ^= key >>> 12;
- key += key << 2;
- key ^= key >>> 4;
- key *= 2057;
- key ^= key >>> 16;
- return key;
- }
-
- /**
- * Computes the hashcode of an array of integers
- *
- * @param keys the given integer array
- *
- * @return the hashcode
- */
- public static int hashCode(int[] keys)
- {
- return hashCode(keys, keys.length, 0);
- }
-
- /**
- * Computes the hashcode of an array of integers
- *
- * It is based on MurmurHash3 Algorithm, described at http://sites.google.com/site/murmurhash
- *
- * @param keys the given integer array
- * @param len number of elements to include, that is
- * len <= keys.length
- * @param seed initial seed
- *
- * @return the hashcode
- */
- public static int hashCode(int[] keys, int len, int seed)
- {
- int h = 0x971e137b ^ seed;
- int c1 = 0x95543787;
- int c2 = 0x2ad7eb25;
-
- for (int i = 0; i < len; i++) {
- int k = keys[i];
- k *= c1;
- k = (k << 11) | (k >>> 21); // rotl k, 11
- k *= c2;
- h ^= k;
-
- h = (h << 2) - h + 0x52dce729;
- c1 = (c1 << 2) + c1 + 0x7b7d159c;
- c2 = (c2 << 2) + c2 + 0x6bce6396;
- }
-
- h ^= len;
- h ^= h >>> 16;
- h *= 0x85ebca6b;
- h ^= h >>> 13;
- h *= 0xc2b2ae35;
- h ^= h >>> 16;
- return h;
- }
-}
diff --git a/extendedset/src/main/java/io/druid/extendedset/utilities/IntList.java b/extendedset/src/main/java/io/druid/extendedset/utilities/IntList.java
index 51474c9fccb..501dbb362a4 100755
--- a/extendedset/src/main/java/io/druid/extendedset/utilities/IntList.java
+++ b/extendedset/src/main/java/io/druid/extendedset/utilities/IntList.java
@@ -7,23 +7,11 @@ import java.util.ArrayList;
*/
public class IntList
{
- private final ArrayList baseLists = new ArrayList();
+ private static final int ALLOCATION_SIZE = 1024;
- private final int allocateSize;
+ private final ArrayList