集合内对象属性重复校验

集合内对象属性重复校验

使用范围

适用于集合内对象排重,如: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;李四;】
符合期望值。

上一篇:Rancher2.x部署K8 Can not find RKE state file: open /var/lib/rancher/management-state/rke/rke-32633077


下一篇:CentOS7 删除virbr0虚拟网卡