/
NikolayIvkin
/
TheAlgorithms
Обзор
Документация
Войти
/
NikolayIvkin
/
TheAlgorithms
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java
100 строк
3 KB
S. Utkarsh
style: enable `MemberName` in checkstyle (#5193)
29 май 2024, 23:44
Не верифицирован
29 май 2024, 23:44
a6e873d
Код
Авторство
О чём код?
package com.thealgorithms.datastructures.crdt; import java.util.HashMap; import java.util.Map; /** * PN-Counter (Positive-Negative Counter) is a state-based CRDT (Conflict-free Replicated Data Type) * designed for tracking counts with both increments and decrements in a distributed and concurrent environment. * It combines two G-Counters, one for increments (P) and one for decrements (N). * The total count is obtained by subtracting the value of the decrement counter from the increment counter. * This implementation supports incrementing, decrementing, querying the total count, * comparing with other PN-Counters, and merging with another PN-Counter * to compute the element-wise maximum for both increment and decrement counters. * (https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type) * * @author itakurah (Niklas Hoefflin) (https://github.com/itakurah) */ class PNCounter { private final Map<Integer, Integer> pCounter; private final Map<Integer, Integer> nCounter; private final int myId; private final int n; /** * Constructs a PN-Counter for a cluster of n nodes. * * @param myId The identifier of the current node. * @param n The number of nodes in the cluster. */ PNCounter(int myId, int n) { this.myId = myId; this.n = n; this.pCounter = new HashMap<>(); this.nCounter = new HashMap<>(); for (int i = 0; i < n; i++) { pCounter.put(i, 0); nCounter.put(i, 0); } } /** * Increments the increment counter for the current node. */ public void increment() { pCounter.put(myId, pCounter.get(myId) + 1); } /** * Increments the decrement counter for the current node. */ public void decrement() { nCounter.put(myId, nCounter.get(myId) + 1); } /** * Gets the total value of the counter by subtracting the decrement counter from the increment counter. * * @return The total value of the counter. */ public int value() { int sumP = pCounter.values().stream().mapToInt(Integer::intValue).sum(); int sumN = nCounter.values().stream().mapToInt(Integer::intValue).sum(); return sumP - sumN; } /** * Compares the state of this PN-Counter with another PN-Counter. * * @param other The other PN-Counter to compare with. * @return True if the state of this PN-Counter is less than or equal to the state of the other PN-Counter. */ public boolean compare(PNCounter other) { if (this.n != other.n) { throw new IllegalArgumentException("Cannot compare PN-Counters with different number of nodes"); } for (int i = 0; i < n; i++) { if (this.pCounter.get(i) > other.pCounter.get(i) && this.nCounter.get(i) > other.nCounter.get(i)) { return false; } } return true; } /** * Merges the state of this PN-Counter with another PN-Counter. * * @param other The other PN-Counter to merge with. */ public void merge(PNCounter other) { if (this.n != other.n) { throw new IllegalArgumentException("Cannot merge PN-Counters with different number of nodes"); } for (int i = 0; i < n; i++) { this.pCounter.put(i, Math.max(this.pCounter.get(i), other.pCounter.get(i))); this.nCounter.put(i, Math.max(this.nCounter.get(i), other.nCounter.get(i))); } } }