先上代碼:
User對(duì)象
public class UserDTO {
private int userId;
private String userName;
private int orgId;
private OrgDTO orgDTO;
}
Org對(duì)象
public Class OrgDTO {
private int orgId;
private String orgName;
}
工具類方法
public static <S, K, T> void oneToOne(List<S> sourceList, List<T> detailList, SafeFunction<S, K> sourceKey, SafeFunction<T, K> detailKey) {
Map<K, T> detailMap = detailList.stream().collect(Collectors.toMap(detailKey, Function.identity()));
for (S s : sourceList) {
K key = sourceKey.apply(s);
T detail = detailMap.get(key);
if (detail != null) {
// TODO How to call s.setDetail() ?
}
}
}
參數(shù)說明:
sourceList: 待填充數(shù)組
detailList: 填充物數(shù)組
sourceKey: sourceList與detailList的關(guān)聯(lián)鍵
detailKey: detailList的關(guān)聯(lián)鍵轉(zhuǎn)換函數(shù)
好吧,以上參數(shù)說明比較難懂(我也不知道要怎么描述)……
舉個(gè)場(chǎng)景例子:有一個(gè)UserDTO和OrgDTO,假設(shè)他們?cè)跀?shù)據(jù)表的關(guān)系是1對(duì)1,很多時(shí)候我們需要根據(jù)UserDTO里面的orgId查詢對(duì)應(yīng)的OrgDTO,然后根據(jù)orgId把OrgDTO填充進(jìn)UserDTO里面。
傳統(tǒng)的代碼寫法如下:
public void fillOrgDTO(List<UserDTO> userDTOs) {
Set<Integer> orgIds = userDTOs.stream().map(UserDTO::getOrgId).collect(Collectors.toSet());
List<OrgDTO> orgDTOs = orgDAO.findByIds(orgIds);
Map<Integer, OrgDTO> orgId2OrgDTOMap = orgDTOs.stream().collect(Collectors.toMap(OrgDTO::getOrgId, Function.identity()));
for (UserDTO userDTO : userDTOs) {
Integer orgId = userDTO.getOrgId();
OrgDTO orgDTO = orgId2OrgDTOMap.get(orgId);
if (orgDTO != null) {
userDTO.setOrgDTO(orgDTO);
}
}
}
我的想法是,有沒有辦法把以上這段代碼抽象成一個(gè)通用的方法,這樣就不用每次都寫類似的代碼。
然后就試著寫出了oneToOne這個(gè)方法,不過去到TODO那里就不知道怎么寫了。
理論上用反射可以做到(需要變更方法簽名),但我不想用反射,因?yàn)椴徽搹男阅苓€是維護(hù)角度來看,反射都不是一個(gè)很好的選擇。
之前也了解過Java8的Consumer和BiConsumer,但試了一下好像也沒法實(shí)現(xiàn)我的需求,可能是我理解得不夠。
所以,在此提出這個(gè)問題,看看大家有沒有好的解決方案?
PS:方法簽名可以變更,代碼可任意修改,UserDTO、OrgDTO可以實(shí)現(xiàn)任意接口。
如何實(shí)現(xiàn)通用的對(duì)象填充方法
幕布斯6054654
2019-03-01 10:41:19