1414 *
1515 * @param <T> The type of the elements in the LWWElementSet.
1616 * @author <a href="https://github.com/itakurah">itakurah (GitHub)</a>, <a
17- * href="https://www.linkedin.com/in/niklashoefflin/">Niklas Hoefflin (LinkedIn)</a>
17+ * href="https://www.linkedin.com/in/niklashoefflin/">Niklas Hoefflin (LinkedIn)</a>
1818 * @see <a href="https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type">Conflict free
19- * replicated data type (Wikipedia)</a>
19+ * replicated data type (Wikipedia)</a>
2020 * @see <a href="https://inria.hal.science/inria-00555588v1/document">A comprehensive study of
21- * Convergent and Commutative Replicated Data Types</a>
21+ * Convergent and Commutative Replicated Data Types</a>
2222 */
2323class LWWElementSet <T > {
24- final Map <T , Element <T >> addSet ;
25- final Map <T , Element <T >> removeSet ;
24+ final Map <T , Element <T >> addSet ;
25+ final Map <T , Element <T >> removeSet ;
2626
27- /**
28- * Constructs an empty LWWElementSet. This constructor initializes the addSet and removeSet as
29- * empty HashMaps. The addSet stores elements that are added, and the removeSet stores elements
30- * that are removed.
31- */
32- LWWElementSet () {
33- this .addSet = new HashMap <>();
34- this .removeSet = new HashMap <>();
35- }
36-
37- /**
38- * Adds an element to the addSet with the current timestamp. This method stores the element in the
39- * addSet, ensuring that the element is added to the set with an associated timestamp that
40- * represents the time of the addition.
41- *
42- * @param key The key of the element to be added.
43- */
44- public void add (T key ) {
45- addSet .put (key , new Element <>(key , Instant .now ()));
46- }
27+ /**
28+ * Constructs an empty LWWElementSet. This constructor initializes the addSet and removeSet as
29+ * empty HashMaps. The addSet stores elements that are added, and the removeSet stores elements
30+ * that are removed.
31+ */
32+ LWWElementSet () {
33+ this .addSet = new HashMap <>();
34+ this .removeSet = new HashMap <>();
35+ }
4736
48- /**
49- * Removes an element by adding it to the removeSet with the current timestamp. This method adds
50- * the element to the removeSet, marking it as removed with the current timestamp.
51- *
52- * @param key The key of the element to be removed.
53- */
54- public void remove (T key ) {
55- removeSet .put (key , new Element <>(key , Instant .now ()));
56- }
37+ /**
38+ * Adds an element to the addSet with the current timestamp. This method stores the element in the
39+ * addSet, ensuring that the element is added to the set with an associated timestamp that
40+ * represents the time of the addition.
41+ *
42+ * @param key The key of the element to be added.
43+ */
44+ public void add (T key ) {
45+ addSet .put (key , new Element <>(key , Instant .now ()));
46+ }
5747
58- /**
59- * Checks if an element is in the LWWElementSet. An element is considered present if it exists in
60- * the addSet and either does not exist in the removeSet, or its add timestamp is later than any
61- * corresponding remove timestamp.
62- *
63- * @param key The key of the element to be checked.
64- * @return {@code true} if the element is present in the set (i.e., its add timestamp is later
65- * than its remove timestamp, or it is not in the remove set), {@code false} otherwise (i.e.,
66- * the element has been removed or its remove timestamp is later than its add timestamp).
67- */
68- public boolean lookup (T key ) {
69- Element <T > inAddSet = addSet .get (key );
70- Element <T > inRemoveSet = removeSet .get (key );
48+ /**
49+ * Removes an element by adding it to the removeSet with the current timestamp. This method adds
50+ * the element to the removeSet, marking it as removed with the current timestamp.
51+ *
52+ * @param key The key of the element to be removed.
53+ */
54+ public void remove (T key ) {
55+ removeSet .put (key , new Element <>(key , Instant .now ()));
56+ }
7157
72- return inAddSet != null
73- && (inRemoveSet == null || inAddSet .timestamp .isAfter (inRemoveSet .timestamp ));
74- }
58+ /**
59+ * Checks if an element is in the LWWElementSet. An element is considered present if it exists in
60+ * the addSet and either does not exist in the removeSet, or its add timestamp is later than any
61+ * corresponding remove timestamp.
62+ *
63+ * @param key The key of the element to be checked.
64+ * @return {@code true} if the element is present in the set (i.e., its add timestamp is later
65+ * than its remove timestamp, or it is not in the remove set), {@code false} otherwise (i.e.,
66+ * the element has been removed or its remove timestamp is later than its add timestamp).
67+ */
68+ public boolean lookup (T key ) {
69+ Element <T > inAddSet = addSet .get (key );
70+ Element <T > inRemoveSet = removeSet .get (key );
7571
76- /**
77- * Merges another LWWElementSet into this set. This method takes the union of both the add-sets
78- * and remove-sets from the two sets, resolving conflicts by keeping the element with the latest
79- * timestamp. If an element appears in both the add-set and remove-set of both sets, the one with
80- * the later timestamp will be retained.
81- *
82- * @param other The LWWElementSet to merge with the current set.
83- */
84- public void merge (LWWElementSet <T > other ) {
85- for (Map .Entry <T , Element <T >> entry : other .addSet .entrySet ()) {
86- addSet .merge (entry .getKey (), entry .getValue (), this ::resolveConflict );
72+ return inAddSet != null
73+ && (inRemoveSet == null || inAddSet .timestamp .isAfter (inRemoveSet .timestamp ));
8774 }
88- for (Map .Entry <T , Element <T >> entry : other .removeSet .entrySet ()) {
89- removeSet .merge (entry .getKey (), entry .getValue (), this ::resolveConflict );
75+
76+ /**
77+ * Merges another LWWElementSet into this set. This method takes the union of both the add-sets
78+ * and remove-sets from the two sets, resolving conflicts by keeping the element with the latest
79+ * timestamp. If an element appears in both the add-set and remove-set of both sets, the one with
80+ * the later timestamp will be retained.
81+ *
82+ * @param other The LWWElementSet to merge with the current set.
83+ */
84+ public void merge (LWWElementSet <T > other ) {
85+ for (Map .Entry <T , Element <T >> entry : other .addSet .entrySet ()) {
86+ addSet .merge (entry .getKey (), entry .getValue (), this ::resolveConflict );
87+ }
88+ for (Map .Entry <T , Element <T >> entry : other .removeSet .entrySet ()) {
89+ removeSet .merge (entry .getKey (), entry .getValue (), this ::resolveConflict );
90+ }
9091 }
91- }
9292
93- /**
94- * Resolves conflicts between two elements by selecting the one with the later timestamp. This
95- * method is used when merging two LWWElementSets to ensure that the most recent operation (based
96- * on timestamps) is kept.
97- *
98- * @param e1 The first element.
99- * @param e2 The second element.
100- * @return The element with the later timestamp.
101- */
102- private Element <T > resolveConflict (Element <T > e1 , Element <T > e2 ) {
103- return e1 .timestamp .isAfter (e2 .timestamp ) ? e1 : e2 ;
104- }
93+ /**
94+ * Resolves conflicts between two elements by selecting the one with the later timestamp. This
95+ * method is used when merging two LWWElementSets to ensure that the most recent operation (based
96+ * on timestamps) is kept.
97+ *
98+ * @param e1 The first element.
99+ * @param e2 The second element.
100+ * @return The element with the later timestamp.
101+ */
102+ private Element <T > resolveConflict (Element <T > e1 , Element <T > e2 ) {
103+ return e1 .timestamp .isAfter (e2 .timestamp ) ? e1 : e2 ;
104+ }
105105}
106106
107107/**
@@ -111,17 +111,17 @@ private Element<T> resolveConflict(Element<T> e1, Element<T> e2) {
111111 * @param <T> The type of the key associated with the element.
112112 */
113113class Element <T > {
114- T key ;
115- Instant timestamp ;
114+ T key ;
115+ Instant timestamp ;
116116
117- /**
118- * Constructs a new Element with the specified key and timestamp.
119- *
120- * @param key The key of the element.
121- * @param timestamp The timestamp associated with the element.
122- */
123- Element (T key , Instant timestamp ) {
124- this .key = key ;
125- this .timestamp = timestamp ;
126- }
117+ /**
118+ * Constructs a new Element with the specified key and timestamp.
119+ *
120+ * @param key The key of the element.
121+ * @param timestamp The timestamp associated with the element.
122+ */
123+ Element (T key , Instant timestamp ) {
124+ this .key = key ;
125+ this .timestamp = timestamp ;
126+ }
127127}
0 commit comments