Add 2P-Set (Two-Phase Set) for both addition and removal operations in distributed systems (#4977)
This commit is contained in:
parent
36580bac1e
commit
249ee1dc99
@ -86,6 +86,7 @@
|
|||||||
* [GCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java)
|
* [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)
|
* [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)
|
* [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
|
||||||
* [DisjointSetUnion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnion.java)
|
* [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)
|
* [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)
|
* [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)
|
* [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)
|
* [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)
|
* [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)
|
* [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)
|
* [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)
|
* [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)
|
* [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)
|
* [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
|
* disjointsetunion
|
||||||
* [DisjointSetUnionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionTest.java)
|
* [DisjointSetUnionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionTest.java)
|
||||||
* graphs
|
* graphs
|
||||||
|
@ -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<String> setA;
|
||||||
|
private Set<String> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user