exercise 1
实现这两个骨架:
- src/simpledb/TupleDesc.java
- src/simpledb/Tuple.java
Tuple就是filed objects的集合,然后filed类型可以不同。TupleDesc则是Tuple的schema,也就是其元信息。
所以,TupleDesc就是tuple的schema,比如对于表student
id(int) name(string) sex(string)
1 xxx m
2 yyy f
那么(1, xxx, m)
就是一个Tuple,然后TupleDesc是(id(int) name(string) sex(string))
。
首先实现TupleDesc
我们首先看到,这个类中有一个辅助类,声明了基本单元
/**
* A help class to facilitate organizing the information of each field
* */
public static class TDItem implements Serializable {
private static final long serialVersionUID = 1L;
/**
* The type of the field
* */
public final Type fieldType;
/**
* The name of the field
* */
public final String fieldName;
public TDItem(Type t, String n) {
this.fieldName = n;
this.fieldType = t;
}
public String toString() {
return fieldName + "(" + fieldType + ")";
}
}
因此我们使用ArrayList来存储这些field,我们使用的数据结构就是
ArrayList<TDItem> tdItems = new ArrayList<>();
然后构造函数就很好写
/**
* Create a new TupleDesc with typeAr.length fields with fields of the
* specified types, with associated named fields.
*
* @param typeAr
* array specifying the number of and types of fields in this
* TupleDesc. It must contain at least one entry.
* @param fieldAr
* array specifying the names of the fields. Note that names may
* be null.
*/
public TupleDesc(Type[] typeAr, String[] fieldAr) {
for(int i = 0; i < typeAr.length; i++){
tdItems.add(new TDItem(typeAr[i], fieldAr[i]));
}
}
/**
* Constructor. Create a new tuple desc with typeAr.length fields with
* fields of the specified types, with anonymous (unnamed) fields.
*
* @param typeAr
* array specifying the number of and types of fields in this
* TupleDesc. It must contain at least one entry.
*/
public TupleDesc(Type[] typeAr) {
for(Type type : typeAr){
tdItems.add(new TDItem(type,""));
}
}
/**
* @return the number of fields in this TupleDesc
*/
public int numFields() {
return tdItems.size();
}
/**
* Gets the (possibly null) field name of the ith field of this TupleDesc.
*
* @param i
* index of the field name to return. It must be a valid index.
* @return the name of the ith field
* @throws NoSuchElementException
* if i is not a valid field reference.
*/
public String getFieldName(int i) throws NoSuchElementException {
return tdItems.get(i).fieldName;
}
/**
* Gets the type of the ith field of this TupleDesc.
*
* @param i
* The index of the field to get the type of. It must be a valid
* index.
* @return the type of the ith field
* @throws NoSuchElementException
* if i is not a valid field reference.
*/
public Type getFieldType(int i) throws NoSuchElementException {
return tdItems.get(i).fieldType;
}
/**
* @return The size (in bytes) of tuples corresponding to this TupleDesc.
* Note that tuples from a given TupleDesc are of a fixed size.
*/
public int getSize() {
int size = 0;
for(TDItem tdItem : tdItems){
size += tdItem.fieldType.getLen();
}
return size;
}
对于tupleDesc的equals方法写法,有标准的步骤。
public boolean equals(Object o) {
// some code goes here
if(this == o){
return true;
}
if(o == null){
return false;
}
if(getClass() != o.getClass()){
return false;
}
TupleDesc tupleDesc = (TupleDesc) o;
int n = this.numFields();
if(tupleDesc.numFields() != n){
return false;
}
for(int i = 0; i < n; i++){
if(!this.getFieldName(i).equals(tupleDesc.getFieldName(i))||
!this.getFieldType(i).equals(tupleDesc.getFieldType(i))){
return false;
}
}
return true;
}
按照要求抛出异常
/**
* Find the index of the field with a given name.
*
* @param name
* name of the field.
* @return the index of the field that is first to have the given name.
* @throws NoSuchElementException
* if no field with a matching name is found.
*/
public int fieldNameToIndex(String name) throws NoSuchElementException {
// some code goes here
for(int i = 0; i < tdItems.size(); i++){
if(tdItems.get(i).fieldName.equals(name)){
return i;
}
}
throw new NoSuchElementException();
}
/**
* Merge two TupleDescs into one, with td1.numFields + td2.numFields fields,
* with the first td1.numFields coming from td1 and the remaining from td2.
*
* @param td1
* The TupleDesc with the first fields of the new TupleDesc
* @param td2
* The TupleDesc with the last fields of the TupleDesc
* @return the new TupleDesc
*/
public static TupleDesc merge(TupleDesc td1, TupleDesc td2) {
// some code goes here
Type[] types = new Type[td1.numFields() + td2.numFields()];
String[] fieldAr = new String[td1.numFields() + td2.numFields()];
int k = 0;
for(int i = 0; i < td1.numFields(); i++){
types[k] = td1.getFieldType(i);
fieldAr[k] = td1.getFieldName(i);
k++;
}
for(int i = 0; i < td2.numFields(); i++){
types[k] = td2.getFieldType(i);
fieldAr[k] = td2.getFieldName(i);
k++;
}
return new TupleDesc(types, fieldAr);
}
tuple的实现也就非常简单
/**
* Create a new tuple with the specified schema (type).
*
* @param td
* the schema of this tuple. It must be a valid TupleDesc
* instance with at least one field.
*/
public Tuple(TupleDesc td) {
this.td = td;
fieldArray = new ArrayList<>(td.numFields());
for(int i = 0; i < td.numFields(); i++){
fieldArray.add(null);
}
}
/**
* Returns the contents of this Tuple as a string. Note that to pass the
* system tests, the format needs to be as follows:
*
* column1\tcolumn2\tcolumn3\t...\tcolumnN
*
* where \t is any whitespace (except a newline)
*/
public String toString() {
StringJoiner joiner = new StringJoiner("\t");
for(Field field : fieldArray){
joiner.add(field.toString());
}
return joiner.toString();
}
注意要实现RecordId类,其中equals和hashcode方法可以由IDEA自动实现。