exercise 1

实现

  • src/simpledb/TupleDesc.java
  • src/simpledb/Tuple.java

通过

  • TupleDescTest
  • TupleTest

两个test。

结构关系

最主要的难点是理清楚一个大致的结构关系。

首先看看两个类的方法,好的方法从名字就可以猜出对应的实现。

首先可以看出来,Tuple是由TupleDesc作为参数进行构造的。即每次在建立元组的时候,都要传入一个视图信息。所以先看看TupleDesc又是由什么构造的。

TupleDesc内部生命了一个静态类,TDItem。静态内部类的特点是无法调用外部类的方法。这样设计的含义是,外部类要用到该内部类,但是该内部类与外部类相对独立。

我们看看TDItem的内部结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static class TDItem implements Serializable {

private static final long serialVersionUID = 1L;

/**
* The type of the field
* */
public final Type fieldType;//比如int类,string类

/**
* The name of the field
* */
public final String fieldName; //字段的名字,比如student,teacher

public TDItem(Type t, String n) {
this.fieldName = n;
this.fieldType = t;
}

public String toString() {
return fieldName + "(" + fieldType + ")";
}
}

其实就是对应一个字段的Type和String。

同时我们看到TupleDesc的构造函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
public TupleDesc(Type[] typeAr, String[] fieldAr) {
// some code goes here
this.fieldSize=0;
listOfTDItem=new ArrayList<>();
this.fieldLength=typeAr.length;
for(int i=0;i<fieldLength;i++){
Type temp=typeAr[i];
this.fieldSize+=temp.getLen();
listOfTDItem.add(new TDItem(temp,fieldAr[i]));/
}

}

该构造函数需要自己实现,传入的是type和string的数组。结合视图的定义,TupleDesc应该是一个描述字段信息的集合。也就是应该是一个TDItem的集合,所以我们用list来存储TDItem,然后利用传入的数组实现对list的初始化。

回过头来看元组,元组用TupleDesc来进行构造。但是我们应该思考下一个元组存储的是什么?

元组存储的应该是“真正的数据”。当然,我们希望能从元组中知道对应的数据的类型,因此,元组可以定义一个变量,指向传进来的TupleDesc。

在元组里要求我们实现一个方法,即设置对应位置的字段值如下:

1
2
3
4
public void setField(int i, Field f) {//field是一个接口
// some code goes here
fieldList.add(i,f);
}

这里传入的参数是Field。Field是一个接口,在本项目中具体的实现有IntField和StringField。其对应的有getValue和toString等函数。因此,这里的Field,代表的就是元组实际存储的数据。而元组,正应该是数据的集合,因此,元组的主要数据结构就是一个field的list。

用IDEA生成类图如下所示:

image-20211112104814127

注意事项

在用测试用例进行测试的时候,也出现了一些问题。

首先是String之间的比较一定要记得用equals而不是直接比较。

然后是在用Type[] typeAr对TupleDesc进行构造的时候,要注意对fieldName也插入一个代表空的字符串,因为后面设计TupleDesc的比较,会调用String的equals函数,不能为空。