Merge branch 'master' of https://gitbox.apache.org/repos/asf/commons-collections.git
This commit is contained in:
commit
3a22be2c1c
|
@ -58,10 +58,11 @@
|
||||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add commons.easymock.version to parameterize EasyMock version.</action>
|
<action type="add" dev="ggregory" due-to="Gary Gregory">Add commons.easymock.version to parameterize EasyMock version.</action>
|
||||||
<action type="add" issue="COLLECTIONS-869" dev="ggregory" due-to="Gary Gregory">Add org.apache.commons.collections4.IteratorUtils.chainedIterator(Iterator<? extends Iterator<? extends E>>).</action>
|
<action type="add" issue="COLLECTIONS-869" dev="ggregory" due-to="Gary Gregory">Add org.apache.commons.collections4.IteratorUtils.chainedIterator(Iterator<? extends Iterator<? extends E>>).</action>
|
||||||
<action type="add" dev="ggregory" due-to="Peter De Maeyer" issue="COLLECTIONS-533">Add ArrayListValuedLinkedHashMap #560.</action>
|
<action type="add" dev="ggregory" due-to="Peter De Maeyer" issue="COLLECTIONS-533">Add ArrayListValuedLinkedHashMap #560.</action>
|
||||||
<action type="fix" dev="ggregory" due-to="Gary Gregory">Add missing test AbstractIteratorTest.testForEachRemaining().</action>
|
<action type="add" dev="ggregory" due-to="Gary Gregory">Add missing test AbstractIteratorTest.testForEachRemaining().</action>
|
||||||
<action type="fix" dev="ggregory" due-to="Gary Gregory, Claude Warren">Add FilterIterator.removeNext() #564.</action>
|
<action type="add" dev="ggregory" due-to="Gary Gregory, Claude Warren">Add FilterIterator.removeNext() #564.</action>
|
||||||
<action type="fix" issue="COLLECTIONS-870" dev="ggregory" due-to="Claude Warren, Gary Gregory">Added ExtendedIterator and tests #564.</action>
|
<action type="add" issue="COLLECTIONS-870" dev="ggregory" due-to="Claude Warren, Gary Gregory">Add ExtendedIterator and tests #564.</action>
|
||||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Refactor ExtendedIterator and FilterIterator with a new interface IteratorOperations.</action>
|
<action type="add" dev="ggregory" due-to="Gary Gregory">Refactor ExtendedIterator and FilterIterator with a new interface IteratorOperations.</action>
|
||||||
|
<action type="add" issue="COLLECTIONS-871" dev="ggregory" due-to="Peter De Maeyer">Add LinkedHashSetValuedLinkedHashMap #565.</action>
|
||||||
<!-- UPDATE -->
|
<!-- UPDATE -->
|
||||||
<action type="update" dev="ggregory" due-to="Gary Gregory">Bump org.apache.commons:commons-parent from 71 to 78 #534, #545, #550 #555, #566.</action>
|
<action type="update" dev="ggregory" due-to="Gary Gregory">Bump org.apache.commons:commons-parent from 71 to 78 #534, #545, #550 #555, #566.</action>
|
||||||
<action type="update" issue="COLLECTIONS-857" dev="ggregory" due-to="Claude Warren">Update bloom filter documentation #508.</action>
|
<action type="update" issue="COLLECTIONS-857" dev="ggregory" due-to="Claude Warren">Update bloom filter documentation #508.</action>
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.collections4.multimap;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.MultiValuedMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a {@code SetValuedMap}, using a {@link LinkedHashMap} to provide data
|
||||||
|
* storage and {@link LinkedHashSet}s as value collections. This is the standard
|
||||||
|
* implementation of a SetValuedMap.
|
||||||
|
* <p>
|
||||||
|
* <strong>Note that LinkedHashSetValuedLinkedHashMap is not synchronized and is not
|
||||||
|
* thread-safe.</strong> If you wish to use this map from multiple threads
|
||||||
|
* concurrently, you must use appropriate synchronization. This class may throw
|
||||||
|
* exceptions when accessed by concurrent threads without synchronization.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param <K> the type of the keys in this map
|
||||||
|
* @param <V> the type of the values in this map
|
||||||
|
* @since 4.5.0-M3
|
||||||
|
*/
|
||||||
|
public class LinkedHashSetValuedLinkedHashMap<K, V> extends AbstractSetValuedMap<K, V>
|
||||||
|
implements Serializable {
|
||||||
|
|
||||||
|
/** Serialization Version */
|
||||||
|
private static final long serialVersionUID = 20241020L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The initial map capacity used when none specified in constructor.
|
||||||
|
*/
|
||||||
|
private static final int DEFAULT_INITIAL_MAP_CAPACITY = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The initial set capacity when using none specified in constructor.
|
||||||
|
*/
|
||||||
|
private static final int DEFAULT_INITIAL_SET_CAPACITY = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The initial list capacity when creating a new value collection.
|
||||||
|
*/
|
||||||
|
private final int initialSetCapacity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an empty LinkedHashSetValuedHashMap with the default initial
|
||||||
|
* map capacity (16) and the default initial set capacity (3).
|
||||||
|
*/
|
||||||
|
public LinkedHashSetValuedLinkedHashMap() {
|
||||||
|
this(DEFAULT_INITIAL_MAP_CAPACITY, DEFAULT_INITIAL_SET_CAPACITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an empty LinkedHashSetValuedHashMap with the default initial
|
||||||
|
* map capacity (16) and the specified initial set capacity.
|
||||||
|
*
|
||||||
|
* @param initialSetCapacity the initial capacity used for value collections
|
||||||
|
*/
|
||||||
|
public LinkedHashSetValuedLinkedHashMap(final int initialSetCapacity) {
|
||||||
|
this(DEFAULT_INITIAL_MAP_CAPACITY, initialSetCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an empty LinkedHashSetValuedHashMap with the specified initial
|
||||||
|
* map and list capacities.
|
||||||
|
*
|
||||||
|
* @param initialMapCapacity the initial hashmap capacity
|
||||||
|
* @param initialSetCapacity the initial capacity used for value collections
|
||||||
|
*/
|
||||||
|
public LinkedHashSetValuedLinkedHashMap(final int initialMapCapacity, final int initialSetCapacity) {
|
||||||
|
super(new LinkedHashMap<>(initialMapCapacity));
|
||||||
|
this.initialSetCapacity = initialSetCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an LinkedHashSetValuedHashMap copying all the mappings of the given map.
|
||||||
|
*
|
||||||
|
* @param map a {@code Map} to copy into this map
|
||||||
|
*/
|
||||||
|
public LinkedHashSetValuedLinkedHashMap(final Map<? extends K, ? extends V> map) {
|
||||||
|
this(map.size(), DEFAULT_INITIAL_SET_CAPACITY);
|
||||||
|
super.putAll(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an LinkedHashSetValuedHashMap copying all the mappings of the given map.
|
||||||
|
*
|
||||||
|
* @param map a {@code MultiValuedMap} to copy into this map
|
||||||
|
*/
|
||||||
|
public LinkedHashSetValuedLinkedHashMap(final MultiValuedMap<? extends K, ? extends V> map) {
|
||||||
|
this(map.size(), DEFAULT_INITIAL_SET_CAPACITY);
|
||||||
|
super.putAll(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LinkedHashSet<V> createCollection() {
|
||||||
|
return new LinkedHashSet<>(initialSetCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes an instance from an ObjectInputStream.
|
||||||
|
*
|
||||||
|
* @param in The source ObjectInputStream.
|
||||||
|
* @throws IOException Any of the usual Input/Output related exceptions.
|
||||||
|
* @throws ClassNotFoundException A class of a serialized object cannot be found.
|
||||||
|
*/
|
||||||
|
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||||
|
in.defaultReadObject();
|
||||||
|
setMap(new LinkedHashMap<>());
|
||||||
|
doReadObject(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes this object to an ObjectOutputStream.
|
||||||
|
*
|
||||||
|
* @param out the target ObjectOutputStream.
|
||||||
|
* @throws IOException thrown when an I/O errors occur writing to the target stream.
|
||||||
|
*/
|
||||||
|
private void writeObject(final ObjectOutputStream out) throws IOException {
|
||||||
|
out.defaultWriteObject();
|
||||||
|
doWriteObject(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -193,9 +193,9 @@ public class HashSetValuedHashMapTest<K, V> extends AbstractMultiValuedMapTest<K
|
||||||
|
|
||||||
// public void testCreate() throws Exception {
|
// public void testCreate() throws Exception {
|
||||||
// writeExternalFormToDisk((java.io.Serializable) makeObject(),
|
// writeExternalFormToDisk((java.io.Serializable) makeObject(),
|
||||||
// "src/test/resources/data/test/HashSetValuedHashMap.emptyCollection.version4.1.obj");
|
// "src/test/resources/org/apache/commons/collections4/data/test/HashSetValuedHashMap.emptyCollection.version4.1.obj");
|
||||||
// writeExternalFormToDisk((java.io.Serializable) makeFullMap(),
|
// writeExternalFormToDisk((java.io.Serializable) makeFullMap(),
|
||||||
// "src/test/resources/data/test/HashSetValuedHashMap.fullCollection.version4.1.obj");
|
// "src/test/resources/org/apache/commons/collections4/data/test/HashSetValuedHashMap.fullCollection.version4.1.obj");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.collections4.multimap;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotSame;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.MultiValuedMap;
|
||||||
|
import org.apache.commons.collections4.SetValuedMap;
|
||||||
|
import org.apache.commons.collections4.collection.AbstractCollectionTest;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests {@link LinkedHashSetValuedLinkedHashMap}.
|
||||||
|
*/
|
||||||
|
public class LinkedHashSetValuedLinkedHashMapTest<K, V> extends AbstractMultiValuedMapTest<K, V> {
|
||||||
|
|
||||||
|
public LinkedHashSetValuedLinkedHashMapTest() {
|
||||||
|
super(LinkedHashSetValuedLinkedHashMapTest.class.getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getIterationBehaviour() {
|
||||||
|
return AbstractCollectionTest.UNORDERED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isHashSetValue() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MultiValuedMap<K, V> makeConfirmedMap() {
|
||||||
|
return new LinkedHashSetValuedLinkedHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SetValuedMap<K, V> makeObject() {
|
||||||
|
return new LinkedHashSetValuedLinkedHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCompatibilityVersion() {
|
||||||
|
return "4.5"; // LinkedHashSetValuedLinkedHashMap was added in version 4.5
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLinkedHashSetValuedLinkedHashMap_2() {
|
||||||
|
final Map<K, V> map = new HashMap<>();
|
||||||
|
final SetValuedMap<K, V> map1;
|
||||||
|
final SetValuedMap<K, V> map2;
|
||||||
|
|
||||||
|
map.put((K) "A", (V) "W");
|
||||||
|
map.put((K) "B", (V) "X");
|
||||||
|
map.put((K) "C", (V) "F");
|
||||||
|
map1 = new LinkedHashSetValuedLinkedHashMap<>(map);
|
||||||
|
assertEquals(1, map1.get((K) "A").size());
|
||||||
|
|
||||||
|
map.remove("A");
|
||||||
|
map.remove("B");
|
||||||
|
map.remove("C");
|
||||||
|
map2 = new LinkedHashSetValuedLinkedHashMap<>(map);
|
||||||
|
assertEquals("{}", map2.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHashSetValueHashMap() {
|
||||||
|
final SetValuedMap<K, V> setMap = new LinkedHashSetValuedLinkedHashMap<>(4);
|
||||||
|
assertEquals(0, setMap.get((K) "whatever").size());
|
||||||
|
|
||||||
|
final Set<V> set = setMap.get((K) "A");
|
||||||
|
set.add((V) "W");
|
||||||
|
set.add((V) "X");
|
||||||
|
set.add((V) "F");
|
||||||
|
assertEquals(3, setMap.get((K) "A").size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHashSetValueHashMap_1() {
|
||||||
|
final MultiValuedMap<K, V> map = new ArrayListValuedHashMap<>();
|
||||||
|
final SetValuedMap<K, V> map1;
|
||||||
|
final SetValuedMap<K, V> map2 = makeObject();
|
||||||
|
final SetValuedMap<K, V> map3;
|
||||||
|
|
||||||
|
map.put((K) "A", (V) "W");
|
||||||
|
map.put((K) "A", (V) "X");
|
||||||
|
map.put((K) "A", (V) "F");
|
||||||
|
map1 = new LinkedHashSetValuedLinkedHashMap<>(map);
|
||||||
|
assertEquals(3, map1.get((K) "A").size());
|
||||||
|
map2.put((K) "A", (V) "X");
|
||||||
|
map2.put((K) "A", (V) "F");
|
||||||
|
map2.put((K) "A", (V) "W");
|
||||||
|
assertEquals(map1, map2);
|
||||||
|
assertEquals(map1.hashCode(), map2.hashCode());
|
||||||
|
|
||||||
|
map.remove("A");
|
||||||
|
map3 = new LinkedHashSetValuedLinkedHashMap<>(map);
|
||||||
|
assertEquals("{}", map3.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testSetValuedMapAdd() {
|
||||||
|
final SetValuedMap<K, V> setMap = makeObject();
|
||||||
|
assertTrue(setMap.get((K) "whatever") instanceof Set);
|
||||||
|
|
||||||
|
final Set<V> set = setMap.get((K) "A");
|
||||||
|
assertTrue(set.add((V) "a1"));
|
||||||
|
assertTrue(set.add((V) "a2"));
|
||||||
|
assertFalse(set.add((V) "a1"));
|
||||||
|
assertEquals(2, setMap.size());
|
||||||
|
assertTrue(setMap.containsKey("A"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
@Test
|
||||||
|
public void testSetValuedMapEqualsHashCodeContract() {
|
||||||
|
final SetValuedMap map1 = makeObject();
|
||||||
|
final SetValuedMap map2 = makeObject();
|
||||||
|
|
||||||
|
map1.put("a", "a1");
|
||||||
|
map1.put("a", "a2");
|
||||||
|
map2.put("a", "a2");
|
||||||
|
map2.put("a", "a1");
|
||||||
|
assertEquals(map1, map2);
|
||||||
|
assertEquals(map1.hashCode(), map2.hashCode());
|
||||||
|
|
||||||
|
map2.put("a", "a2");
|
||||||
|
assertEquals(map1, map2);
|
||||||
|
assertEquals(map1.hashCode(), map2.hashCode());
|
||||||
|
|
||||||
|
map2.put("a", "a3");
|
||||||
|
assertNotSame(map1, map2);
|
||||||
|
assertNotSame(map1.hashCode(), map2.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testSetValuedMapRemove() {
|
||||||
|
final SetValuedMap<K, V> setMap = makeObject();
|
||||||
|
assertTrue(setMap.get((K) "whatever") instanceof Set);
|
||||||
|
|
||||||
|
final Set<V> set = setMap.get((K) "A");
|
||||||
|
assertTrue(set.add((V) "a1"));
|
||||||
|
assertTrue(set.add((V) "a2"));
|
||||||
|
assertFalse(set.add((V) "a1"));
|
||||||
|
assertEquals(2, setMap.size());
|
||||||
|
assertTrue(setMap.containsKey("A"));
|
||||||
|
|
||||||
|
assertTrue(set.remove("a1"));
|
||||||
|
assertTrue(set.remove("a2"));
|
||||||
|
assertFalse(set.remove("a1"));
|
||||||
|
|
||||||
|
assertEquals(0, setMap.size());
|
||||||
|
assertFalse(setMap.containsKey("A"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void testSetValuedMapRemoveViaIterator() {
|
||||||
|
final SetValuedMap<K, V> setMap = makeObject();
|
||||||
|
assertTrue(setMap.get((K) "whatever") instanceof Set);
|
||||||
|
|
||||||
|
final Set<V> set = setMap.get((K) "A");
|
||||||
|
set.add((V) "a1");
|
||||||
|
set.add((V) "a2");
|
||||||
|
set.add((V) "a1");
|
||||||
|
|
||||||
|
final Iterator<V> it = set.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
assertEquals(0, setMap.size());
|
||||||
|
assertFalse(setMap.containsKey("A"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void testCreate() throws Exception {
|
||||||
|
// writeExternalFormToDisk((java.io.Serializable) makeObject(),
|
||||||
|
// "src/test/resources/org/apache/commons/collections4/data/test/LinkedHashSetValuedLinkedHashMap.emptyCollection.version4.5.obj");
|
||||||
|
// writeExternalFormToDisk((java.io.Serializable) makeFullMap(),
|
||||||
|
// "src/test/resources/org/apache/commons/collections4/data/test/LinkedHashSetValuedLinkedHashMap.fullCollection.version4.5.obj");
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue