集合内对象属性重复校验
使用范围
适用于集合内对象排重,如:excel导入,只要满足某些属性一样,则认为数据重复和其他场景。
代码实现
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.apache.commons.lang3.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
public class ListTool {
private static final String FH = ";";
private static final String SPERATOR = "\r\n";
/**
* 对象比较:此方法默认,可按照自己的业务改造
* @param <T>
* @param obj
* @param other
* @param fields 要比较的属性
* @return
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static <T> String compareObj(T obj, T other, Set<Field> fields) throws Exception {
StringBuilder result = null;
Object v1 = null;
Object v2 = null;
//全部相同才认为两条数据重复
boolean wholeSame = true;
for (Field field : fields) {
field.setAccessible(true);
v1 = field.get(obj);
v2 = field.get(other);
if(v1 != null && v2 != null) {
if(v1.toString().equalsIgnoreCase(v2.toString())) {
if(result == null) {
result = new StringBuilder();
}
result.append(v1.toString()).append(FH);
}else {
//有一个不一样则认为不重复
wholeSame = false;
break;
}
}
}
return !wholeSame ? null : result.toString();
}
/**
* 对象集合重复校验
* @param <T>
* @param list
* @param fieldNames
* @return
* @throws Exception
*/
public static <T> String duplicate(List<T> list, Set<String> fieldNames) throws Exception {
if(list == null || fieldNames == null) {
throw new Exception("params is null......");
}
if(list.isEmpty() || fieldNames.isEmpty()) {
throw new Exception("params is null......");
}
Class<? extends Object> clazz = list.get(0).getClass();
Set<Field> fields = new HashSet<Field>(fieldNames.size());
for (String name : fieldNames) {
fields.add(clazz.getDeclaredField(name));
}
//只与后面的比较
String result = null;
List<Integer> index = null;
Map<Integer, String> resultCache = new HashMap<Integer, String>();
//记录互相重复的下标,用于良好输出,+1遵循人眼习惯
Map<Integer, List<Integer>> indexs = new TreeMap<Integer, List<Integer>>();
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
result = compareObj(list.get(i), list.get(j), fields);
if(StringUtils.isNotEmpty(result)) {
resultCache.put(i+1, result);
index = indexs.get(i+1);
if(index == null) {
index = new ArrayList<Integer>();
}
index.add(j+1);
indexs.put(i+1, index);
}
}
}
//下标合并,如:1:2,8,9 2:8,9 3:4 8:9 --> 1:2,8,9 3:4
combine(indexs);
if(!indexs.isEmpty()) {
StringBuilder sb = new StringBuilder();
List<Integer> value = null;
for (Entry<Integer, List<Integer>> entry : indexs.entrySet()) {
value = entry.getValue();
value.add(entry.getKey());
Collections.sort(value);
sb.append("第"+value.toString()+"条数据重复,重复的数据:【"+resultCache.get(entry.getKey())+"】").append(SPERATOR);
}
return sb.toString();
}
return null;
}
/**
* 结果合并
* @param <T>
* @param map
*/
private static <T> void combine(Map<T, List<T>> map) {
Map<T, List<T>> nmap = new TreeMap<T, List<T>>();
nmap.putAll(map);
Iterator<Entry<T, List<T>>> iterator = nmap.entrySet().iterator();
Entry<T, List<T>> entry = null;
while(iterator.hasNext()) {
entry = iterator.next();
for (T key : entry.getValue()) {
if(nmap.containsKey(key)) {
map.remove(key);
}
}
}
}
}
@Data
@AllArgsConstructor
class Demo{
private Integer id;
private String name;
private Date birthday;
}
运行结果
public static void main(String[] args) throws Exception {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
List<Demo> list = new ArrayList<Demo>();
Demo d1 = new Demo(1, "张三", format.parse("1992-01-01 00:00:00"));
Demo d2 = new Demo(1, "张三", format.parse("1992-01-01 00:00:00"));
Demo d3 = new Demo(1, "李四", format.parse("1992-01-01 00:00:00"));
Demo d4 = new Demo(1, "李四", format.parse("1992-01-01 00:00:00"));
Demo d5 = new Demo(1, "王五", format.parse("1992-01-01 00:00:00"));
Demo d6 = new Demo(1, "赵六", format.parse("1992-01-02 00:00:00"));
Demo d7 = new Demo(1, "周七", format.parse("1992-01-01 00:00:00"));
Demo d8 = new Demo(1, "张三", format.parse("1992-01-01 00:00:00"));
Demo d9 = new Demo(1, "张三", format.parse("1992-01-01 00:00:00"));
list.add(d1);
list.add(d2);
list.add(d3);
list.add(d4);
list.add(d5);
list.add(d6);
list.add(d7);
list.add(d8);
list.add(d9);
Set<String> set = new HashSet<String>();
set.add("name");
set.add("birthday");
String result = duplicate(list, set);
System.out.println(result);
}
结果如下:
第[1, 2, 8, 9]条数据重复,重复的数据:【Wed Jan 01 00:00:00 CST 1992;张三;】
第[3, 4]条数据重复,重复的数据:【Wed Jan 01 00:00:00 CST 1992;李四;】
符合期望值。