From e59a3b1ebba0b484fad64adb06aedc06eb366825 Mon Sep 17 00:00:00 2001 From: Niklas Hoefflin <122729995+itakurah@users.noreply.github.com> Date: Tue, 5 Dec 2023 19:39:18 +0100 Subject: [PATCH] Add G-Set (Grow-only Set) (#4975) --- DIRECTORY.md | 2 + .../datastructures/crdt/GSet.java | 65 +++++++++++++++++ .../datastructures/crdt/GSetTest.java | 71 +++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 src/main/java/com/thealgorithms/datastructures/crdt/GSet.java create mode 100644 src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java diff --git a/DIRECTORY.md b/DIRECTORY.md index 0548d3455..4a9480956 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -84,6 +84,7 @@ * [MRUCache](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/caches/MRUCache.java) * crdt * [GCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java) + * [GSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java) * [PNCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java) * disjointsetunion * [DisjointSetUnion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnion.java) @@ -618,6 +619,7 @@ * [MRUCacheTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/caches/MRUCacheTest.java) * crdt * [GCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java) + * [GSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java) * [PNCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/PNCounterTest.java) * disjointsetunion * [DisjointSetUnionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionTest.java) diff --git a/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java b/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java new file mode 100644 index 000000000..37873adc2 --- /dev/null +++ b/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java @@ -0,0 +1,65 @@ +package com.thealgorithms.datastructures.crdt; + +import java.util.HashSet; +import java.util.Set; + +/** + * GSet (Grow-only Set) is a state-based CRDT (Conflict-free Replicated Data Type) + * that allows only the addition of elements and ensures that once an element is added, + * it cannot be removed. The merge operation of two G-Sets is their union. + * This implementation supports adding elements, looking up elements, comparing with other G-Sets, + * and merging with another G-Set to create a new G-Set containing all unique elements from both sets. + * (https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type) + * + * @author itakurah (Niklas Hoefflin) (https://github.com/itakurah) + */ + +public class GSet { + private final Set elements; + + /** + * Constructs an empty G-Set. + */ + public GSet() { + this.elements = new HashSet<>(); + } + + /** + * Adds an element to the G-Set. + * + * @param e the element to be added + */ + public void addElement(T e) { + elements.add(e); + } + + /** + * Checks if the given element is present in the G-Set. + * + * @param e the element to be checked + * @return true if the element is present, false otherwise + */ + public boolean lookup(T e) { + return elements.contains(e); + } + + /** + * Compares the G-Set with another G-Set to check if it is a subset. + * + * @param other the other G-Set to compare with + * @return true if the current G-Set is a subset of the other, false otherwise + */ + public boolean compare(GSet other) { + return elements.containsAll(other.elements); + } + + /** + * Merges the current G-Set with another G-Set, creating a new G-Set + * containing all unique elements from both sets. + * + * @param other the G-Set to merge with + */ + public void merge(GSet other) { + elements.addAll(other.elements); + } +} diff --git a/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java b/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java new file mode 100644 index 000000000..995882590 --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java @@ -0,0 +1,71 @@ +package com.thealgorithms.datastructures.crdt; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +class GSetTest { + + @Test + void testAddElement() { + GSet gSet = new GSet<>(); + gSet.addElement("apple"); + gSet.addElement("orange"); + + assertTrue(gSet.lookup("apple")); + assertTrue(gSet.lookup("orange")); + assertFalse(gSet.lookup("banana")); + } + + @Test + void testLookup() { + GSet gSet = new GSet<>(); + gSet.addElement(1); + gSet.addElement(2); + + assertTrue(gSet.lookup(1)); + assertTrue(gSet.lookup(2)); + assertFalse(gSet.lookup(3)); + } + + @Test + void testCompare() { + GSet gSet1 = new GSet<>(); + GSet gSet2 = new GSet<>(); + + gSet1.addElement("apple"); + gSet1.addElement("orange"); + + gSet2.addElement("orange"); + gSet2.addElement("banana"); + + assertFalse(gSet1.compare(gSet2)); + + GSet gSet3 = new GSet<>(); + gSet3.addElement("apple"); + gSet3.addElement("orange"); + + assertTrue(gSet1.compare(gSet3)); + } + + @Test + void testMerge() { + GSet gSet1 = new GSet<>(); + GSet gSet2 = new GSet<>(); + + gSet1.addElement("apple"); + gSet1.addElement("orange"); + + gSet2.addElement("orange"); + gSet2.addElement("banana"); + + GSet mergedSet = new GSet<>(); + mergedSet.merge(gSet1); + mergedSet.merge(gSet2); + + assertTrue(mergedSet.lookup("apple")); + assertTrue(mergedSet.lookup("orange")); + assertTrue(mergedSet.lookup("banana")); + assertFalse(mergedSet.lookup("grape")); + } +}