diff --git a/DIRECTORY.md b/DIRECTORY.md index 4a94809560a1..703642a0d28e 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -86,6 +86,7 @@ * [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) + * [TwoPSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java) * disjointsetunion * [DisjointSetUnion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnion.java) * [Node](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/disjointsetunion/Node.java) @@ -528,7 +529,7 @@ * [InfixToPostfix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/InfixToPostfix.java) * [LargestRectangle](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/LargestRectangle.java) * [MaximumMinimumWindow](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/MaximumMinimumWindow.java) - * [NextGraterElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/NextGraterElement.java) + * [NextGreaterElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/NextGreaterElement.java) * [NextSmallerElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/NextSmallerElement.java) * [PostfixToInfix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/PostfixToInfix.java) * [StackPostfixNotation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/StackPostfixNotation.java) @@ -621,6 +622,7 @@ * [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) + * [TwoPSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java) * disjointsetunion * [DisjointSetUnionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionTest.java) * graphs diff --git a/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java b/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java new file mode 100644 index 000000000000..f5e155c28d8d --- /dev/null +++ b/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java @@ -0,0 +1,84 @@ +package com.thealgorithms.datastructures.crdt; + +import java.util.HashSet; +import java.util.Set; + +/** + * TwoPhaseSet (2P-Set) is a state-based CRDT (Conflict-free Replicated Data Type) designed for managing sets + * with support for both addition and removal operations in a distributed and concurrent environment. + * It combines two G-Sets (grow-only sets) - one set for additions and another set (tombstone set) for removals. + * Once an element is removed and placed in the tombstone set, it cannot be re-added, adhering to "remove-wins" semantics. + * This implementation supports querying the presence of elements, adding elements, removing elements, + * comparing with other 2P-Sets, and merging two 2P-Sets while preserving the remove-wins semantics. + * (https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type) + * + * @author itakurah (Niklas Hoefflin) (https://github.com/itakurah) + */ + +public class TwoPSet { + private Set setA; + private Set setR; + + /** + * Constructs an empty Two-Phase Set. + */ + public TwoPSet() { + this.setA = new HashSet<>(); + this.setR = new HashSet<>(); + } + + /** + * Checks if an element is in the set and has not been removed. + * + * @param element The element to be checked. + * @return True if the element is in the set and has not been removed, otherwise false. + */ + public boolean lookup(String element) { + return setA.contains(element) && !setR.contains(element); + } + + /** + * Adds an element to the set. + * + * @param element The element to be added. + */ + public void add(String element) { + setA.add(element); + } + + /** + * Removes an element from the set. The element will be placed in the tombstone set. + * + * @param element The element to be removed. + */ + public void remove(String element) { + if (lookup(element)) { + setR.add(element); + } + } + + /** + * Compares the current 2P-Set with another 2P-Set. + * + * @param otherSet The other 2P-Set to compare with. + * @return True if both SetA and SetR are subset, otherwise false. + */ + public boolean compare(TwoPSet otherSet) { + return otherSet.setA.containsAll(setA) && otherSet.setR.containsAll(setR); + } + + /** + * Merges the current 2P-Set with another 2P-Set. + * + * @param otherSet The other 2P-Set to merge with. + * @return A new 2P-Set containing the merged elements. + */ + public TwoPSet merge(TwoPSet otherSet) { + TwoPSet mergedSet = new TwoPSet(); + mergedSet.setA.addAll(this.setA); + mergedSet.setA.addAll(otherSet.setA); + mergedSet.setR.addAll(this.setR); + mergedSet.setR.addAll(otherSet.setR); + return mergedSet; + } +} diff --git a/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java b/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java new file mode 100644 index 000000000000..18ab5c169e5c --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java @@ -0,0 +1,68 @@ +package com.thealgorithms.datastructures.crdt; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class TwoPSetTest { + + private TwoPSet set; + + @BeforeEach + void setUp() { + set = new TwoPSet(); + } + + @Test + void testLookup() { + set.add("A"); + assertTrue(set.lookup("A")); + assertFalse(set.lookup("B")); + set.remove("A"); + assertFalse(set.lookup("A")); + } + + @Test + void testAdd() { + set.add("A"); + assertTrue(set.lookup("A")); + } + + @Test + void testRemove() { + set.add("A"); + set.remove("A"); + assertFalse(set.lookup("A")); + } + + @Test + void testCompare() { + TwoPSet set1 = new TwoPSet(); + set1.add("A"); + set1.add("B"); + TwoPSet set2 = new TwoPSet(); + set2.add("A"); + assertFalse(set1.compare(set2)); + set2.add("B"); + assertTrue(set1.compare(set2)); + set1.remove("A"); + assertFalse(set1.compare(set2)); + set2.remove("A"); + assertTrue(set1.compare(set2)); + } + + @Test + void testMerge() { + TwoPSet set1 = new TwoPSet(); + set1.add("A"); + set1.add("B"); + TwoPSet set2 = new TwoPSet(); + set2.add("B"); + set2.add("C"); + TwoPSet mergedSet = set1.merge(set2); + assertTrue(mergedSet.lookup("A")); + assertTrue(mergedSet.lookup("B")); + assertTrue(mergedSet.lookup("C")); + } +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy