import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Slf4j
public class CompareListUtil {
/**
* 差集key-add
*/
public static String DIFFERENCE = "difference_add";
/**
* 交集key-update
*/
public static String INTERSECTION = "intersection_update";
/**
* 补集key-delete
*/
public static String COMPLEMENT = "complement_delete";
/**
* 根据某个字段对比两个集合
*
* @param oldList 旧的集合
* @param newList 新的集合
* @param fieldName 需要对比的字段名称
* @return 差集key-add 交集key-update 补集key-delete
* @throws
*/
public static <T> Map<String, List<T>> compareList(List<T> oldList, List<T> newList, String fieldName) throws IllegalAccessException {
if (StringUtils.isBlank(fieldName)) {
throw new RuntimeException("\n对比字段不能为空");
}
// 空集合
List<T> emptyList = Lists.newArrayList();
List<T> differenceList = Lists.newArrayList();
List<T> intersectionList = Lists.newArrayList();
List<T> complementList = Lists.newArrayList();
Map<String, List<T>> resultMap = Maps.newHashMap();
if (CollectionUtils.isEmpty(oldList)) {
resultMap.put(DIFFERENCE, newList);
resultMap.put(INTERSECTION, emptyList);
resultMap.put(COMPLEMENT, emptyList);
return resultMap;
}
if (CollectionUtils.isEmpty(newList)) {
resultMap.put(DIFFERENCE, emptyList);
resultMap.put(DIFFERENCE, emptyList);
resultMap.put(COMPLEMENT, oldList);
return resultMap;
}
Set<Object> existSet = Sets.newHashSet();
for (T old : oldList) {
Object fieldValue = getFieldValue(old, fieldName);
existSet.add(fieldValue);
}
Set<Object> newSet = Sets.newHashSet();
for (T newObj : newList) {
Object fieldValue = getFieldValue(newObj, fieldName);
newSet.add(fieldValue);
}
for (T newObj : newList) {
Object fieldValueNew = getFieldValue(newObj, fieldName);
if (existSet.contains(fieldValueNew)) {
intersectionList.add(newObj);
} else {
differenceList.add(newObj);
}
}
for (T old : oldList) {
Object fieldValueNew = getFieldValue(old, fieldName);
if (!newSet.contains(fieldValueNew)) {
complementList.add(old);
}
}
resultMap.put(DIFFERENCE, differenceList);
resultMap.put(INTERSECTION, intersectionList);
resultMap.put(COMPLEMENT, complementList);
return resultMap;
}
/**
* 获取元素T中的字段值
*
* @param t 元素
* @param fieldName 字段名称
* @return
* @throws IllegalAccessException
*/
private static <T> Object getFieldValue(T t, String fieldName) throws IllegalAccessException {
Field targetField = Arrays.stream(t.getClass().getDeclaredFields())
.filter(field -> field.getName().equals(fieldName)).collect(Collectors.toList()).get(0);
targetField.setAccessible(true);
return targetField.get(t);
}
public static void main(String[] args) throws IllegalAccessException {
List<User> usersOld = Lists.newArrayList();
usersOld.add(new User(1L, "1"));
usersOld.add(new User(2L, "1"));
usersOld.add(new User(3L, "1"));
usersOld.add(new User(4L, "1"));
List<User> usersNew = Lists.newArrayList();
usersNew.add(new User(1L, "1"));
usersNew.add(new User(2L, "1"));
// usersNew.add(new User(3L, "1"));
usersNew.add(new User(4L, "1"));
usersNew.add(new User(5L, "1"));
Map<String, List<User>> maps = compareList(usersOld, usersNew, "userId");
maps.forEach((k, v) -> {
log.info("\n {} : {}", k, JSONObject.toJSONString(v));
});
}
}
@Data
@AllArgsConstructor
class User {
private Long userId;
private String userName;
}
intersection_update : [{"userId":1,"userName":"1"},{"userId":2,"userName":"1"},{"userId":4,"userName":"1"}]
19:51:18.653 [main] INFO com.enterprise.common.util.tool.CompareListUtil -
difference_add : [{"userId":5,"userName":"1"}]
19:51:18.653 [main] INFO com.enterprise.common.util.tool.CompareListUtil -
complement_delete : [{"userId":3,"userName":"1"}]
JDK8-交集-差集
// 交集
List<User> intersectA = usersOld
.stream() //获取第一个集合的Stream1
.filter( //取出Stream1中符合条件的元素组成新的Stream2,lambda表达式1返回值为true时为符合条件
a -> //lambda表达式1,a为lambda表达式1的参数,是Stream1中的每个元素
usersNew.stream() //获取第二个集合的Stream3
.map(User::getUserId) //将第二个集合每个元素的id属性取出来,映射成新的一个Stream4
.anyMatch( //返回值(boolean):Stream4中是否至少有一个元素使lambda表达式2返回值为true
id -> //lambda表达式2,id为lambda表达式2的参数,是Stream4中的每个元素
Objects.equals(a.getUserId(), id) //判断id的值是否相等
)
)
.collect(Collectors.toList()); //将Stream2转换为List
log.info("\nintersectA {}", JSONObject.toJSONString(intersectA));
// 差集
List<User> differenceB = usersNew.stream().filter(b -> usersOld.stream().map(User::getUserId).noneMatch(id ->
Objects.equals(b.getUserId(), id))).collect(Collectors.toList());
log.info("\ndifference {}", JSONObject.toJSONString(differenceB));