From 8e36168dc5f3a68917606a93fef5add281ac48c1 Mon Sep 17 00:00:00 2001 From: Evgeniy Kuvardin Date: Fri, 17 Jan 2025 14:38:40 +0300 Subject: [PATCH 1/6] COLLECTIONS-873. Add PatriciaTrieSet --- .../collections4/set/PatriciaTrieSet.java | 145 +++++++++++ .../commons/collections4/set/TrieSet.java | 26 ++ .../collections4/set/PatriciaTrieSetTest.java | 230 ++++++++++++++++++ 3 files changed, 401 insertions(+) create mode 100644 src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java create mode 100644 src/main/java/org/apache/commons/collections4/set/TrieSet.java create mode 100644 src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java diff --git a/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java new file mode 100644 index 0000000000..2f1d571c7e --- /dev/null +++ b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java @@ -0,0 +1,145 @@ +package org.apache.commons.collections4.set; + +import org.apache.commons.collections4.trie.PatriciaTrie; + +import java.io.IOException; +import java.util.AbstractSet; +import java.util.Comparator; +import java.util.Iterator; +import java.io.Serializable; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * Add {@code Set} to work with PatriciaTree with unique key ignore corresponding values + *

+ * This set exists to provide interface to work with Set + PatriciaTree + *

+ *

+ * One usage would be to ensure that no null entries are added to the set. + *

+ *
PatriciaTrieSet = new PatriciaTrieSet();
+ *

+ * This class is Serializable and Cloneable. + *

+ * + * @since 5.0 + */ +public class PatriciaTrieSet extends AbstractSet implements TrieSet, Serializable { + + private static final long serialVersionUID = -2365733183789787136L; + + // Stub for all values in PatriciaTrie + static final Object PRESENT = new Object(); + transient PatriciaTrie trie; + + public PatriciaTrieSet() { + trie = new PatriciaTrie<>(); + } + + @Override + public Iterator iterator() { + return trie.keySet().iterator(); + } + + @Override + public int size() { + return trie.size(); + } + + @Override + public boolean isEmpty() { + return trie.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return trie.containsKey(o); + } + + @Override + public boolean add(String e) { + return trie.put(e, PRESENT) == null; + } + + @Override + public boolean remove(Object o) { + return trie.remove(o) == PRESENT; + } + + @Override + public void clear() { + trie.clear(); + } + + /** + * 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(java.io.ObjectOutputStream out) + throws IOException { + out.defaultWriteObject(); + out.writeInt(trie.size()); + + for (String entry : this.trie.keySet()) { + out.writeObject(entry); + } + } + + /** + * Deserializes the set in using a custom routine. + * + * @param s the input stream + * @throws IOException if an error occurs while reading from the stream + * @throws ClassNotFoundException if an object read from the stream cannot be loaded + */ + @SuppressWarnings("unchecked") + private void readObject(java.io.ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.readFields(); + int size = s.readInt(); + this.trie = new PatriciaTrie<>(); + + for (int i = 0; i < size; i++) { + this.add((String) s.readObject()); + } + } + + @Override + public SortedSet prefixSet(String key) { + return new TreeSet<>(trie.prefixMap(key).keySet()); + } + + @Override + public Comparator comparator() { + return trie.comparator(); + } + + @Override + public SortedSet subSet(String fromElement, String toElement) { + return new TreeSet<>(trie.subMap(fromElement, toElement).keySet()); + } + + @Override + public SortedSet headSet(String toElement) { + return new TreeSet<>(trie.headMap(toElement).keySet()); + } + + @Override + public SortedSet tailSet(String fromElement) { + return new TreeSet<>(trie.tailMap(fromElement).keySet()); + } + + @Override + public String first() { + return trie.firstKey(); + } + + @Override + public String last() { + return trie.lastKey(); + } + +} \ No newline at end of file diff --git a/src/main/java/org/apache/commons/collections4/set/TrieSet.java b/src/main/java/org/apache/commons/collections4/set/TrieSet.java new file mode 100644 index 0000000000..fe0052a9a8 --- /dev/null +++ b/src/main/java/org/apache/commons/collections4/set/TrieSet.java @@ -0,0 +1,26 @@ +package org.apache.commons.collections4.set; + +import java.util.SortedSet; + +/** + * Defines the interface for a prefix set, an ordered tree data structure. For more information, see Tries. + * + * @param – the type of elements maintained by this set + */ +public interface TrieSet extends SortedSet { + + /** + * Returns a view of this {@link TrieSet} of all elements that are prefixed by the given key without duplicates + *

+ * In a {@link TrieSet} with fixed size keys, this is essentially a {@link #contains(Object)} operation. + *

+ *

+ * For example, if the {@link TrieSet} contains 'Anna', 'Anael', 'Analu', 'Andreas', 'Andrea', 'Andres', and 'Anatole', then a lookup of 'And' would return + * 'Andreas', 'Andrea', and 'Andres'. + *

+ * + * @param key the key used in the search + * @return a {@link SortedSet} view of this {@link TrieSet} with all elements whose key is prefixed by the search key + */ + SortedSet prefixSet(K key); +} \ No newline at end of file diff --git a/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java b/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java new file mode 100644 index 0000000000..a97a170206 --- /dev/null +++ b/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java @@ -0,0 +1,230 @@ +package org.apache.commons.collections4.set; + +import org.apache.commons.collections4.trie.analyzer.StringKeyAnalyzer; +import org.apache.commons.lang3.SerializationUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashSet; +import java.util.SortedSet; + +public class PatriciaTrieSetTest { + + PatriciaTrieSet patriciaTrieSet = new PatriciaTrieSet(); + + @BeforeEach + public void preInitTest() { + patriciaTrieSet.clear(); + } + + @Test + public void setShouldContainUniqueElements() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albe"); + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albe"); + + Assertions.assertEquals(2, patriciaTrieSet.size()); + } + + @Test + public void setShouldNotContainsNullKey() { + Assertions.assertThrows(NullPointerException.class, () -> patriciaTrieSet.add(null)); + } + + @Test + public void clearShouldClearAllElements() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albe"); + + patriciaTrieSet.clear(); + + Assertions.assertEquals(0, patriciaTrieSet.size()); + Assertions.assertTrue(patriciaTrieSet.isEmpty()); + } + + @Test + public void isEmptyShouldReturnFalseIfElementsExist() { + Assertions.assertTrue(patriciaTrieSet.isEmpty()); + patriciaTrieSet.add("Alberto"); + + Assertions.assertFalse(patriciaTrieSet.isEmpty()); + } + + @Test + public void iteratorShouldContainsAllElements() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albe"); + + HashSet set = new HashSet<>(2); + set.add("Alberto"); + set.add("Albe"); + + for (String value : patriciaTrieSet) { + Assertions.assertTrue(set.remove(value), "Value " + value + " not exists!"); + } + } + + @Test + public void containsShouldReturnCorrectValue() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albe"); + patriciaTrieSet.add("Al"); + patriciaTrieSet.add("A"); + + Assertions.assertTrue(patriciaTrieSet.contains("A")); + Assertions.assertTrue(patriciaTrieSet.contains("Al")); + Assertions.assertTrue(patriciaTrieSet.contains("Albe")); + Assertions.assertTrue(patriciaTrieSet.contains("Alberto")); + Assertions.assertFalse(patriciaTrieSet.contains("Albert")); + } + + @Test + public void addShouldReturnFalseIfValueExists() { + patriciaTrieSet.add("Alberto"); + + Assertions.assertFalse(patriciaTrieSet.add("Alberto")); + } + + @Test + public void addShouldReturnTrueIfValueNotExists() { + Assertions.assertTrue(patriciaTrieSet.add("Alberto")); + } + + @Test + public void removeShouldReturnTrueIfValueExists() { + patriciaTrieSet.add("Alberto"); + + Assertions.assertTrue(patriciaTrieSet.remove("Alberto")); + } + + @Test + public void removeShouldReturnFalseIfValueNotExist() { + Assertions.assertFalse(patriciaTrieSet.remove("Alberto")); + } + + @Test + public void serializeShouldSerializeAndDeserializedCorrectly() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albe"); + patriciaTrieSet.add("Al"); + patriciaTrieSet.add("A"); + + byte[] serializedBytes = SerializationUtils.serialize(patriciaTrieSet); + PatriciaTrieSet expected = SerializationUtils.deserialize(serializedBytes); + + Assertions.assertEquals(4, expected.size()); + Assertions.assertTrue(patriciaTrieSet.contains("A")); + Assertions.assertTrue(patriciaTrieSet.contains("Al")); + Assertions.assertTrue(patriciaTrieSet.contains("Albe")); + Assertions.assertTrue(patriciaTrieSet.contains("Alberto")); + } + + @Test + public void serializeShouldSerializeAndDeserializedCorrectlyEmptyObject() { + byte[] serializedBytes = SerializationUtils.serialize(patriciaTrieSet); + PatriciaTrieSet expected = SerializationUtils.deserialize(serializedBytes); + + Assertions.assertEquals(0, expected.size()); + } + + @Test + public void prefixSetShouldReturnCorrectObject() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Bbe"); + patriciaTrieSet.add("Bb"); + patriciaTrieSet.add("Al"); + patriciaTrieSet.add("A"); + + SortedSet set = patriciaTrieSet.prefixSet("Bb"); + Assertions.assertEquals(2, set.size()); + + Assertions.assertEquals("Bb", set.first()); + Assertions.assertEquals("Bbe", set.last()); + } + + @Test + public void subSetShouldReturnCorrectObject() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Bbe"); + patriciaTrieSet.add("Bb"); + patriciaTrieSet.add("Al"); + patriciaTrieSet.add("A"); + + SortedSet set = patriciaTrieSet.subSet("Al", "Bbe"); + Assertions.assertEquals(3, set.size()); + + String[] array = new String[3]; + set.toArray(array); + + Assertions.assertEquals("Al", array[0]); + Assertions.assertEquals("Alberto", array[1]); + Assertions.assertEquals("Bb", array[2]); + } + + @Test + public void headSetShouldReturnCorrectObject() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Bbe"); + patriciaTrieSet.add("Bb"); + patriciaTrieSet.add("Al"); + patriciaTrieSet.add("A"); + + SortedSet set = patriciaTrieSet.headSet("Bbe"); + Assertions.assertEquals(4, set.size()); + + String[] array = new String[4]; + set.toArray(array); + + Assertions.assertEquals("A", array[0]); + Assertions.assertEquals("Al", array[1]); + Assertions.assertEquals("Alberto", array[2]); + Assertions.assertEquals("Bb", array[3]); + } + + @Test + public void tailSetShouldReturnCorrectObject() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Bbe"); + patriciaTrieSet.add("Bb"); + patriciaTrieSet.add("Al"); + patriciaTrieSet.add("Z"); + + SortedSet set = patriciaTrieSet.tailSet("Bbe"); + Assertions.assertEquals(2, set.size()); + + String[] array = new String[2]; + set.toArray(array); + + Assertions.assertEquals("Bbe", array[0]); + Assertions.assertEquals("Z", array[1]); + } + + @Test + public void firstKeyShouldReturnCorrectObject() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Bbe"); + patriciaTrieSet.add("Bb"); + patriciaTrieSet.add("Al"); + patriciaTrieSet.add("Z"); + + Assertions.assertEquals("Al", patriciaTrieSet.first()); + } + + @Test + public void lastKeyShouldReturnCorrectObject() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Bbe"); + patriciaTrieSet.add("Bb"); + patriciaTrieSet.add("Al"); + patriciaTrieSet.add("Zz"); + + Assertions.assertEquals("Zz", patriciaTrieSet.last()); + } + + @Test + public void comparatorShouReturnSetComparator() { + Assertions.assertEquals(StringKeyAnalyzer.INSTANCE, patriciaTrieSet.comparator()); + } +} \ No newline at end of file From 79def318807081424cc60040fe52159bedab2082 Mon Sep 17 00:00:00 2001 From: Evgeniy Kuvardin Date: Fri, 17 Jan 2025 14:52:43 +0300 Subject: [PATCH 2/6] COLLECTIONS-873. Add check on class --- .../apache/commons/collections4/set/PatriciaTrieSet.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java index 2f1d571c7e..b0e99fc97a 100644 --- a/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java +++ b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java @@ -54,7 +54,10 @@ public boolean isEmpty() { @Override public boolean contains(Object o) { - return trie.containsKey(o); + if (o instanceof String) + return trie.containsKey(o); + + return false; } @Override @@ -95,7 +98,6 @@ private void writeObject(java.io.ObjectOutputStream out) * @throws IOException if an error occurs while reading from the stream * @throws ClassNotFoundException if an object read from the stream cannot be loaded */ - @SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { s.readFields(); From 9a4c3cb0df8646e4ce727836b8be9ced3aa35466 Mon Sep 17 00:00:00 2001 From: Evgeniy Kuvardin Date: Fri, 17 Jan 2025 19:47:49 +0300 Subject: [PATCH 3/6] COLLECTIONS-873. Check checkstyle warning. Add license and tests on mixed language --- .../collections4/set/PatriciaTrieSet.java | 28 +++++-- .../commons/collections4/set/TrieSet.java | 18 ++++- .../collections4/set/PatriciaTrieSetTest.java | 76 ++++++++++++++++++- 3 files changed, 111 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java index b0e99fc97a..c91772ed53 100644 --- a/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java +++ b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java @@ -1,15 +1,31 @@ +/* + * 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.set; -import org.apache.commons.collections4.trie.PatriciaTrie; - import java.io.IOException; +import java.io.Serializable; import java.util.AbstractSet; import java.util.Comparator; import java.util.Iterator; -import java.io.Serializable; import java.util.SortedSet; import java.util.TreeSet; +import org.apache.commons.collections4.trie.PatriciaTrie; + /** * Add {@code Set} to work with PatriciaTree with unique key ignore corresponding values *

@@ -23,7 +39,6 @@ * This class is Serializable and Cloneable. *

* - * @since 5.0 */ public class PatriciaTrieSet extends AbstractSet implements TrieSet, Serializable { @@ -54,8 +69,9 @@ public boolean isEmpty() { @Override public boolean contains(Object o) { - if (o instanceof String) + if (o instanceof String) { return trie.containsKey(o); + } return false; } @@ -144,4 +160,4 @@ public String last() { return trie.lastKey(); } -} \ No newline at end of file +} diff --git a/src/main/java/org/apache/commons/collections4/set/TrieSet.java b/src/main/java/org/apache/commons/collections4/set/TrieSet.java index fe0052a9a8..6c27c709bb 100644 --- a/src/main/java/org/apache/commons/collections4/set/TrieSet.java +++ b/src/main/java/org/apache/commons/collections4/set/TrieSet.java @@ -1,3 +1,19 @@ +/* + * 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.set; import java.util.SortedSet; @@ -23,4 +39,4 @@ public interface TrieSet extends SortedSet { * @return a {@link SortedSet} view of this {@link TrieSet} with all elements whose key is prefixed by the search key */ SortedSet prefixSet(K key); -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java b/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java index a97a170206..dba1be21eb 100644 --- a/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java +++ b/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java @@ -1,14 +1,35 @@ +/* + * 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.set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashSet; +import java.util.SortedSet; + import org.apache.commons.collections4.trie.analyzer.StringKeyAnalyzer; import org.apache.commons.lang3.SerializationUtils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.HashSet; -import java.util.SortedSet; - public class PatriciaTrieSetTest { PatriciaTrieSet patriciaTrieSet = new PatriciaTrieSet(); @@ -227,4 +248,51 @@ public void lastKeyShouldReturnCorrectObject() { public void comparatorShouReturnSetComparator() { Assertions.assertEquals(StringKeyAnalyzer.INSTANCE, patriciaTrieSet.comparator()); } -} \ No newline at end of file + + @Test + public void prefixMapShouldCorrectlyWorkWihChineseCharacter() { + // COLLECTIONS-525 + final PatriciaTrieSet set = new PatriciaTrieSet(); + set.add("点评"); + set.add("书评"); + assertTrue(set.prefixSet("点").contains("点评")); + assertEquals("点评", set.prefixSet("点").first()); + assertFalse(set.prefixSet("点").isEmpty()); + assertEquals(1, set.prefixSet("点").size()); + assertEquals(1, set.prefixSet("点评").size()); + + set.clear(); + set.add("点评"); + set.add("点版"); + assertEquals(2, set.prefixSet("点").size()); + assertEquals(2, set.prefixSet("点").size()); + } + + @Test + public void setShouldCorrectlyWorkWithMixedCharacters() { + final PatriciaTrieSet set = new PatriciaTrieSet(); + set.add("书评"); + set.add("书点"); + set.add("Al"); + set.add("Alberto"); + set.add("Йод"); + set.add("Йододефицит"); + + + SortedSet subset = set.prefixSet("Al"); + assertEquals(2, subset.size()); + assertEquals("Al", subset.first()); + assertEquals("Alberto", subset.last()); + + subset = set.prefixSet("Йод"); + assertEquals(2, subset.size()); + assertEquals("Йод", subset.first()); + assertEquals("Йододефицит", subset.last()); + + subset = set.prefixSet("书"); + + assertEquals(2, subset.size()); + assertEquals("书点", subset.first()); + assertEquals("书评", subset.last()); + } +} From 4b308e0bd1f8be7ae0595d6660746fc71a87f304 Mon Sep 17 00:00:00 2001 From: Evgeniy Kuvardin Date: Sun, 19 Jan 2025 23:03:34 +0300 Subject: [PATCH 4/6] COLLECTIONS-873. Remove TreeSet and make SortedSet through SortedMap delegation --- .../collections4/set/PatriciaTrieSet.java | 88 +++++++++++++++++-- .../collections4/set/PatriciaTrieSetTest.java | 2 + 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java index c91772ed53..c6b633924f 100644 --- a/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java +++ b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java @@ -21,8 +21,8 @@ import java.util.AbstractSet; import java.util.Comparator; import java.util.Iterator; +import java.util.SortedMap; import java.util.SortedSet; -import java.util.TreeSet; import org.apache.commons.collections4.trie.PatriciaTrie; @@ -38,7 +38,6 @@ *

* This class is Serializable and Cloneable. *

- * */ public class PatriciaTrieSet extends AbstractSet implements TrieSet, Serializable { @@ -127,7 +126,7 @@ private void readObject(java.io.ObjectInputStream s) @Override public SortedSet prefixSet(String key) { - return new TreeSet<>(trie.prefixMap(key).keySet()); + return new RangePatriciaTrieSortedSet(trie.prefixMap(key)); } @Override @@ -137,17 +136,17 @@ public Comparator comparator() { @Override public SortedSet subSet(String fromElement, String toElement) { - return new TreeSet<>(trie.subMap(fromElement, toElement).keySet()); + return new RangePatriciaTrieSortedSet(trie.subMap(fromElement, toElement)); } @Override public SortedSet headSet(String toElement) { - return new TreeSet<>(trie.headMap(toElement).keySet()); + return new RangePatriciaTrieSortedSet(trie.headMap(toElement)); } @Override public SortedSet tailSet(String fromElement) { - return new TreeSet<>(trie.tailMap(fromElement).keySet()); + return new RangePatriciaTrieSortedSet(trie.tailMap(fromElement)); } @Override @@ -160,4 +159,81 @@ public String last() { return trie.lastKey(); } + static class RangePatriciaTrieSortedSet extends AbstractSet implements SortedSet { + + protected SortedMap delegate; + + RangePatriciaTrieSortedSet(SortedMap del) { + delegate = del; + } + + @Override + public Iterator iterator() { + return delegate.keySet().iterator(); + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean contains(Object key) { + if (key instanceof String) { + return delegate.containsKey(key); + } + + return false; + } + + @Override + public Comparator comparator() { + return delegate.comparator(); + } + + @Override + public SortedSet subSet(String fromElement, String toElement) { + return new RangePatriciaTrieSortedSet(delegate.subMap(fromElement, toElement)); + } + + @Override + public SortedSet headSet(String toElement) { + return new RangePatriciaTrieSortedSet(delegate.headMap(toElement)); + } + + @Override + public SortedSet tailSet(String fromElement) { + return new RangePatriciaTrieSortedSet(delegate.tailMap(fromElement)); + } + + @Override + public String first() { + return delegate.firstKey(); + } + + @Override + public String last() { + return delegate.lastKey(); + } + + @Override + public boolean add(String value) { + return delegate.put(value, PRESENT) != null; + } + + @Override + public boolean remove(Object o) { + return delegate.remove(o) == PRESENT; + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public void clear() { + delegate.clear(); + } + } } diff --git a/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java b/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java index dba1be21eb..f54b4f3b29 100644 --- a/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java +++ b/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java @@ -47,6 +47,8 @@ public void setShouldContainUniqueElements() { patriciaTrieSet.add("Albe"); Assertions.assertEquals(2, patriciaTrieSet.size()); + Assertions.assertTrue(patriciaTrieSet.contains("Alberto")); + Assertions.assertTrue(patriciaTrieSet.contains("Albe")); } @Test From 0380f3e03d03019b40f2be0d85baaed7f416f099 Mon Sep 17 00:00:00 2001 From: Evgeniy Kuvardin Date: Sat, 25 Jan 2025 19:53:02 +0300 Subject: [PATCH 5/6] COLLECTIONS-873. Add split iterator --- .../collections4/set/PatriciaTrieSet.java | 6 + .../collections4/set/PatriciaTrieSetTest.java | 408 +++++++++++++++++- 2 files changed, 391 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java index c6b633924f..f97d6e054f 100644 --- a/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java +++ b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java @@ -23,6 +23,7 @@ import java.util.Iterator; import java.util.SortedMap; import java.util.SortedSet; +import java.util.Spliterator; import org.apache.commons.collections4.trie.PatriciaTrie; @@ -172,6 +173,11 @@ public Iterator iterator() { return delegate.keySet().iterator(); } + @Override + public Spliterator spliterator() { + return delegate.keySet().spliterator(); + } + @Override public int size() { return delegate.size(); diff --git a/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java b/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java index f54b4f3b29..c67322df41 100644 --- a/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java +++ b/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java @@ -22,7 +22,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.HashSet; +import java.util.NoSuchElementException; import java.util.SortedSet; +import java.util.Spliterator; import org.apache.commons.collections4.trie.analyzer.StringKeyAnalyzer; import org.apache.commons.lang3.SerializationUtils; @@ -254,47 +256,407 @@ public void comparatorShouReturnSetComparator() { @Test public void prefixMapShouldCorrectlyWorkWihChineseCharacter() { // COLLECTIONS-525 - final PatriciaTrieSet set = new PatriciaTrieSet(); - set.add("点评"); - set.add("书评"); - assertTrue(set.prefixSet("点").contains("点评")); - assertEquals("点评", set.prefixSet("点").first()); - assertFalse(set.prefixSet("点").isEmpty()); - assertEquals(1, set.prefixSet("点").size()); - assertEquals(1, set.prefixSet("点评").size()); + patriciaTrieSet.add("点评"); + patriciaTrieSet.add("书评"); + assertTrue(patriciaTrieSet.prefixSet("点").contains("点评")); + assertEquals("点评", patriciaTrieSet.prefixSet("点").first()); + assertFalse(patriciaTrieSet.prefixSet("点").isEmpty()); + assertEquals(1, patriciaTrieSet.prefixSet("点").size()); + assertEquals(1, patriciaTrieSet.prefixSet("点评").size()); - set.clear(); - set.add("点评"); - set.add("点版"); - assertEquals(2, set.prefixSet("点").size()); - assertEquals(2, set.prefixSet("点").size()); + patriciaTrieSet.clear(); + patriciaTrieSet.add("点评"); + patriciaTrieSet.add("点版"); + assertEquals(2, patriciaTrieSet.prefixSet("点").size()); + assertEquals(2, patriciaTrieSet.prefixSet("点").size()); } @Test public void setShouldCorrectlyWorkWithMixedCharacters() { - final PatriciaTrieSet set = new PatriciaTrieSet(); - set.add("书评"); - set.add("书点"); - set.add("Al"); - set.add("Alberto"); - set.add("Йод"); - set.add("Йододефицит"); + patriciaTrieSet.add("书评"); + patriciaTrieSet.add("书点"); + patriciaTrieSet.add("Al"); + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Йод"); + patriciaTrieSet.add("Йододефицит"); - SortedSet subset = set.prefixSet("Al"); + SortedSet subset = patriciaTrieSet.prefixSet("Al"); assertEquals(2, subset.size()); assertEquals("Al", subset.first()); assertEquals("Alberto", subset.last()); - subset = set.prefixSet("Йод"); + subset = patriciaTrieSet.prefixSet("Йод"); assertEquals(2, subset.size()); assertEquals("Йод", subset.first()); assertEquals("Йододефицит", subset.last()); - subset = set.prefixSet("书"); + subset = patriciaTrieSet.prefixSet("书"); assertEquals(2, subset.size()); assertEquals("书点", subset.first()); assertEquals("书评", subset.last()); } + + @Test + public void containsShouldReturnFalse() { + patriciaTrieSet.add("Al"); + patriciaTrieSet.add("Alberto"); + + assertFalse(patriciaTrieSet.contains("w")); + assertFalse(patriciaTrieSet.contains(new Object())); + } + + @Test + public void rangePatriciaTrieSortedSetIteratorShouldReturnCorrectOrder() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + + Assertions.assertNotNull(subSet); + + String[] actual = new String[3]; + int idx = 0; + + for (String s : subSet) { + actual[idx] = s; + idx++; + } + + Assertions.assertEquals("Al", actual[0]); + Assertions.assertEquals("Albert", actual[1]); + Assertions.assertEquals("Alberto", actual[2]); + } + + @Test + public void rangePatriciaTrieSortedSetSplitIteratorShouldReturnIteratorOverMap() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + + Spliterator spliterator = subSet.spliterator(); + Assertions.assertEquals(Spliterator.DISTINCT | Spliterator.SIZED | Spliterator.SUBSIZED, spliterator.characteristics()); + Assertions.assertEquals(3, spliterator.getExactSizeIfKnown()); + } + + @Test + public void rangePatriciaTrieSortedSetSizeShouldReturnCorrectSize() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + + SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + Assertions.assertEquals(3, subSet.size()); + } + + @Test + public void rangePatriciaTrieSortedSetContainsShouldReturnTrue() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + + SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + Assertions.assertTrue(subSet.contains("Albert")); + } + + @Test + public void rangePatriciaTrieSortedSetContainsShouldReturnFalse() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + + SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + Assertions.assertFalse(subSet.contains("Wirz")); + Assertions.assertFalse(subSet.contains(new Object())); + } + + @Test + public void rangePatriciaTrieSortedSetComparatorShouldCorrectValue() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + + SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + Assertions.assertEquals(StringKeyAnalyzer.INSTANCE, subSet.comparator()); + } + + @Test + public void rangePatriciaTrieSortedSetSubSetShouldReturnCorrectSubSet() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.subSet("Albert", "Wirz"); + + Assertions.assertNotNull(subSet); + + String[] actual = new String[3]; + int idx = 0; + + for (String s : subSet) { + actual[idx] = s; + idx++; + } + + Assertions.assertEquals("Albert", actual[0]); + Assertions.assertEquals("Alberto", actual[1]); + Assertions.assertEquals("W", actual[2]); + } + + @Test + public void rangePatriciaTrieSortedSetSubSetShouldReturnCorrectSubSetTwice() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.subSet("Albert", "Wirz"); + subSet = subSet.subSet("Albert", "W"); + Assertions.assertNotNull(subSet); + + Assertions.assertNotNull(subSet); + + String[] actual = new String[2]; + int idx = 0; + + for (String s : subSet) { + actual[idx] = s; + idx++; + } + + Assertions.assertEquals("Albert", actual[0]); + Assertions.assertEquals("Alberto", actual[1]); + } + + @Test + public void rangePatriciaTrieSortedSetHeadSetShouldReturnCorrectHeadSet() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Wl"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.headSet("Wl"); + Assertions.assertNotNull(subSet); + + String[] actual = new String[5]; + int idx = 0; + + for (String s : subSet) { + actual[idx] = s; + idx++; + } + + Assertions.assertEquals("Al", actual[0]); + Assertions.assertEquals("Albert", actual[1]); + Assertions.assertEquals("Alberto", actual[2]); + Assertions.assertEquals("W", actual[3]); + Assertions.assertEquals("Wirz", actual[4]); + } + + @Test + public void rangePatriciaTrieSortedSetHeadSetShouldReturnCorrectHeadSetTwice() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Wl"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.headSet("Wl"); + Assertions.assertNotNull(subSet); + subSet = subSet.headSet("Alberto"); + Assertions.assertNotNull(subSet); + + String[] actual = new String[2]; + int idx = 0; + + for (String s : subSet) { + actual[idx] = s; + idx++; + } + + Assertions.assertEquals("Al", actual[0]); + Assertions.assertEquals("Albert", actual[1]); + } + + @Test + public void rangePatriciaTrieSortedSetTailSetShouldReturnCorrectTailSet() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Wl"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.tailSet("Alberto"); + Assertions.assertNotNull(subSet); + + String[] actual = new String[4]; + int idx = 0; + + for (String s : subSet) { + actual[idx] = s; + idx++; + } + + Assertions.assertEquals("Alberto", actual[0]); + Assertions.assertEquals("W", actual[1]); + Assertions.assertEquals("Wirz", actual[2]); + Assertions.assertEquals("Wl", actual[3]); + } + + @Test + public void rangePatriciaTrieSortedSetTailSetShouldReturnCorrectTailSetTwice() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Wl"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.tailSet("Alberto"); + Assertions.assertNotNull(subSet); + subSet = subSet.tailSet("Wirz"); + + String[] actual = new String[2]; + int idx = 0; + + for (String s : subSet) { + actual[idx] = s; + idx++; + } + + Assertions.assertEquals("Wirz", actual[0]); + Assertions.assertEquals("Wl", actual[1]); + } + + @Test + public void rangePatriciaTrieSortedSetFirstShouldReturnCorrectResult() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Wl"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.tailSet("Alberto"); + + Assertions.assertEquals("Alberto", subSet.first()); + + subSet = patriciaTrieSet.tailSet("Wir"); + + Assertions.assertEquals("Wirz", subSet.first()); + } + + @Test + public void rangePatriciaTrieSortedSetLastShouldReturnCorrectResult() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Wl"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.headSet("Alberto"); + Assertions.assertEquals("Albert", subSet.last()); + + subSet = patriciaTrieSet.headSet("Al"); + Assertions.assertThrows(NoSuchElementException.class, subSet::last); + } + + @Test + public void rangePatriciaTrieSortedSetAddShouldReturnCorrectResult() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Wl"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.headSet("Alberto"); + subSet.add("Albert"); + + Assertions.assertEquals(2, subSet.size()); + Assertions.assertEquals(6, patriciaTrieSet.size()); + + subSet.add("Alber"); + + Assertions.assertEquals(3, subSet.size()); + Assertions.assertEquals(7, patriciaTrieSet.size()); + } + + @Test + public void rangePatriciaTrieSortedSetRemoveShouldReturnCorrectResult() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Wl"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.headSet("Alberto"); + subSet.remove("Al"); + + Assertions.assertEquals(1, subSet.size()); + Assertions.assertEquals(5, patriciaTrieSet.size()); + + subSet.remove("A"); + + Assertions.assertEquals(1, subSet.size()); + Assertions.assertEquals(5, patriciaTrieSet.size()); + + } + + @Test + public void rangePatriciaTrieSortedSetIsEmptyShouldReturnCorrectResult() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Wl"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.headSet("Al"); + assertTrue(subSet.isEmpty()); + + subSet = patriciaTrieSet.headSet("Albert"); + assertFalse(subSet.isEmpty()); + } + + @Test + public void rangePatriciaTrieSortedSetClearShouldClearElements() { + patriciaTrieSet.add("Alberto"); + patriciaTrieSet.add("Albert"); + patriciaTrieSet.add("Wirz"); + patriciaTrieSet.add("W"); + patriciaTrieSet.add("Wl"); + patriciaTrieSet.add("Al"); + + SortedSet subSet = patriciaTrieSet.headSet("Al"); + subSet.clear(); + + Assertions.assertEquals(0, subSet.size()); + Assertions.assertEquals(6, patriciaTrieSet.size()); + + subSet = patriciaTrieSet.headSet("Alberto"); + subSet.clear(); + + Assertions.assertEquals(0, subSet.size()); + Assertions.assertEquals(4, patriciaTrieSet.size()); + } } From eaf295fcb2d0b32614d32fa7041acfe834d1e4d6 Mon Sep 17 00:00:00 2001 From: Evgeniy Kuvardin Date: Mon, 7 Apr 2025 12:37:14 +0300 Subject: [PATCH 6/6] COLLECTIONS-873. Fix new checkstyle warning after merge with master --- .../collections4/set/PatriciaTrieSet.java | 5 +- .../collections4/set/PatriciaTrieSetTest.java | 62 +++++++++---------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java index f97d6e054f..7b70b0d42d 100644 --- a/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java +++ b/src/main/java/org/apache/commons/collections4/set/PatriciaTrieSet.java @@ -48,6 +48,9 @@ public class PatriciaTrieSet extends AbstractSet implements TrieSet trie; + /** + * Create new Patricia Set with PatriciaTrie under the hood using StringKeyAnalyzer + */ public PatriciaTrieSet() { trie = new PatriciaTrie<>(); } @@ -117,7 +120,7 @@ private void writeObject(java.io.ObjectOutputStream out) private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { s.readFields(); - int size = s.readInt(); + final int size = s.readInt(); this.trie = new PatriciaTrie<>(); for (int i = 0; i < size; i++) { diff --git a/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java b/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java index c67322df41..7adacc6fd8 100644 --- a/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java +++ b/src/test/java/org/apache/commons/collections4/set/PatriciaTrieSetTest.java @@ -82,7 +82,7 @@ public void iteratorShouldContainsAllElements() { patriciaTrieSet.add("Alberto"); patriciaTrieSet.add("Albe"); - HashSet set = new HashSet<>(2); + final HashSet set = new HashSet<>(2); set.add("Alberto"); set.add("Albe"); @@ -136,8 +136,8 @@ public void serializeShouldSerializeAndDeserializedCorrectly() { patriciaTrieSet.add("Al"); patriciaTrieSet.add("A"); - byte[] serializedBytes = SerializationUtils.serialize(patriciaTrieSet); - PatriciaTrieSet expected = SerializationUtils.deserialize(serializedBytes); + final byte[] serializedBytes = SerializationUtils.serialize(patriciaTrieSet); + final PatriciaTrieSet expected = SerializationUtils.deserialize(serializedBytes); Assertions.assertEquals(4, expected.size()); Assertions.assertTrue(patriciaTrieSet.contains("A")); @@ -148,8 +148,8 @@ public void serializeShouldSerializeAndDeserializedCorrectly() { @Test public void serializeShouldSerializeAndDeserializedCorrectlyEmptyObject() { - byte[] serializedBytes = SerializationUtils.serialize(patriciaTrieSet); - PatriciaTrieSet expected = SerializationUtils.deserialize(serializedBytes); + final byte[] serializedBytes = SerializationUtils.serialize(patriciaTrieSet); + final PatriciaTrieSet expected = SerializationUtils.deserialize(serializedBytes); Assertions.assertEquals(0, expected.size()); } @@ -162,7 +162,7 @@ public void prefixSetShouldReturnCorrectObject() { patriciaTrieSet.add("Al"); patriciaTrieSet.add("A"); - SortedSet set = patriciaTrieSet.prefixSet("Bb"); + final SortedSet set = patriciaTrieSet.prefixSet("Bb"); Assertions.assertEquals(2, set.size()); Assertions.assertEquals("Bb", set.first()); @@ -177,10 +177,10 @@ public void subSetShouldReturnCorrectObject() { patriciaTrieSet.add("Al"); patriciaTrieSet.add("A"); - SortedSet set = patriciaTrieSet.subSet("Al", "Bbe"); + final SortedSet set = patriciaTrieSet.subSet("Al", "Bbe"); Assertions.assertEquals(3, set.size()); - String[] array = new String[3]; + final String[] array = new String[3]; set.toArray(array); Assertions.assertEquals("Al", array[0]); @@ -196,10 +196,10 @@ public void headSetShouldReturnCorrectObject() { patriciaTrieSet.add("Al"); patriciaTrieSet.add("A"); - SortedSet set = patriciaTrieSet.headSet("Bbe"); + final SortedSet set = patriciaTrieSet.headSet("Bbe"); Assertions.assertEquals(4, set.size()); - String[] array = new String[4]; + final String[] array = new String[4]; set.toArray(array); Assertions.assertEquals("A", array[0]); @@ -216,10 +216,10 @@ public void tailSetShouldReturnCorrectObject() { patriciaTrieSet.add("Al"); patriciaTrieSet.add("Z"); - SortedSet set = patriciaTrieSet.tailSet("Bbe"); + final SortedSet set = patriciaTrieSet.tailSet("Bbe"); Assertions.assertEquals(2, set.size()); - String[] array = new String[2]; + final String[] array = new String[2]; set.toArray(array); Assertions.assertEquals("Bbe", array[0]); @@ -314,11 +314,11 @@ public void rangePatriciaTrieSortedSetIteratorShouldReturnCorrectOrder() { patriciaTrieSet.add("Wirz"); patriciaTrieSet.add("Al"); - SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + final SortedSet subSet = patriciaTrieSet.headSet("Wirz"); Assertions.assertNotNull(subSet); - String[] actual = new String[3]; + final String[] actual = new String[3]; int idx = 0; for (String s : subSet) { @@ -338,9 +338,9 @@ public void rangePatriciaTrieSortedSetSplitIteratorShouldReturnIteratorOverMap() patriciaTrieSet.add("Wirz"); patriciaTrieSet.add("Al"); - SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + final SortedSet subSet = patriciaTrieSet.headSet("Wirz"); - Spliterator spliterator = subSet.spliterator(); + final Spliterator spliterator = subSet.spliterator(); Assertions.assertEquals(Spliterator.DISTINCT | Spliterator.SIZED | Spliterator.SUBSIZED, spliterator.characteristics()); Assertions.assertEquals(3, spliterator.getExactSizeIfKnown()); } @@ -352,7 +352,7 @@ public void rangePatriciaTrieSortedSetSizeShouldReturnCorrectSize() { patriciaTrieSet.add("Wirz"); patriciaTrieSet.add("W"); - SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + final SortedSet subSet = patriciaTrieSet.headSet("Wirz"); Assertions.assertEquals(3, subSet.size()); } @@ -363,7 +363,7 @@ public void rangePatriciaTrieSortedSetContainsShouldReturnTrue() { patriciaTrieSet.add("Wirz"); patriciaTrieSet.add("W"); - SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + final SortedSet subSet = patriciaTrieSet.headSet("Wirz"); Assertions.assertTrue(subSet.contains("Albert")); } @@ -374,7 +374,7 @@ public void rangePatriciaTrieSortedSetContainsShouldReturnFalse() { patriciaTrieSet.add("Wirz"); patriciaTrieSet.add("W"); - SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + final SortedSet subSet = patriciaTrieSet.headSet("Wirz"); Assertions.assertFalse(subSet.contains("Wirz")); Assertions.assertFalse(subSet.contains(new Object())); } @@ -386,7 +386,7 @@ public void rangePatriciaTrieSortedSetComparatorShouldCorrectValue() { patriciaTrieSet.add("Wirz"); patriciaTrieSet.add("W"); - SortedSet subSet = patriciaTrieSet.headSet("Wirz"); + final SortedSet subSet = patriciaTrieSet.headSet("Wirz"); Assertions.assertEquals(StringKeyAnalyzer.INSTANCE, subSet.comparator()); } @@ -398,11 +398,11 @@ public void rangePatriciaTrieSortedSetSubSetShouldReturnCorrectSubSet() { patriciaTrieSet.add("W"); patriciaTrieSet.add("Al"); - SortedSet subSet = patriciaTrieSet.subSet("Albert", "Wirz"); + final SortedSet subSet = patriciaTrieSet.subSet("Albert", "Wirz"); Assertions.assertNotNull(subSet); - String[] actual = new String[3]; + final String[] actual = new String[3]; int idx = 0; for (String s : subSet) { @@ -429,7 +429,7 @@ public void rangePatriciaTrieSortedSetSubSetShouldReturnCorrectSubSetTwice() { Assertions.assertNotNull(subSet); - String[] actual = new String[2]; + final String[] actual = new String[2]; int idx = 0; for (String s : subSet) { @@ -450,10 +450,10 @@ public void rangePatriciaTrieSortedSetHeadSetShouldReturnCorrectHeadSet() { patriciaTrieSet.add("Wl"); patriciaTrieSet.add("Al"); - SortedSet subSet = patriciaTrieSet.headSet("Wl"); + final SortedSet subSet = patriciaTrieSet.headSet("Wl"); Assertions.assertNotNull(subSet); - String[] actual = new String[5]; + final String[] actual = new String[5]; int idx = 0; for (String s : subSet) { @@ -482,7 +482,7 @@ public void rangePatriciaTrieSortedSetHeadSetShouldReturnCorrectHeadSetTwice() { subSet = subSet.headSet("Alberto"); Assertions.assertNotNull(subSet); - String[] actual = new String[2]; + final String[] actual = new String[2]; int idx = 0; for (String s : subSet) { @@ -503,10 +503,10 @@ public void rangePatriciaTrieSortedSetTailSetShouldReturnCorrectTailSet() { patriciaTrieSet.add("Wl"); patriciaTrieSet.add("Al"); - SortedSet subSet = patriciaTrieSet.tailSet("Alberto"); + final SortedSet subSet = patriciaTrieSet.tailSet("Alberto"); Assertions.assertNotNull(subSet); - String[] actual = new String[4]; + final String[] actual = new String[4]; int idx = 0; for (String s : subSet) { @@ -533,7 +533,7 @@ public void rangePatriciaTrieSortedSetTailSetShouldReturnCorrectTailSetTwice() { Assertions.assertNotNull(subSet); subSet = subSet.tailSet("Wirz"); - String[] actual = new String[2]; + final String[] actual = new String[2]; int idx = 0; for (String s : subSet) { @@ -588,7 +588,7 @@ public void rangePatriciaTrieSortedSetAddShouldReturnCorrectResult() { patriciaTrieSet.add("Wl"); patriciaTrieSet.add("Al"); - SortedSet subSet = patriciaTrieSet.headSet("Alberto"); + final SortedSet subSet = patriciaTrieSet.headSet("Alberto"); subSet.add("Albert"); Assertions.assertEquals(2, subSet.size()); @@ -609,7 +609,7 @@ public void rangePatriciaTrieSortedSetRemoveShouldReturnCorrectResult() { patriciaTrieSet.add("Wl"); patriciaTrieSet.add("Al"); - SortedSet subSet = patriciaTrieSet.headSet("Alberto"); + final SortedSet subSet = patriciaTrieSet.headSet("Alberto"); subSet.remove("Al"); Assertions.assertEquals(1, subSet.size());