#java #if-statement #java-stream #filtering
Вопрос:
private static CodeList prepareChangeObject(CodeList codeList, CodeList existingCodeList, boolean dataExists)
throws EntityValidationException {
CodeList UpdatedCodeList = new CodeList();
BeanUtils.copyProperties(codeList, UpdatedCodeList);
Set<CodeListData> updatedDataList =UpdatedCodeList.getData().stream().collect(Collectors.toSet());
updatedDataList.addAll(existingCodeList.getData());
List<CodeListData> finalData = updatedDataList.stream().collect(
collectingAndThen(toCollection(() -> new TreeSet<>(comparing(CodeListData::getKey))), ArrayList::new));
finalData = finalData.stream().filter(data -> {
if (data.getOperation() == null)
data.setOperation(MetaConstants.OPERATION_ADD);
if (null != data.getOperation()) {
if (data.getOperation().equals(MetaConstants.OPERATION_DELETE) amp;amp; dataExists)
exceptionMessagesList.add(
new ExceptionMessage("foundation.OperationNotAllowed", new String[] { data.getKey() }));
if (data.getOperation().equals(MetaConstants.OPERATION_DELETE) amp;amp; !dataExists)
return false;
if (data.getOperation().equals(MetaConstants.OPERATION_ADD))
return true;
}
return false;
}).collect(Collectors.toList());
UpdatedCodeList.setData(finalData);
if(!CollectionUtils.isEmpty(exceptionMessagesList))
throw new EntityValidationException(HTTPClientError.BAD_REQUEST, exceptionMessagesList);
return UpdatedCodeList;
}
1.Описанный выше метод должен возвращать объект изменения на основе указанной операции.
public static void main(String[] args) throws JsonMappingException, JsonProcessingException, EntityValidationException {
String jsonPost = "{n"
" "id": "temperature101",n"
" "descriptions": [n"
" {n"
" "languageCode": "en",n"
" "description": "description",n"
" "longDescription": "long description"n"
" },n"
" {n"
" "languageCode": "de",n"
" "description": "description",n"
" "longDescription": "long description"n"
" }n"
" ],n"
" "dataType": "String",n"
" "data": [n"
" {n"
" "key": "val1",n"
" "value": "High"n"
" },n"
" {n"
" "key": "val4",n"
" "value": "Medium"n"
" },n"
" {n"
" "key": "val3",n"
" "value": "Low"n"
" }n"
" ]n"
"}";
String jsonPatch = "{n"
" "id": "temperature101",n"
" "descriptions": [n"
" {n"
" "languageCode": "en",n"
" "description": "description1",n"
" "longDescription": "long description1"n"
" },n"
" {n"
" "languageCode": "de",n"
" "description": "description1",n"
" "longDescription": "long description1"n"
" }n"
" ],n"
" "dataType": "String",n"
" "data": [n"
" {n"
" "key": "val1",n"
" "value": "High",n"
" "operation": "DELETE"n"
"n"
" },n"
" {n"
" "key": "val4",n"
" "value": "Medium",n"
" "operation": "DELETE"n"
" }n"
" ]n"
"}";
ObjectMapper mapper = new ObjectMapper();
CodeList ExistingodeList = mapper.readValue(jsonPost, CodeList.class);
CodeList currentCodeList = mapper.readValue(jsonPatch, CodeList.class);
CodeList upDatetedCodeList = prepareChangeObject(currentCodeList, ExistingodeList, false);
Gson gson = new Gson();
System.out.println(upDatetedCodeList.toString());
System.out.println(gson.toJson(upDatetedCodeList));
}
- приведенный выше основной метод проверки кода
@Data
public class CodeListData {
@Column("ID")
@JsonIgnore
private String id;
@Column("KEY")
private String key;
@Column("VALUE")
private String value;
@Column("ETAG")
@JsonIgnore
private String etag;
@JsonIgnore
@Column("VERSION")
@Version
private Long version;
@Transient
@JsonProperty(access = Access.WRITE_ONLY)
private String operation;
}
- Pojo for reference
@Data
public class CodeList implements Persistable<String>{
@NotNull
@Id
@Column("ID")
private String id;
@MappedCollection(idColumn = "ID", keyColumn = "ID_SEQ")
private List<CodeListDescriptions> descriptions = new ArrayList<>();
@Column("DATA_TYPE")
private String dataType;
@Column("LENGTH")
private String length;
@MappedCollection(idColumn = "ID", keyColumn = "ID_SEQ")
private List<CodeListData> data = new ArrayList<CodeListData>();
@JsonIgnore
@Column("VERSION")
private Long version;
@Column("ETAG")
@JsonIgnore
private String etag;
@Transient
@JsonIgnore
@Setter
private boolean isInsert;
@JsonIgnore
public boolean isNew() {
return isInsert;
}
}
4.pojo из списка кодов
@Data
public class CodeListDescriptions{
@Column("ISO")
public String languageCode;
@Column("DESCRIPTION")
public String description;
@Column("LONG_DESCRIPTION")
public String longDescription;
@Column("ID")
@JsonIgnore
private String id;
}
5.конечный результат, необходимый только "val3"
для того, чтобы присутствовать. Предполагается, что метод удаляет или добавляет на основе операций DELETE
или ADD
. Проблема в том, что val4 все еще находится в выводе, потому что при создании окончательных данных он предпочитает хранить "val4"
данные из существующих, которые не содержат никаких операций. Конечный вывод должен содержать добавленные значения и значения, не указанные в полезной нагрузке, но существующие в первом.
Ответ №1:
он предпочитает хранить val4 из существующих данных, которые не содержат никаких операций
вы выполняете add
операцию по умолчанию с помощью этого кода, поэтому независимо от того, существует операция или нет, вы явно задаете ее
if (data.getOperation() == null)
data.setOperation(MetaConstants.OPERATION_ADD);
Затем вы проверяете это, как
if (null != data.getOperation()) { // this is always true, because you use the default one line before
...
if (data.getOperation().equals(MetaConstants.OPERATION_ADD))
return true;
}
так что в конце концов финал
return false;
никогда не будет достигнуто.
Комментарии:
1. «не используйте равенства для перечислений», похоже, это строки, для которых
equals
правильный выбор.2. Ах, вы правы, наверное, я пропустил это при чтении и просто предположил, что это зависит от того, как я буду с этим справляться. Отредактированный
Ответ №2:
Вы создаете a Set<CodeListData>
как из существующего, так и из обновленного набора данных. CodeListData
определяет его equals
и hashCode
методы во всех полях. Обратите внимание, что Ломбок игнорирует transient
поля, но они отличаются от полей с аннотациями @Transient
. Таким образом, у вас есть val4
два раза в Set
один раз с DELETE
операцией и один раз без какой-либо операции. Тот, у DELETE
которого есть, будет отфильтрован, но тот, у которого нет операции, будет по умолчанию ADD
и останется в SET
.
Примечание: Я считаю неудачным называть переменную типа Set
чем-либо, что заканчивается List
.