All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.solovyev.common.collections.multiset.AbstractMapManyInstancesMultiSet Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2013 serso aka se.solovyev
 *
 * 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.
 *
 * ---------------------------------------------------------------------
 * Contact details
 *
 * Email: [email protected]
 * Site:  http://se.solovyev.org
 */

package org.solovyev.common.collections.multiset;

import javax.annotation.Nonnull;
import java.util.*;

abstract class AbstractMapManyInstancesMultiSet extends AbstractMultiSet implements ManyInstancesMultiSet {

	@Nonnull
	private final Map> backingMap;

	protected AbstractMapManyInstancesMultiSet(@Nonnull Map> backingMap) {
		this.backingMap = backingMap;
	}

	@Override
	public int count(E e) {
		return get(e).size();
	}

	// always returns unmodifiable list
	@Nonnull
	private List get(E e) {
		final List list = backingMap.get(e);
		return list == null ? Collections.emptyList() : Collections.unmodifiableList(list);
	}

	@Nonnull
	@Override
	public Collection getAll(E e) {
		return get(e);
	}

	@Nonnull
	@Override
	public Set toElementSet() {
		final Set result = new HashSet();

		for (Map.Entry> entry : backingMap.entrySet()) {
			final List list = entry.getValue();
			if (list != null && !list.isEmpty()) {
				result.add(entry.getKey());
			}
		}

		return result;
	}

	@Override
	public boolean add(E e, int count) {
		MultiSets.checkAdd(count);

		final List oldList = get(e);

		final List newList = new ArrayList(oldList);
		for (int i = 0; i < count; i++) {
			newList.add(e);
		}

		this.backingMap.put(e, newList);

		return count > 0;
	}

	@Override
	public int remove(E e, int count) {
		MultiSets.checkRemove(count);

		final List list = backingMap.get(e);

		final int result = list == null ? 0 : list.size();

		int i = 0;
		if (list != null) {
			for (Iterator it = list.iterator(); it.hasNext() && i < count; i++) {
				it.next();
				it.remove();
			}
		}

		return result;
	}

	@Override
	public int size() {
		int result = 0;

		for (List list : backingMap.values()) {
			result += list.size();
		}

		return result;
	}

	@Override
	public boolean contains(Object o) {
		return !get((E) o).isEmpty();
	}

	@Override
	public Iterator iterator() {
		return new ValueIterator();
	}

	private class ValueIterator implements Iterator {
		private final Iterator>> keyIterator;
		private Collection collection;
		private Iterator valueIterator;

		private ValueIterator() {
			keyIterator = backingMap.entrySet().iterator();
			if (keyIterator.hasNext()) {
				findValueIteratorAndKey();
			} else {
				valueIterator = (Iterator) MultiSets.EMPTY_MODIFIABLE_ITERATOR;
			}
		}

		void findValueIteratorAndKey() {
			Map.Entry> entry = keyIterator.next();
			collection = entry.getValue();
			valueIterator = collection.iterator();
		}

		@Override
		public boolean hasNext() {
			return keyIterator.hasNext() || valueIterator.hasNext();
		}

		@Override
		public E next() {
			if (!valueIterator.hasNext()) {
				findValueIteratorAndKey();
			}

			return valueIterator.next();
		}

		@Override
		public void remove() {
			valueIterator.remove();
			if (collection.isEmpty()) {
				keyIterator.remove();
			}
		}
	}

	@Override
	public void clear() {
		this.backingMap.clear();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy