我有以下问题:在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
-甚至更长?您的实例Alice
和Bob
应该以小写字母开头,并且是alice
和bob
。
你的代码剩余物和注释代码应该删除,在这里发布之前。
声明:成员字段不需要知道列表的实现,使用List<Integer>
和List<Object>
就足够了,在构造函数中只使用new
操作符使用ArrayList<>
!
由于您永远不会重新分配成员字段vectorClock
和values
,因此您应该将它们设置为final
。
构造函数:您不需要指定列表在赋值时存储的类型,有this.vectorClock = new ArrayList<>(Collections.nCopies(size, 0));
就足够了方法setValue
:您在setValue
方法中有与size
相同的问题,请将其替换为this.values.size()
。
在for
循环中的while
循环中,i
和index
的值在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);