在下面的场景中寻找重构建议
我们有一个DataMap<header,RecordHolder>
RecordHolder类具有如下近似结构
RecordA,RecordB ....从公共基类型继承 - 记录。
RecordHolder{
RecordA
RecordB
RecordC
RecordD;
setRecordA();
setRecordB();
....
}
解析器实用程序读取文件的每一行并转换为相应的记录类型:
Map<key,Record> parse(String line){....}
从parse返回时,将获取与该键对应的RecordHolder实例 - 并且必须调用相应的setRecordXXX方法来更新已解析的记录。
RecordHolder d = DataMap.get(key);
if(d==null){ ==========> (A)
d = new RecorHolder();
DataMap.put(key,d);
}
d.setRecordXXX(Record);=========>(B)
问题:
(A)对于地图的get-else-put-and-return来说,这是最好的习语
(B)如果没有Record(RecordA,RecordB等)的显式类型检查,我怎样才能实现这一点
答案 0 :(得分:3)
(A)什么是get-else-put-and-return for map的最佳成语。
您可以使用Map#computeIfAbsent()
方法,如下面的代码所示:
DataMap.computeIfAbsent(key, k -> new RecordHolder()).setRecordXXX(Record);
computeIfAbsent
将第一个参数作为键,第二个参数作为Function<KeyType, RecordHolder>
。因此,当密钥没有值时。然后调用该函数并将其设置为值。
地图中可能的实现可以是以下内容(不是jdk中的实际内容):
public V computeIfAbsent(K key, Function<K,V> mappingFunction){
V value = this.get(key);
if(value == null){
value = mappingFunction.apply(key);
this.put(key, value);
}
return value;
}
类型K
和V
是通用的,分别代表key
value
的类型。如您所见,方法computeIfAbsent
返回value
,它位于地图中或稍后创建。然后可以调用setRecordXXX
方法。
(B)如果没有Record(RecordA,RecordB等)的显式类型检查,我怎样才能实现这一目标
为此你必须在RecordHolder中创建一个方法,它使用if-elseif-else-statement
来确定应该设置什么记录。如下所示:
public void setRecordXXX(Record record){
if(record instanceof RecordA){
setRecordA((RecordA) record);
} else if(record instanceof RecordB){
setRecordB((RecordB) record);
} else if(...){
// other records
} else {
// throw when unknown record implementation
throw new UnsupportedOperation("RecordType not supported: " + record);
}
}