001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.collections4.multiset; 018 019import java.util.Set; 020 021import org.apache.commons.collections4.MultiSet; 022import org.apache.commons.collections4.collection.SynchronizedCollection; 023 024/** 025 * Decorates another {@link MultiSet} to synchronize its behaviour 026 * for a multi-threaded environment. 027 * <p> 028 * Methods are synchronized, then forwarded to the decorated multiset. 029 * Iterators must be separately synchronized around the loop. 030 * </p> 031 * 032 * @param <E> the type held in the multiset 033 * @since 4.1 034 */ 035public class SynchronizedMultiSet<E> extends SynchronizedCollection<E> implements MultiSet<E> { 036 037 /** Serialization version */ 038 private static final long serialVersionUID = 20150629L; 039 040 /** 041 * Factory method to create a synchronized multiset. 042 * 043 * @param <E> the type of the elements in the multiset 044 * @param multiset the multiset to decorate, must not be null 045 * @return a new synchronized MultiSet 046 * @throws NullPointerException if multiset is null 047 */ 048 public static <E> SynchronizedMultiSet<E> synchronizedMultiSet(final MultiSet<E> multiset) { 049 return new SynchronizedMultiSet<>(multiset); 050 } 051 052 //----------------------------------------------------------------------- 053 /** 054 * Constructor that wraps (not copies). 055 * 056 * @param multiset the multiset to decorate, must not be null 057 * @throws NullPointerException if multiset is null 058 */ 059 protected SynchronizedMultiSet(final MultiSet<E> multiset) { 060 super(multiset); 061 } 062 063 /** 064 * Constructor that wraps (not copies). 065 * 066 * @param multiset the multiset to decorate, must not be null 067 * @param lock the lock to use, must not be null 068 * @throws NullPointerException if multiset or lock is null 069 */ 070 protected SynchronizedMultiSet(final MultiSet<E> multiset, final Object lock) { 071 super(multiset, lock); 072 } 073 074 /** 075 * Gets the multiset being decorated. 076 * 077 * @return the decorated multiset 078 */ 079 @Override 080 protected MultiSet<E> decorated() { 081 return (MultiSet<E>) super.decorated(); 082 } 083 084 @Override 085 public boolean equals(final Object object) { 086 if (object == this) { 087 return true; 088 } 089 synchronized (lock) { 090 return decorated().equals(object); 091 } 092 } 093 094 @Override 095 public int hashCode() { 096 synchronized (lock) { 097 return decorated().hashCode(); 098 } 099 } 100 101 //----------------------------------------------------------------------- 102 103 @Override 104 public int add(final E object, final int count) { 105 synchronized (lock) { 106 return decorated().add(object, count); 107 } 108 } 109 110 @Override 111 public int remove(final Object object, final int count) { 112 synchronized (lock) { 113 return decorated().remove(object, count); 114 } 115 } 116 117 @Override 118 public int getCount(final Object object) { 119 synchronized (lock) { 120 return decorated().getCount(object); 121 } 122 } 123 124 @Override 125 public int setCount(final E object, final int count) { 126 synchronized (lock) { 127 return decorated().setCount(object, count); 128 } 129 } 130 131 @Override 132 public Set<E> uniqueSet() { 133 synchronized (lock) { 134 final Set<E> set = decorated().uniqueSet(); 135 return new SynchronizedSet<>(set, lock); 136 } 137 } 138 139 @Override 140 public Set<Entry<E>> entrySet() { 141 synchronized (lock) { 142 final Set<MultiSet.Entry<E>> set = decorated().entrySet(); 143 return new SynchronizedSet<>(set, lock); 144 } 145 } 146 147 //----------------------------------------------------------------------- 148 /** 149 * Synchronized Set for the MultiSet class. 150 */ 151 static class SynchronizedSet<T> extends SynchronizedCollection<T> implements Set<T> { 152 /** Serialization version */ 153 private static final long serialVersionUID = 20150629L; 154 155 /** 156 * Constructor. 157 * @param set the set to decorate 158 * @param lock the lock to use, shared with the multiset 159 */ 160 SynchronizedSet(final Set<T> set, final Object lock) { 161 super(set, lock); 162 } 163 } 164 165}