一般immutable类都需要重写equals和hashCode函数。这两个函数继承自Object基类
例如一个代表边的泛型类,认为如果起点终点权重相等的边等价,hashCode采用起点终点权重的hashCode乘质数相加的方法。
如下:
接收任意一个类的对象,首先要判断它是一个Edge对象,然后由于Edge是泛型类,还需要在强制类型转换时加上"<?>"
/**
* Override equals
* @param obj an object expected to be Edge<>
* @return true if source, target, weight are equal
*/
@Override public boolean equals(Object obj){
if(obj instanceof Edge){
if(!this.source.equals(((Edge<?>) obj).source()))
return false;
if(!this.target.equals(((Edge<?>) obj).target()))
return false;
return this.weight == ((Edge<?>) obj).weight;
}
return false;
}
/**
* Override hashCode
* @return hashCode of this
*/
@Override public int hashCode(){
int result = this.source.hashCode();
result = 17 * result + this.target.hashCode();
result = 17 * result + this.weight;
return result;
}
完整类如下:
/**
* TODO specification
* Immutable.
* This class is internal to the rep of ConcreteEdgesGraph.
*
* <p>PS2 instructions: the specification and implementation of this class is
* up to you.
*/
class Edge<L> {
// TODO fields
private final L source;
private final L target;
private final int weight;
// Abstraction function:
// represents one edge from source to target of weight
// field source represents the source of the edge
// field target represents the target of the edge
// field weight represents the weight of the edge
// TODO
// Representation invariant:
// source and target are two different vertex
// weight > 0
// TODO
// Safety from rep exposure:
// All fields are private
// source and target are String and weight is int. So they are immutable
// TODO
// TODO constructor
public Edge(L sourceVertex, L targetVertex, int weightOfEdge){
source = sourceVertex;
target = targetVertex;
weight = weightOfEdge;
checkRep();
}
// TODO checkRep
public void checkRep(){
assert (weight > 0);
assert (!source.equals(target));
}
// TODO methods
/**
* get immutable field source
* @return this.source
*/
public L source(){
return source;
}
/**
* get immutable field target
* @return this.target
*/
public L target(){
return target;
}
/**
* get immutable field weight
* @return this.weight
*/
public int weight(){
return weight;
}
/**
* generate a new Edge from this.source to this.target of weight w to replace older Edge
* @param w weight
* @return a new Edge from source to target of weight w
*/
public Edge<L> setWeight(int w){
return new Edge<>(source, target, w);
}
/**
* Override equals
* @param obj an object expected to be Edge<>
* @return true if source, target, weight are equal
*/
@Override public boolean equals(Object obj){
if(obj instanceof Edge){
if(!this.source.equals(((Edge<?>) obj).source()))
return false;
if(!this.target.equals(((Edge<?>) obj).target()))
return false;
return this.weight == ((Edge<?>) obj).weight;
}
return false;
}
/**
* Override hashCode
* @return hashCode of this
*/
@Override public int hashCode(){
int result = this.source.hashCode();
result = 17 * result + this.target.hashCode();
result = 17 * result + this.weight;
return result;
}
// TODO toString()
/**
* useful human-readable representation of the abstract value.
* @return representation
*/
@Override public String toString(){
return String.format(source.toString() + " -> " + target.toString() + " %d\n", weight);
}
}