DiffType 枚举类中的抽象方法实现,需要枚举类中的每个对象都对其进行实现
public enum DiffType {
NONE,ADDED,REMOVED,MODIFIED;
public static boolean isModified(DiffType type){
return type!=null && type !=NONE;
}
public boolean isAdded() {
return this == ADDED;
}
public boolean isRemoved() {
return this == REMOVED;
}
public boolean isNone() {
return this == NONE;
}
}
静态变量可以用于引用所有对象的公共属性(对于每个对象不是唯一的)。
如果等于定义的元素,返回true
FieldDiff类
@Data
@Builder
public class FieldDiff {
private String fieldName;
private DiffType diffType;
private Object original;
private Object current;
@Builder.Default
private List<FieldDiff> fields = new ArrayList<>();
}
Default字段表示注解的字段必须要有初始化表达式,如果在构造期间未明确设置,则该表达式会被默认使用,创建一个ArrayList类型,创建一个属于FieldDiff类型的字段
originalRemovedField类
default List<FieldDiff> originalRemovedField(Map<String,T> originalMapById,
Map<String,T> currentMapById){
return originalMapById.entrySet()
.stream()
.filter(entry-> !currentMapById.containsKey(entry.getKey()))
.map(entry-> FieldDiff.builder()
.fieldName(entry.getKey())
.original(entry.getValue())
.diffType(DiffType.REMOVED)
.build())
.collect(Collectors.toList());
}
方法名称:初始化删除字段(它的类型为字段差异)-
T - Type(Java 类)
-
keySet返回此map中包含map的 Set 视图。 set由map支持,因此对map的更改会反映在set中,反之亦然。
-
返回此集合中元素的顺序流
-
返回由与给定谓词匹配的此流的元素组成的流。返回the new stream
-
如果currentMapById不包含此条目对应的键,返回false
-
返回由将给定函数应用于此流的元素的结果组成的流。返回符合FieldDiff类型的元素
-
Map.entrySet返回map的元素视图.得到entry的键作为字段名,entry的值作为初始值,找到符合差异类型中的remove进行构造
-
使用collect将构造好的元素按照遇到的顺序累积到list列表中
default Map<String, T> toMap(List<T> content, Function<T, String> idMapping) {
return content
.stream()
.collect(Collectors.toMap(idMapping, Function.identity(), (a, b) -> {
log.warn("Duplicate key, origin = {}, current = {}", a, b);
return a;
}));
}
-
默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。
-
返回此集合元素的顺序流
-
Function接收参数并且返回结果的函数,T表示函数输入的类型,R表示函数结果的类型,identity方法表示始终返回其输入参数的函数
-
->表示一个函数式接口,表示对两个相同操作数的操作,产生与操作数相同类型的结果
-
apply方法 将此函数应用于给定的参数
-
参数a和b在WARN级别中记录消息,复制键,起始值为空,当前值也为空
currentAddedField类
default List<FieldDiff> currentAddedField(Map<String, T> originalMapById,
Map<String, T> currentMapById) {
return currentMapById.entrySet()
.stream()
.filter(entry -> !originalMapById.containsKey(entry.getKey()))
.map(entry -> FieldDiff.builder()
.fieldName(entry.getKey())
.current(entry.getValue())
.diffType(DiffType.ADDED)
.build())
.collect(Collectors.toList());
}
- 默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。
- entrySet 返回此映射中包含的集合视图
- 返回此集合元素的顺序流
- 返回由与给定谓词匹配的此流的元素组成的流。返回the new stream ,判断originalMapById中是否包含与此条目对应的键
- R 新流的元素类型,map方法表示构造符合FieldDiff类型的元素的结果组成的流
- 找到与该条目对应的键作为字段名,与此条目对应的值作为当前值,判断它是不是枚举类DiffType下的ADDED方法,元素流构造完成
- 构造一个将输入元素累计到新列表中的收集器,使用collect方法将元素累计到这个list中
modifiedField类
default List<FieldDiff> modifiedField(Map<String,T> original,
Map<String,T> current){
ArrayList<FieldDiff> diff = new ArrayList<>();
original.entrySet()
.stream()
.filter(entry-> current.containsKey(entry.getKey()))
.forEach(entry->{
T originalValue = entry.getValue();
T currentValue = current.get(entry.getKey());
if (!Objects.equals(originalValue,currentValue)){
FieldDiff fieldDiff = FieldDiff.builder()
.fieldName(entry.getKey())
.original(originalValue)
.current(currentValue)
.diffType(DiffType.MODIFIED)
.build();
diff.add(fieldDiff);
}
});
return diff;
}
- 创建一个diff对象,存储FieldDiff类型的元素
- -> 谓词的输入类型
- 找到起始值的mapping所包含的Set视图,返回此集合元素的顺序流,filter表示返回与current对应的键
- 对此流的每个元素执行操作
- 条目的值作为起始值,条目的键的值映射作为当前值,如果起始值和当前值不相等,找到它们的字段差异值,将它加入到数组diff中用来返回
diffTableField类
default FieldDiff diffTableField(List<T> original,
List<T> current,
String fieldName,
Function<T, String> identity) {
Map<String, T> originalMap = toMap(original, identity);
Map<String, T> currentMap = toMap(current, identity);
List<FieldDiff> columnFieldDiffs = new ArrayList<>(32);
// removed
List<FieldDiff> removedFields = originalRemovedField(originalMap, currentMap);
columnFieldDiffs.addAll(removedFields);
// added
List<FieldDiff> addedFields = currentAddedField(originalMap, currentMap);
columnFieldDiffs.addAll(addedFields);
// modified
List<FieldDiff> modifiedFields = modifiedField(originalMap, currentMap);
columnFieldDiffs.addAll(modifiedFields);
return FieldDiff.builder()
.fieldName(fieldName)
.diffType(columnFieldDiffs.isEmpty() ? DiffType.NONE : DiffType.MODIFIED)
.fields(columnFieldDiffs)
.build();
}
- 创建一个属于FieldDiff类型的方法,输入参数为起始值,当前值,字段名称,Function中的T表示输入类型的参数,String表示输出类型的参数,identify作为特征值
- 将特征值加入到original和current中作为初始值映射和当前值映射的集合,创建一个容量为32,类型为字段之间的差异所组成的列表,名称为列字段差异。
- 使用起始删除字段和当前已添加字段方法分别对originalMap和currentMap进行操作,起始删除字段方法是找到与originalMap和currentMap中的不同的键,当前已添加字段方法是找到与originalMap和currentMap中的不同的键,构造出字段差异的类型并且将其加入到list中返回 。列的field差异列表分别加入已删除的字段名和已添加的字段名。
- 找到修改过的originalMap和currentMap的差异值,加入到列的field差异列表中,检查列差异列表是否为空,如果不为空的话,它为已经修改的标志,如果为空,则为null,返回一开始输入的字段名称作为列之间字段差异类型的集合来返回。