如何改变这个合并()方法的多值寄存器CRDT实现?



我有以下问题:在MVR-CRDT的这个简单实现中,merge()方法应该将所有不为空的值添加到合并的副本中。为了实现这一点,我使用了一个For循环,它遍历两个数组列表。在每个存在值的索引处,它比较向量时钟并覆盖该索引处最高时钟的值。它似乎没有像预期的那样起作用。如果有人能指出这个问题,我会很高兴的。

import java.util.ArrayList;
import java.util.Collections;
public class MVR_CRDT{
//variables
static int size;
private ArrayList<Integer> vectorClock;
private ArrayList<Object> values;

//constructor
public MVR_CRDT(int size) {
this.vectorClock = new ArrayList<Integer>(Collections.nCopies(size, 0));
this.values = new ArrayList<Object>(Collections.nCopies(size, null));
}    

//sets a value and increments its corresponding vector clock
public void setValue(int index, Object value) {
//check if value is different
if (value != this.values.get(index)){
this.vectorClock.set(index, this.vectorClock.get(index) + 1);
this.values.set(index, value);
//goes over the other indexes and empties their value
for (int i = 0; i < size; i++) {
while (i != index){
this.values.set(i, null);
}
}
}
}
//the second replica merges into the first
public static void merge(MVR_CRDT first, MVR_CRDT second){
//loops through the ArrayList
for (int i = 0; i < size; i++) {
//if there is a value to be merged
if (second.values.get(i) != null){
first.vectorClock.set(i, max(first.vectorClock.get(i), second.vectorClock.get(i)));
first.values.set(i, second.values.get(i));
}
}
}

private static Integer max(Integer integer, Integer integer2) {
return null;
}
//gets the value at index position of a replica
public Object getValue(int index) {
return this.values.get(index);
}
public Integer getVector(int index) {
return this.vectorClock.get(index);
}
//prints the replica
public void query() {
System.out.println("Vector Clock: " + this.vectorClock.toString());
System.out.println("Values: " + this.values.toString() + "n");
}
public static void main(String[] args) {
MVR_CRDT Alice = new MVR_CRDT(3);
MVR_CRDT Bob = new MVR_CRDT(3);
MVR_CRDT Charlie = new MVR_CRDT(3);
Alice.setValue(0, "Hello");
Alice.setValue(0, "Hello"); //to show that Alices counter does not increase
System.out.println("Alice's replica: ");
Alice.query();
Bob.setValue(1, 12312);
System.out.println("Bob's replica: ");
Bob.query();
// Charlie.setValue(2, false);
merge(Alice, Bob);
System.out.println("Alice's replica after merging: ");
Alice.query();
// System.out.println(Bob.getValue(1) + " , " + Bob.getVector(1));
}
}

期望合并后输出:

Vector Clock: [1, 1, 0] Values: [Hello, 12312, null]

主方法输出:

Alice's replica: 
Vector Clock: [1, 0, 0]
Values: [Hello, null, null]
Bob's replica:
Vector Clock: [0, 1, 0]
Values: [null, 12312, null]
Alice's replica after merging:
Vector Clock: [1, 0, 0]
Values: [Hello, null, null]

看看你的代码,可以做一些改进。我从你要的开始,所以你可以在那之后停止:

您的方法merge使用静态变量size作为for循环中的停止标准,这从未显式初始化,因此它被隐式初始化为0-merge中的循环从不进行单个传递,因此您的输出显示未修改的Alice

但即使它会使用"better"size,例如first.vectorClock.size(),它不会输出正确的结果,而是一个不同的结果:

Alice's replica after merging: 
Vector Clock: [1, null, 0]
Values: [Hello, 12312, null]

这是因为你的max方法总是返回null。我建议您使用内置的max方法,如Integer.max(int, int)。然后输出您期望的结果。


现在还有一些其他的发现(你可以停止阅读,你原来的问题解决了):当您在这里发布代码时,请使用既定的命名约定,对于Java,这在Java语言规范第6章中。名称,第6.1节。声明(从长嵌套列表后面开始,用斜体书写)。

所以你的类名应该是MvrCrdt或更好的MultiValueRegisterCRDT-甚至更长?您的实例AliceBob应该以小写字母开头,并且是alicebob

你的代码剩余物和注释代码应该删除,在这里发布之前。

声明:成员字段不需要知道列表的实现,使用List<Integer>List<Object>就足够了,在构造函数中只使用new操作符使用ArrayList<>!

由于您永远不会重新分配成员字段vectorClockvalues,因此您应该将它们设置为final

构造函数:您不需要指定列表在赋值时存储的类型,有this.vectorClock = new ArrayList<>(Collections.nCopies(size, 0));

就足够了方法setValue:您在setValue方法中有与size相同的问题,请将其替换为this.values.size()

for循环中的while循环中,iindex的值在while循环中永远不会改变,因此您应该将while替换为if或更改循环体。否则,如果进入了循环,你就会有一个无尽的循环!现在您还没有遇到这个问题,因为外部的for循环从来没有进入过。

方法merge:该方法既不能是static,也不能有两个参数。它总是修改第一个输入,所以它也可以将对象合并到当前实例中,并操作this而不是first:

public void merge(MultiValueRegisterCrdt other) {
//loops through the ArrayList
for (int i = 0; i < this.vectorClock.size(); i++) {
//if there is a value to be merged
if (other.values.get(i) != null) {
this.vectorClock.set(i, Integer.max(this.vectorClock.get(i), other.vectorClock.get(i)));
this.values.set(i, other.values.get(i));
}
}
}

有了这个修改,你必须这样使用:alice.merge(bob);

方法query:您可以用toString的重写来替换它,例如:

@Override
public String toString() {
return "MultiValueRegisterCrdt{" +
"vectorClock=" + vectorClock +
", values=" + values +
'}';
}

你可以使用System.out.println("Alice's replica: n" + alice);

相关内容

  • 没有找到相关文章

最新更新