diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TMap.java b/classlib/src/main/java/org/teavm/classlib/java/util/TMap.java index b85f0e74d..b1ceca084 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TMap.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TMap.java @@ -92,12 +92,13 @@ public interface TMap { V oldValue = v; V newValue = remappingFunction.apply(key, oldValue); if (newValue != null) { - return put(key, newValue); + put(key, newValue); } else { - return remove(key); + remove(key); } + return newValue; } - return v; + return null; } default V compute(K key, BiFunction remappingFunction) { @@ -120,9 +121,10 @@ public interface TMap { V newValue = (oldValue == null) ? value : remappingFunction.apply(oldValue, value); if (newValue == null) { - return remove(key); + remove(key); } else { - return put(key, newValue); + put(key, newValue); } + return newValue; } } diff --git a/tests/src/test/java/org/teavm/classlib/java/util/HashtableTest.java b/tests/src/test/java/org/teavm/classlib/java/util/HashtableTest.java index deb94921d..e8582ba32 100644 --- a/tests/src/test/java/org/teavm/classlib/java/util/HashtableTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/util/HashtableTest.java @@ -731,7 +731,7 @@ public class HashtableTest { } @Test - public void test_computeRemovesEntryOnNullMapping() { + public void test_computeRemovesEntryWhenNullProduced() { Hashtable ht10 = new Hashtable<>(); for(int i = 0; i < 10; i++) { ht10.put("Key" + i, "Val" + i); @@ -750,6 +750,258 @@ public class HashtableTest { } } + @Test + public void test_computeIfAbsentNominal() { + Hashtable ht10 = new Hashtable<>(); + for(int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.computeIfAbsent("absent key", (k) -> "added"); + assertEquals("added", newVal); + assertEquals(11, ht10.size()); + + for(int i = 0; i < 10; i++) { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + assertEquals("New value expected","added", ht10.get("absent key")); + } + + @Test + public void test_computeIfAbsentIgnoresExistingEntry() { + Hashtable ht10 = new Hashtable<>(); + for(int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.computeIfAbsent("Key5", (v) -> "changed"); + assertEquals("Val5", newVal); + assertEquals(10, ht10.size()); + + for(int i = 0; i < 10; i++) { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + } + + @Test + public void test_computeIfAbsentDoesNothingIfNullProduced() { + Hashtable ht10 = new Hashtable<>(); + for(int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.computeIfAbsent("absent key", (v) -> null); + assertEquals(null, newVal); + assertEquals(10, ht10.size()); + + for(int i = 0; i < 10; i++) { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + } + + @Test + public void test_computeIfPresentNominal() { + Hashtable ht10 = new Hashtable<>(); + for(int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.computeIfPresent("Key5", (k, v) -> "changed"); + assertEquals("changed", newVal); + assertEquals(10, ht10.size()); + + for(int i = 0; i < 10; i++) { + if(i == 5) { + assertEquals("Value was incorrectly updated", "changed", ht10.get("Key" + i)); + } else { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + } + } + + @Test + public void test_computeIfPresentIgnoresAbsentKeys() { + Hashtable ht10 = new Hashtable<>(); + for(int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.computeIfPresent("absent key", (k, v) -> "added"); + assertEquals(null, newVal); + assertEquals(10, ht10.size()); + + for(int i = 0; i < 10; i++) { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + } + + @Test + public void test_computeIfPresentRemovesEntryWhenNullProduced() { + Hashtable ht10 = new Hashtable<>(); + for(int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.computeIfPresent("Key5", (k, v) -> null); + assertEquals(null, newVal); + assertEquals(9, ht10.size()); + + for(int i = 0; i < 10; i++) { + if(i == 5) { + assertNull("Value unexpectedly present", ht10.get("Key" + i)); + } else { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + } + } + + + @Test + public void test_mergeKeyAbsentCase() { + Hashtable ht10 = new Hashtable<>(); + for (int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.merge("absent key", "changed", (k, v) -> "remapped"); + assertEquals("changed", newVal); + assertEquals(11, ht10.size()); + + for (int i = 0; i < 10; i++) { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + assertEquals("New value expected", "changed", ht10.get("absent key")); + } + + @Test + public void test_mergeKeyPresentCase() { + Hashtable ht10 = new Hashtable<>(); + for (int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.merge("Key5", "changed", (k, v) -> "remapped"); + assertEquals("remapped", newVal); + assertEquals(10, ht10.size()); + + for (int i = 0; i < 10; i++) { + if (i == 5) { + assertEquals("Value was incorrectly updated", "remapped", ht10.get("Key" + i)); + } else { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + } + } + + @Test + public void test_mergeKeyAbsentCase_remapToNull() { + Hashtable ht10 = new Hashtable<>(); + for (int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.merge("absent key", "changed", (k, v) -> null); + assertEquals("changed", newVal); + assertEquals(11, ht10.size()); + + for (int i = 0; i < 10; i++) { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + assertEquals("New value expected", "changed", ht10.get("absent key")); + } + + @Test + public void test_mergeKeyPresentCase_remapToNull() { + Hashtable ht10 = new Hashtable<>(); + for (int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.merge("Key5", "changed", (k, v) -> null); + assertEquals(null, newVal); + assertEquals(9, ht10.size()); + + for (int i = 0; i < 10; i++) { + if (i == 5) { + assertNull("Null value expected", ht10.get("Key" + i)); + } else { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + } + } + + @Test + public void test_replaceNominal() { + Hashtable ht10 = new Hashtable<>(); + for (int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.replace("Key5", "changed"); + assertEquals("Val5", newVal); + assertEquals(10, ht10.size()); + + for (int i = 0; i < 10; i++) { + if (i == 5) { + assertEquals("Value was incorrectly updated", "changed", ht10.get("Key" + i)); + } else { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + } + } + + @Test + public void test_replaceAbsentKey() { + Hashtable ht10 = new Hashtable<>(); + for (int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + String newVal = ht10.replace("absent key", "changed"); + assertEquals(null, newVal); + assertEquals(10, ht10.size()); + + for (int i = 0; i < 10; i++) { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + } + + @Test + public void test_replace2Nominal() { + Hashtable ht10 = new Hashtable<>(); + for (int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + boolean replaced = ht10.replace("Key5", "Val5", "changed"); + assertEquals(true, replaced); + assertEquals(10, ht10.size()); + + for (int i = 0; i < 10; i++) { + if (i == 5) { + assertEquals("Value was incorrectly updated", "changed", ht10.get("Key" + i)); + } else { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + } + } + + @Test + public void test_replace2WithIncorrectExpectation() { + Hashtable ht10 = new Hashtable<>(); + for (int i = 0; i < 10; i++) { + ht10.put("Key" + i, "Val" + i); + } + + boolean replaced = ht10.replace("Key5", "incorrect value", "changed"); + assertEquals(false, replaced); + assertEquals(10, ht10.size()); + + for (int i = 0; i < 10; i++) { + assertEquals("Value was unexpectedly changed", "Val" + i, ht10.get("Key" + i)); + } + } + @SuppressWarnings("unchecked") protected Hashtable hashtableClone(Hashtable s) { return (Hashtable) s.clone();