org.infinispan.distribution.util.ReadOnlySegmentAwareCollection Maven / Gradle / Ivy
package org.infinispan.distribution.util;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.util.AbstractDelegatingCollection;
/**
* Set implementation that shows a read only view of the provided set by only allowing
* entries that map to a given segment using the provided consistent hash.
*
* This set is useful when you don't want to copy an entire set but only need to see
* values from the given segments.
*
* Note many operations are not constant time when using this set. Please check the method
* you are using to see if it will perform differently than normally expected.
* @author wburns
* @since 7.2
*/
public class ReadOnlySegmentAwareCollection extends AbstractDelegatingCollection {
protected final Collection set;
protected final ConsistentHash ch;
protected final Set allowedSegments;
public ReadOnlySegmentAwareCollection(Collection set, ConsistentHash ch, Set allowedSegments) {
super();
this.set = Collections.unmodifiableCollection(set);
this.ch = ch;
this.allowedSegments = allowedSegments;
}
@Override
protected Collection delegate() {
return set;
}
protected boolean valueAllowed(Object obj) {
int segment = ch.getSegment(obj);
return allowedSegments.contains(segment);
}
@Override
public boolean contains(Object o) {
if (valueAllowed(o)) {
return super.contains(o);
}
return false;
}
@Override
public boolean containsAll(Collection> c) {
for (Object obj : c) {
if (valueAllowed(obj) && !super.contains(obj)) {
return false;
}
}
return true;
}
/**
* Checks if the provided set is empty. This is done by iterating over all of the values
* until it can find a key that maps to a given segment.
*
* This method should always be preferred over checking the size to see if it is empty.
*
* This time complexity for this method between O(1) to O(N).
*/
@Override
public boolean isEmpty() {
Iterator iter = iterator();
return !iter.hasNext();
}
/**
* Returns the size of the read only set. This is done by iterating over all of the
* values counting all that are in the segments.
*
* If you are using this method to verify if the set is empty, you should instead use
* the {@link ReadOnlySegmentAwareEntryCollection#isEmpty()} as it will perform better if the
* size is only used for this purpose.
*
* This time complexity for this method is always O(N).
*/
@Override
public int size() {
Iterator iter = iterator();
int count = 0;
while (iter.hasNext()) {
iter.next();
count++;
}
return count;
}
@Override
public Iterator iterator() {
return new ReadOnlySegmentAwareIterator<>(super.iterator(), ch, allowedSegments);
}
}