diff --git a/src/main/java/org/apache/commons/collections4/properties/OrderedProperties.java b/src/main/java/org/apache/commons/collections4/properties/OrderedProperties.java index 34e21ab913..4cf0b9c6c7 100644 --- a/src/main/java/org/apache/commons/collections4/properties/OrderedProperties.java +++ b/src/main/java/org/apache/commons/collections4/properties/OrderedProperties.java @@ -16,14 +16,18 @@ */ package org.apache.commons.collections4.properties; +import java.util.AbstractMap.SimpleEntry; import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.Map; +import java.util.Objects; import java.util.Properties; import java.util.Set; +import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; +import java.util.stream.Collectors; /** * A drop-in replacement for {@link Properties} for ordered keys. @@ -50,8 +54,8 @@ public synchronized void clear() { } @Override - public synchronized Object compute(Object key, BiFunction remappingFunction) { - Object compute = super.compute(key, remappingFunction); + public synchronized Object compute(final Object key, final BiFunction remappingFunction) { + final Object compute = super.compute(key, remappingFunction); if (compute != null) { orderedKeys.add(key); } @@ -59,14 +63,25 @@ public synchronized Object compute(Object key, BiFunction mappingFunction) { - Object computeIfAbsent = super.computeIfAbsent(key, mappingFunction); + public synchronized Object computeIfAbsent(final Object key, final Function mappingFunction) { + final Object computeIfAbsent = super.computeIfAbsent(key, mappingFunction); if (computeIfAbsent != null) { orderedKeys.add(key); } return computeIfAbsent; } + @Override + public Set> entrySet() { + return orderedKeys.stream().map(k -> new SimpleEntry<>(k, get(k))).collect(Collectors.toCollection(LinkedHashSet::new)); + } + + @Override + public synchronized void forEach(final BiConsumer action) { + Objects.requireNonNull(action); + orderedKeys.forEach(k -> action.accept(k, get(k))); + } + @Override public synchronized Enumeration keys() { return Collections.enumeration(orderedKeys); @@ -91,7 +106,7 @@ public Enumeration propertyNames() { @Override public synchronized Object put(final Object key, final Object value) { - Object put = super.put(key, value); + final Object put = super.put(key, value); if (put == null) { orderedKeys.add(key); } @@ -106,7 +121,7 @@ public synchronized void putAll(final Map t) @Override public synchronized Object putIfAbsent(final Object key, final Object value) { - Object putIfAbsent = super.putIfAbsent(key, value); + final Object putIfAbsent = super.putIfAbsent(key, value); if (putIfAbsent == null) { orderedKeys.add(key); } @@ -115,7 +130,7 @@ public synchronized Object putIfAbsent(final Object key, final Object value) { @Override public synchronized Object remove(final Object key) { - Object remove = super.remove(key); + final Object remove = super.remove(key); if (remove != null) { orderedKeys.remove(key); } @@ -124,7 +139,7 @@ public synchronized Object remove(final Object key) { @Override public synchronized boolean remove(final Object key, final Object value) { - boolean remove = super.remove(key, value); + final boolean remove = super.remove(key, value); if (remove) { orderedKeys.remove(key); } diff --git a/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesTest.java b/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesTest.java index 0974a617d4..813e6a4e1f 100644 --- a/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesTest.java +++ b/src/test/java/org/apache/commons/collections4/properties/OrderedPropertiesTest.java @@ -26,6 +26,7 @@ import java.util.Enumeration; import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.Test; @@ -46,6 +47,12 @@ private void assertAscendingOrder(final OrderedProperties orderedProperties) { for (int i = first; i <= last; i++) { assertEquals("key" + i, iterSet.next()); } + final Iterator> iterEntrySet = orderedProperties.entrySet().iterator(); + for (int i = first; i <= last; i++) { + final Entry next = iterEntrySet.next(); + assertEquals("key" + i, next.getKey()); + assertEquals("value" + i, next.getValue()); + } final Enumeration propertyNames = orderedProperties.propertyNames(); for (int i = first; i <= last; i++) { assertEquals("key" + i, propertyNames.nextElement()); @@ -63,6 +70,12 @@ private OrderedProperties assertDescendingOrder(final OrderedProperties orderedP for (int i = first; i <= last; i--) { assertEquals("key" + i, iterSet.next()); } + final Iterator> iterEntrySet = orderedProperties.entrySet().iterator(); + for (int i = first; i <= last; i--) { + final Entry next = iterEntrySet.next(); + assertEquals("key" + i, next.getKey()); + assertEquals("value" + i, next.getValue()); + } final Enumeration propertyNames = orderedProperties.propertyNames(); for (int i = first; i <= last; i--) { assertEquals("key" + i, propertyNames.nextElement()); @@ -121,31 +134,51 @@ public void testComputeIfAbsent() { @Test public void testEntrySet() { final OrderedProperties orderedProperties = new OrderedProperties(); - for (char ch = 'Z'; ch >= 'A'; ch--) { + final char first = 'Z'; + final char last = 'A'; + for (char ch = first; ch >= last; ch--) { orderedProperties.put(String.valueOf(ch), "Value" + ch); } final Iterator> entries = orderedProperties.entrySet().iterator(); - for (char ch = 'Z'; ch <= 'A'; ch++) { + for (char ch = first; ch <= last; ch++) { final Map.Entry entry = entries.next(); assertEquals(String.valueOf(ch), entry.getKey()); assertEquals("Value" + ch, entry.getValue()); } } + @Test + public void testForEach() { + final OrderedProperties orderedProperties = new OrderedProperties(); + final char first = 'Z'; + final char last = 'A'; + for (char ch = first; ch >= last; ch--) { + orderedProperties.put(String.valueOf(ch), "Value" + ch); + } + final AtomicInteger aCh = new AtomicInteger(first); + orderedProperties.forEach((k, v) -> { + final char ch = (char) aCh.getAndDecrement(); + assertEquals(String.valueOf(ch), k); + assertEquals("Value" + ch, v); + }); + } + @Test public void testKeys() { final OrderedProperties orderedProperties = new OrderedProperties(); - for (char ch = 'Z'; ch >= 'A'; ch--) { + final char first = 'Z'; + final char last = 'A'; + for (char ch = first; ch >= last; ch--) { orderedProperties.put(String.valueOf(ch), "Value" + ch); } final Enumeration keys = orderedProperties.keys(); - for (char ch = 'Z'; ch <= 'A'; ch++) { + for (char ch = first; ch <= last; ch++) { assertEquals(String.valueOf(ch), keys.nextElement()); } } @Test - public void testLoadOrderedKeys() throws FileNotFoundException, IOException { + public void testLoadOrderedKeys() throws IOException { final OrderedProperties orderedProperties = new OrderedProperties(); try (FileReader reader = new FileReader("src/test/resources/org/apache/commons/collections4/properties/test.properties")) { orderedProperties.load(reader); @@ -154,7 +187,7 @@ public void testLoadOrderedKeys() throws FileNotFoundException, IOException { } @Test - public void testLoadOrderedKeysReverse() throws FileNotFoundException, IOException { + public void testLoadOrderedKeysReverse() throws IOException { loadOrderedKeysReverse(); } @@ -253,4 +286,17 @@ public void testRemoveKeyValue() throws FileNotFoundException, IOException { assertFalse(Collections.list(props.keys()).contains(k)); assertFalse(Collections.list(props.propertyNames()).contains(k)); } + + @Test + public void testToString() { + final OrderedProperties orderedProperties = new OrderedProperties(); + final char first = 'Z'; + final char last = 'A'; + for (char ch = first; ch >= last; ch--) { + orderedProperties.put(String.valueOf(ch), "Value" + ch); + } + assertEquals( + "{Z=ValueZ, Y=ValueY, X=ValueX, W=ValueW, V=ValueV, U=ValueU, T=ValueT, S=ValueS, R=ValueR, Q=ValueQ, P=ValueP, O=ValueO, N=ValueN, M=ValueM, L=ValueL, K=ValueK, J=ValueJ, I=ValueI, H=ValueH, G=ValueG, F=ValueF, E=ValueE, D=ValueD, C=ValueC, B=ValueB, A=ValueA}", + orderedProperties.toString()); + } }