gpt4 book ai didi

java - 在 Java Map 中插入新元素或通过其键更新现有元素

转载 作者:行者123 更新时间:2023-12-02 01:00:26 24 4
gpt4 key购买 nike

业务请求是我构建一个 List<ResponsePOJO>来自List<RequestPOJO> 。这看起来很简单。
该请求实际上需要一些(更多)处理,这意味着我需要保存几个参数,然后针对每个元素向 CassandraMicroservice 发出请求,返回 List<CassandraPOJO> 。这个<List<CassandraPOJO>的每个元素有它自己的List<DataPOJO>需要属于 List<ResponsePOJO> 中某些特定特征所代表的类别。基本上适用于 List<RequestPOJO> 中的每个元素我正在构建一个 List<List<DataPOJO>>这需要处理。不幸的是,一切都陷入困境,我无法更改架构
简而言之,我的问题是我无法找到一个简单的 createOrUpdateMap 。我试图制作一个 updateOrCreate类型 BiFunction 。我认为做一些像 BiFunction、Map> 这样的事情就足够了(伪代码):

private BiFunction<ResponsePOJO, Map<Integer, ResponsePOJO>, Map<Integer, ResponsePOJO>> updateOrCreate(?*) {
return (newValue, currentResult) -> {
if (currentResult.contains(newValue))
currentResult.updateParams(newValue);
else
currentResult.put(newValue);
return currentResult;
};
}

?* 我注意到对 BiFunction 的调用是无参数的,它如何知道其参数是什么类型? (不是我的主要问题,但我认为我的问题的原因之一是缺乏真正理解 BiFunctionMap.compute )
(几乎)完整的代码片段是:

// the POJOs, using lombok (anotations skipped)  
public class RequestPOJO {
private Long id;
private Long idEntity;
private Long idInventory;
// some are omitted for brevity
}

@Builder(toBuilder = true)
public class ResponsePOJO {
private Integer id;
private Long noInventory;
private String nameSpecies;
private Double g1;
private Double g2;
private Double g3;
// some are omitted for brevity

public void updateParams(ResponsePOJO resp) {
// only these fields need updating, because of business logic
this.g1 += resp.getG1();
this.g2 += resp.getG2();
this.g3 += resp.getG3();
}
}

public class CassandraPOJO {
private Long id;
private List<DataPOJO> detailsDataPojo;
private Long noInventory;
// some are omitted for brevity
}


public class DataPOJO {
private Long idSpecies;
private Long idQualityClass;
private Double height;
private Double diameter;
private Double noCount;
// some are omitted for brevity
}

// the business logic
public List<ResponsePOJO> compute(List<RequestPOJO> requestPojoList, List<SpeciesPOJO>speciesList) {
List<ResponsePOJO> responseList = new ArrayList<>();
for (RequestPOJO requestPojo : requestPojoList) {
Long idEntity = requestPojo.getIdEntity();
Long noInventory = requestPojo.getIdInventory(); // yes I know this is wrong, stick to the question

List<CassandraPOJO> res = cassandraMicroservice.getByIdEntityFilteredByNoInventory(idEntity, noInventory);

res.stream().forEach(dar -> {
Map<Long, List<DataPOJO>> listDataPojoBySpeciesId =
dar.getDetailsDataPojo().stream().collect(
Collectors.groupingBy(DataPOJO::getIdSpecies, Collectors.toList())
);
responseList.addAll(
classifyDataPojo(listDataPojoBySpeciesId, speciesList, dar.getNoInventory())
);
});
}

Comparator<ResponsePOJO> compareResponsePojo = Comparator.comparing(ResponsePOJO::getNameSpecies);
return responseList.stream()
.sorted(compareResponsePojo).collect(Collectors.toList());
}

private List<ResponsePOJO> classifyDataPojo(Map<Long, List<DataPOJO>> listDataPojoBySpeciesId, List<SpeciesPOJO> speciesList, Long noInventory) {
Map<Integer, ResponsePOJO> result = new HashMap();
for (Long speciesId : listDataPojoBySpeciesId.keySet()) {
String nameSpecies = speciesList.stream().filter(s -> s.getIdSpecies() == speciesId).findFirst().get().getNameSpecies(); // it's guaranteed to be found
for (DataPOJO dataP : listDataPojoBySpeciesId.get(speciesId)) {
Double volumeUnit = getVolumeUnit(dataP);
Double equivalenceCoefficient = getEquivalentClass(dataP, speciesList);
CustomTypeEnum customType = getCustomType(speciesList, dataP.getDiameter, speciesId);
resp = ResponsePOJO.builder()
.noInventory(noInventory)
.nameSpecies(nameSpecies)
.build();
switch (customType) {
case G1:
resp.setG1(volumeUnit * equivalenceCoefficient * dataP.getNoCount());
break;
case G2:
resp.setG2(volumeUnit * equivalenceCoefficient * dataP.getNoCount());
break;
case G3:
resp.setG3(volumeUnit * equivalenceCoefficient * dataP.getNoCount());
break;
default:
break;
}
}
int diameter = ComputeUtil.getDiamenterClass(resp.getDiameter());
// doesn't compile, it says Wrong 2nd argument type. Found: BiFunction<ResponsePOJO, Map<Integer, ResponsePOJO>, Map<Integer,ResponsePOJO>> Required: BiFunction<? super Integer,? super ResponsePOJO,? extends ResponsePOJO>
result.compute(diameter, updateOrCreate());
// I have fiddled with reduce and merge but to no avail
// result.values().stream().reduce(new ArrayList<>(), updateOrCreate(), combiningFunction());
// result.merge(diameter, update())
}
return result.values().stream().collect(Collectors.toList());
}

我选择Map是因为我希望它尽可能快,这个方法compute(...)经常被调用,我不想每次需要更新时都搜索所有响应列表。我不愿意更改 POJO,尤其是 CassandraPOJODataPOJO .
正如您所看到的,这是经典 for 的混合体。和java8 stream 。我打算根据java8更改所有代码,但我花了相当多的时间来编写这段(复杂、难以理解、易于理解)代码。
我坚信有一个更简单的解决方案,但我自己无法解决。

最佳答案

在冗长的代码中,在我看来,您只是在寻找合并操作,例如:

result.merge(diameter, resp, (a, b) -> { 
a.updateParams(b);
return a;
});
return new ArrayList<>(result.values());

可以抽象为

private BiFunction<ResponsePOJO, ResponsePOJO, ResponsePOJO> mergeResponse() {
return (a, b) -> {
a.updateParams(b);
return a;
};
}

并进一步用作

result.merge(diameter, resp, mergeResponse());

关于java - 在 Java Map 中插入新元素或通过其键更新现有元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60723226/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com