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.multimap; 018 019import java.io.IOException; 020import java.io.ObjectInputStream; 021import java.io.ObjectOutputStream; 022import java.io.Serializable; 023import java.util.HashMap; 024import java.util.HashSet; 025import java.util.Map; 026 027import org.apache.commons.collections4.MultiValuedMap; 028 029/** 030 * Implements a {@code SetValuedMap}, using a {@link HashMap} to provide data 031 * storage and {@link HashSet}s as value collections. This is the standard 032 * implementation of a SetValuedMap. 033 * <p> 034 * <strong>Note that HashSetValuedHashMap is not synchronized and is not 035 * thread-safe.</strong> If you wish to use this map from multiple threads 036 * concurrently, you must use appropriate synchronization. This class may throw 037 * exceptions when accessed by concurrent threads without synchronization. 038 * 039 * @param <K> the type of the keys in this map 040 * @param <V> the type of the values in this map 041 * @since 4.1 042 */ 043public class HashSetValuedHashMap<K, V> extends AbstractSetValuedMap<K, V> 044 implements Serializable { 045 046 /** Serialization Version */ 047 private static final long serialVersionUID = 20151118L; 048 049 /** 050 * The initial map capacity used when none specified in constructor. 051 */ 052 private static final int DEFAULT_INITIAL_MAP_CAPACITY = 16; 053 054 /** 055 * The initial set capacity when using none specified in constructor. 056 */ 057 private static final int DEFAULT_INITIAL_SET_CAPACITY = 3; 058 059 /** 060 * The initial list capacity when creating a new value collection. 061 */ 062 private final int initialSetCapacity; 063 064 /** 065 * Creates an empty HashSetValuedHashMap with the default initial 066 * map capacity (16) and the default initial set capacity (3). 067 */ 068 public HashSetValuedHashMap() { 069 this(DEFAULT_INITIAL_MAP_CAPACITY, DEFAULT_INITIAL_SET_CAPACITY); 070 } 071 072 /** 073 * Creates an empty HashSetValuedHashMap with the default initial 074 * map capacity (16) and the specified initial set capacity. 075 * 076 * @param initialSetCapacity the initial capacity used for value collections 077 */ 078 public HashSetValuedHashMap(final int initialSetCapacity) { 079 this(DEFAULT_INITIAL_MAP_CAPACITY, initialSetCapacity); 080 } 081 082 /** 083 * Creates an empty HashSetValuedHashMap with the specified initial 084 * map and list capacities. 085 * 086 * @param initialMapCapacity the initial hashmap capacity 087 * @param initialSetCapacity the initial capacity used for value collections 088 */ 089 public HashSetValuedHashMap(final int initialMapCapacity, final int initialSetCapacity) { 090 super(new HashMap<K, HashSet<V>>(initialMapCapacity)); 091 this.initialSetCapacity = initialSetCapacity; 092 } 093 094 /** 095 * Creates an HashSetValuedHashMap copying all the mappings of the given map. 096 * 097 * @param map a <code>MultiValuedMap</code> to copy into this map 098 */ 099 public HashSetValuedHashMap(final MultiValuedMap<? extends K, ? extends V> map) { 100 this(map.size(), DEFAULT_INITIAL_SET_CAPACITY); 101 super.putAll(map); 102 } 103 104 /** 105 * Creates an HashSetValuedHashMap copying all the mappings of the given map. 106 * 107 * @param map a <code>Map</code> to copy into this map 108 */ 109 public HashSetValuedHashMap(final Map<? extends K, ? extends V> map) { 110 this(map.size(), DEFAULT_INITIAL_SET_CAPACITY); 111 super.putAll(map); 112 } 113 114 // ----------------------------------------------------------------------- 115 @Override 116 protected HashSet<V> createCollection() { 117 return new HashSet<>(initialSetCapacity); 118 } 119 120 // ----------------------------------------------------------------------- 121 private void writeObject(final ObjectOutputStream oos) throws IOException { 122 oos.defaultWriteObject(); 123 doWriteObject(oos); 124 } 125 126 private void readObject(final ObjectInputStream ois) throws IOException, ClassNotFoundException { 127 ois.defaultReadObject(); 128 setMap(new HashMap<K, HashSet<V>>()); 129 doReadObject(ois); 130 } 131 132}