对于Multiset集合可以存储重复的值,他的强大之处是他的同一个值个数统计功能。实现类为HashMulitset类,他的继承关系图为:
从Multiset接口开始分析源码:
public interface Multiset<E> extends Collection<E> {
//返回给定参数元素的个数
int count(@Nullable Object var1);
//向其中添加指定个数的元素
int add(@Nullable E var1, int var2);
//移除相应个数的元素
int remove(@Nullable Object var1, int var2);
//设定某一个元素的重复次数
int setCount(E var1, int var2);
//将符合原有重复个数的元素修改为新的重复次数
boolean setCount(E var1, int var2, int var3);
//将不同的元素放入一个Set中
Set<E> elementSet();
//类似与Map.entrySet 返回Set<Multiset.Entry>。包含的Entry支持使用getElement()和getCount()
Set<Multiset.Entry<E>> entrySet();
boolean equals(@Nullable Object var1);
int hashCode();
String toString();
//返回迭代器
Iterator<E> iterator();
//判断是否存在某个元素
boolean contains(@Nullable Object var1);
//判断是否存在集合中所有元素
boolean containsAll(Collection<?> var1);
//添加元素
boolean add(E var1);
//删除某个元素
boolean remove(@Nullable Object var1);
//删除集合中所有元素
boolean removeAll(Collection<?> var1);
boolean retainAll(Collection<?> var1);
public interface Entry<E> {
E getElement();
int getCount();
boolean equals(Object var1);
int hashCode();
String toString();
}
}
对于Multiset的接口中方法的实现在AbstractMapBasedMultiset抽象类中,下面针对AbstractMapBasedMultiset类的存储数据结构。add、remove、count和迭代器的实现进行分析
存储数据结构
private transient Map<E, Count> backingMap;
可以看到他的实际存储结构为一个Map,key为存储元素,Count类型存储是key这个元素的个数,看一下Count源码:
final class Count implements Serializable {
//记录当前个数
private int value;
//构造方法,为变量赋值
Count(int value) {
this.value = value;
}
//获取当前个数
public int get() {
return this.value;
}
//加上指定个数,先加在返回加完后的值
public int getAndAdd(int delta) {
int result = this.value;
this.value = result + delta;
return result;
}
//加上指定个数,先返回,在进行想加
public int addAndGet(int delta) {
return this.value += delta;
}
//直接设置当前个数
public void set(int newValue) {
this.value = newValue;
}
//先设置新的值在返回这个值大小
public int getAndSet(int newValue) {
int result = this.value;
this.value = newValue;
return result;
}
public int hashCode() {
return this.value;
}
public boolean equals(@Nullable Object obj) {
return obj instanceof Count && ((Count)obj).value == this.value;
}
public String toString() {
return Integer.toString(this.value);
}
}
构造方法
protected AbstractMapBasedMultiset(Map<E, Count> backingMap) {
//存储的Map可以为任意类型的Map
this.backingMap = (Map)Preconditions.checkNotNull(backingMap);
//获取当前Multiset长度
this.size = (long)super.size();
}
add方法
public int add(@Nullable E element, int occurrences) {
//如果想要添加的个数为0
if(occurrences == 0) {
//如果存在则返回这个元素的个数,否则返回0
return this.count(element);
} else {
Preconditions.checkArgument(occurrences > 0, "occurrences cannot be negative: %s", new Object[]{Integer.valueOf(occurrences)});
//根据想要插入的元素在map中找到Count
Count frequency = (Count)this.backingMap.get(element);
int oldCount;
//如果key所对应的Count为null
if(frequency == null) {
//设置原来数据为0
oldCount = 0;
//将这个元素和所对应的Count添加到Map中
this.backingMap.put(element, new Count(occurrences));
} else {
//获取原来个数
oldCount = frequency.get();
//计算出新的个数
long newCount = (long)oldCount + (long)occurrences;
Preconditions.checkArgument(newCount <= 2147483647L, "too many occurrences: %s", new Object[]{Long.valueOf(newCount)});
//为key所对应的Count添加occurrences个
frequency.getAndAdd(occurrences);
}
//将当前的size加上occurrences
this.size += (long)occurrences;
//返回原来数据
return oldCount;
}
}
remove方法
public int remove(@Nullable Object element, int occurrences) {
//如果想要删除0个
if(occurrences == 0) {
//返回当前这个元素的个数,如果不存在容器中返回0
return this.count(element);
} else {
Preconditions.checkArgument(occurrences > 0, "occurrences cannot be negative: %s", new Object[]{Integer.valueOf(occurrences)});
//根据要删除的值作为key获取到他的Count
Count frequency = (Count)this.backingMap.get(element);
//如果对应的Count为null,则返回0
if(frequency == null) {
return 0;
} else {
//获取当前个数
int oldCount = frequency.get();
int numberRemoved;
//如果原来个数大于想要删除的个数
if(oldCount > occurrences) {
numberRemoved = occurrences;
} else {
//如果原来个数小于想要删除的个数
numberRemoved = oldCount;
//直接将这个元素在Map中删除
this.backingMap.remove(element);
}
//设置这个元素对应的Count
frequency.addAndGet(-numberRemoved);
this.size -= (long)numberRemoved;
return oldCount;
}
}
}
count方法
public int count(@Nullable Object element) {
//以传入的作为key,在map容器中找到相对应的Count
Count frequency = (Count)Maps.safeGet(this.backingMap, element);
//如果这个Count为空,则返回0,否则返回Count中的值
return frequency == null?0:frequency.get();
}
迭代器
public Iterator<E> iterator() {
return new AbstractMapBasedMultiset.MapBasedMultisetIterator();
}
可以看到Multiset中有一个实现了Iterator接口的类:
private class MapBasedMultisetIterator implements Iterator<E> {
final Iterator<java.util.Map.Entry<E, Count>> entryIterator;
java.util.Map.Entry<E, Count> currentEntry;
int occurrencesLeft;
boolean canRemove;
MapBasedMultisetIterator() {
//获取当前map容器的迭代器
this.entryIterator = AbstractMapBasedMultiset.this.backingMap.entrySet().iterator();
}
//根据当前迭代器判断是否还有元素
public boolean hasNext() {
return this.occurrencesLeft > 0 || this.entryIterator.hasNext();
}
public E next() {
//如果occurrencesLeft为0,则说明现在处于刚开始,或上一个元素完成
if(this.occurrencesLeft == 0) {
//迭代器向下获取一个元素
this.currentEntry = (java.util.Map.Entry)this.entryIterator.next();
//获取到当前元素的个数
this.occurrencesLeft = ((Count)this.currentEntry.getValue()).get();
}
//因为是获取一个元素,所以减去这一个
--this.occurrencesLeft;
this.canRemove = true;
return this.currentEntry.getKey();
}
public void remove() {
CollectPreconditions.checkRemove(this.canRemove);
int frequency = ((Count)this.currentEntry.getValue()).get();
if(frequency <= 0) {
throw new ConcurrentModificationException();
} else {
if(((Count)this.currentEntry.getValue()).addAndGet(-1) == 0) {
this.entryIterator.remove();
}
AbstractMapBasedMultiset.access$110(AbstractMapBasedMultiset.this);
this.canRemove = false;
}
}
}
这个迭代器的好处是,存储多个相同的值,不会占用多个地方,只会占用1个位置。