集合内对象属性重复校验

集合内对象属性重复校验

使用范围

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,对象及其属性的非空校验非常重要,因为如果对象属性为空,可能会导致程序崩溃或产生不可预料的错误。 以下是一些常见的Java对象及其属性的非空校验方法: 1. 对象非空校验 在判断一个对象是否为空时,可以使用以下方法: ```java if (object == null) { // 对象为空 } else { // 对象不为空 } ``` 2. 字符串非空校验 在判断一个字符串是否为空时,可以使用以下方法: ```java if (str == null || str.length() == 0) { // 字符串为空 } else { // 字符串不为空 } ``` 或者使用StringUtils类中的方法: ```java if (StringUtils.isEmpty(str)) { // 字符串为空 } else { // 字符串不为空 } ``` 3. 数组非空校验 在判断一个数组是否为空时,可以使用以下方法: ```java if (array == null || array.length == 0) { // 数组为空 } else { // 数组不为空 } ``` 4. 集合非空校验 在判断一个集合是否为空时,可以使用以下方法: ```java if (collection == null || collection.isEmpty()) { // 集合为空 } else { // 集合不为空 } ``` 5. 对象属性非空校验 在判断一个对象属性是否为空时,可以使用以下方法: ```java if (object.getProperty() == null) { // 对象属性为空 } else { // 对象属性不为空 } ``` 或者使用Objects类中的方法: ```java if (Objects.isNull(object.getProperty())) { // 对象属性为空 } else { // 对象属性不为空 } ``` 以上是一些常见的Java对象及其属性的非空校验方法,需要根据具体情况选择合适的方法进行校验

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值