Java list<T> 去重复 数据

昨天,做项目的时候遇到需要这样将list 分组的 功能,找百度,试了很多方法,一直没有好的方法,再说功能不够强大,只是单纯的一个两个字段group by。心烦,搞到也不想再找了,然后花了两三个小时,整合了一个  List<T>  的  group by 方法,提供了两个重载,一个是只group by,另一个可以count 合并列(Integer,Long,Double,Float)是相加,String 就拼接起来。废话少说,上代码。缺包的看   import    ,然后自己下载。

===========================我======是======分======割======线=========================================================

使用方法:

原list<T> lists :

[{"functiontype":23,"identifying":20,"remark":"分页大小10","systemid":0,"value":"10"},{"functiontype":23,"identifying":20,"remark":"分页大小20","systemid":0,"value":"20"},{"functiontype":23,"identifying":20,"remark":"分页大小30","systemid":0,"value":"30"},{"functiontype":23,"identifying":20,"remark":"分页大小40","systemid":0,"value":"40"},{"functiontype":23,"identifying":20,"remark":"分页大小50","systemid":0,"value":"50"},{"functiontype":24,"identifying":21,"remark":"预期5周","systemid":0,"value":"5"}]

===========================我======是======分======割======线=========================================================

调用只group by 方法:

List<SystemInstall> liSystemInstalls = systemListUtil.getListByGroup(
lists, 
new String[]{"Functiontype","Identifying"});

 数据如下:

[{"functiontype":23,"identifying":20,"remark":"分页大小10","systemid":0,"value":"10"},{"functiontype":24,"identifying":21,"remark":"预期5周","systemid":0,"value":"5"}]

===========================我======是======分======割======线=========================================================

需要合并count的:

List<SystemInstall> liSystemInstalls1 = systemListUtil.getListByGroup(SystemInstall.class,
lists, 
new String[]{"Functiontype","Identifying"},new String[]{"Functiontype","Identifying","Value"});

得到数据如下:

[{"functiontype":115,"identifying":100,"remark":"分页大小10","systemid":0,"value":"50,40,30,20,10"},{"functiontype":24,"identifying":21,"remark":"预期5周","systemid":0,"value":"5"}]

===========================我======是======分======割======线=========================================================

其中参数为  string[] 的都是对应字段的  get   、set   方法名字,但是不需要前面的’get‘和‘set’ !!!

代码:

package com.zsm.core.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

@SuppressWarnings("unchecked")
public class ListUtil<T extends Serializable> {
	
	/** 
	* 获得对象属性的值 get 方法
	*/  
	private static Object invokeMethod(Object owner, String methodName) throws Exception { 
		Class ownerClass = owner.getClass();
		Method method = null;  
		try {
			method = ownerClass.getMethod(methodName); 
		} catch (SecurityException e) { } 
		catch (NoSuchMethodException e) {
			return " can't find 'get" + methodName + "' method";  
		}  
		return method.invoke(owner);  
	}  
  
  /**
   * @param MethodName 
   * @param o           调用此方法的对象
   * @param paras       调用的这个方法的参数参数列表
   */
	private void invokeMethod(String MethodName,Object o,Object []paras){
       Class c[]=null;
       if(paras!=null){//存在
           int len=paras.length;
           c = new Class[len];
           for(int i=0;i<len;++i){
               c[i]=paras[i].getClass();
           }
       }
      try {
          Method method=o.getClass().getDeclaredMethod(MethodName,c);
          try {
              method.invoke(o,paras);//调用o对象的方法
          } catch (IllegalAccessException ex) {
              Logger.getLogger(ListUtil.class.getName()).log(Level.SEVERE, null, ex);
          } catch (IllegalArgumentException ex) {
              Logger.getLogger(ListUtil.class.getName()).log(Level.SEVERE, null, ex);
          } catch (InvocationTargetException ex) {
              Logger.getLogger(ListUtil.class.getName()).log(Level.SEVERE, null, ex);
          }
      } catch (NoSuchMethodException ex) {
          Logger.getLogger(ListUtil.class.getName()).log(Level.SEVERE, null, ex);
      } catch (SecurityException ex) {
          Logger.getLogger(ListUtil.class.getName()).log(Level.SEVERE, null, ex);
      }
	}

   /**
    * 该类 使用的  set 方法
    */
	private void setMethod(String MethodName,Object o,Object []paras){
		invokeMethod("set" + MethodName,o,paras);
	}

   /**
    * 该类 使用的  get 方法
    * @throws Exception 
    */
	private Object getMethod(Object owner, String methodName) throws Exception{
		return invokeMethod(owner,"get" + methodName);
	}
	
  	/**
  	 * List<T> group by 分组
  	 * @list 分组 list 
  	 * @groupMethodNames 需要分组的 字段的 get 方法名字
  	 * */
	public List<T> getListByGroup(List<T> list,String[] groupMethodNames) throws Exception {
        List<T> result = new ArrayList<T>();
		for (T bean : list) {
			if (!iscontains(bean,result,groupMethodNames)) {
                result.add(bean);
            }
		}
        return result;
    }
	
	/**
  	 * List<T> group by 分组
  	 * @class1 需要分组的对象 的 class
  	 * @list 分组 list 
  	 * @groupMethodNames 需要分组的 字段的 get 方法名字(不需要‘get’)
  	 * @countMethodNames 需要分组后合并的 set 方法名字(不需要‘set’)
	 * @return boolean
  	 * */
	public List<T> getListByGroup(Class<T> class1,List<T> list,String[] groupMethodNames,String[] countMethodNames) throws Exception {
		List<T> originalList = new ArrayList<T>();
        List<T> result = new ArrayList<T>();
		Object objcount;
		Object objoriginal;
		T originalT;
		for (T bean : list) {
			if (iscontains(bean,originalList,groupMethodNames)) {
				int index = isindexOf(bean,originalList,groupMethodNames);
				for (int i = 0; i < countMethodNames.length; i++) {
					objcount = getMethod(bean,countMethodNames[i]);//获取  需要合并的 数据
					objoriginal = getMethod(result.get(index),countMethodNames[i]);//获取  原来 需要合并的 数据
					if (objcount instanceof Integer || objcount instanceof Double || objcount instanceof Float || objcount instanceof Long) {
						objcount = ((Integer) objcount).intValue()+((Integer) objoriginal).intValue();
					} else if (objcount instanceof String) {
						objcount = ((String) objcount)+","+((String) objoriginal);
					}
					//调用 set 方法 累计 count
					setMethod(countMethodNames[i], result.get(index), new Object[]{objcount});
				}
            } else {
            	originalT = myclone(bean);
            	originalList.add(originalT);
                result.add(bean);
            }
		}
        return result;
    }
	
	/**
	 * 判断是list 是否存在 与  obj  相同的 对象
	 * @obj 对比对象
	 * @elementData 判断的 list 对象
	 * @groupMethodNames group by 分组字段的 get 方法名(不需要‘get’)
	 * @return boolean
	 * */
	private boolean iscontains(Object obj,List<T> elementData,String[] groupMethodNames) throws Exception {
	    return isindexOf(obj, elementData,groupMethodNames) >= 0;
    }
	
	/**
	 * 获取 相同值的 第一个 index
	 * @obj 对比对象
	 * @elementData 判断的 list 对象
	 * @groupMethodNames group by 分组字段的 get 方法名(不需要‘get’)
	 * @return int
	 * */
	private int isindexOf(Object obj,List<T> elementData,String[] groupMethodNames) throws Exception {
	    if (obj == null) {
	        for (int i = 0; i < elementData.size(); i++)
	        if (elementData.get(i)==null)
	            return i;
	    } else {
	        for (int i = 0; i < elementData.size(); i++)
	        if (isequals(obj,elementData.get(i),groupMethodNames))
	            return i;
	    }
	    return -1;
    }
	
	/**
	 * 判断 两个值 相等
	 * @obj1 对比对象1
	 * @obj2 对比对象2
	 * @groupMethodNames group by 分组字段的 get 方法名(不需要‘get’)
	 * @return boolean
	 * */
	private boolean isequals(Object obj1,Object obj2,String[] groupMethodNames) throws Exception {
		String str1 = "";
		String str2 = "";
		for (int i = 0; i < groupMethodNames.length; i++) {
			str1 = getMethod(obj1,groupMethodNames[i]).toString();
			str2 = getMethod(obj2,groupMethodNames[i]).toString();
			if(!str1.equals(str2)){
				return false;
			}
		}
        return true;
    }
	
	/**
	 * Discription:[深度复制方法,需要对象及对象所有的对象属性都实现序列化] 
	 * @c 需要复制的对象
	 * @return 复制后的对象
	 * */
	public T myclone(T c) {
		T outer = null;
		try { // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(baos);
			oos.writeObject(c);
			// 将流序列化成对象
			ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
			ObjectInputStream ois = new ObjectInputStream(bais);
			outer = (T) ois.readObject();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return outer;
	}
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
jdk8 优化以下代码: for (DqExecuteResult dqExecuteResult : dqExecuteResults) { String errorOutputPath = dqExecuteResult.getErrorOutputPath(); Path path = new Path(errorOutputPath); R<List<String>> getFileResult = resourceClient.getFilesAtPath(path.toUri().getPath()); if (null != getFileResult && getFileResult.isSuccess()) { for (String fullPath : getFileResult.getData()) { R<List<String>> previewResult = resourceClient.viewFileByPath(new Path(fullPath).toUri().getPath(), query.getCurrent(), query.getSize(), "\n"); if (null != previewResult && previewResult.isSuccess()) { if("原始库".equals(datasourceName)){ Long datasourceId = iDataSourceClient.queryRawDataSource().getId(); List<MetaColumn> tableColumns = iDataSourceMetaClient.getTableColumns(datasourceId, tableName); for (MetaColumn metaColumn : tableColumns){ headers.add(metaColumn.getColumnName()); } } else if("标准库".equals(datasourceName)){ Long datasourceId = iDataSourceClient.queryModelDataSource().getId(); List<MetaColumn> tableColumns = iDataSourceMetaClient.getTableColumns(datasourceId, tableName); for (MetaColumn metaColumn : tableColumns){ headers.add(metaColumn.getColumnName()); } } int headerSize = headers.size(); List<String> datas = previewResult.getData(); StringBuilder contextBuilder = new StringBuilder(); for(String data : datas){ contextBuilder.append(data.replaceAll("[\r\n\t]", " ")); contextBuilder.append("\n"); } StringReader reader = new StringReader(contextBuilder.toString()); Iterable<CSVRecord> records = CSVFormat.DEFAULT.parse(reader); for (CSVRecord record : records) { if (record.size() == headerSize){ List<String> content = new ArrayList<>(); for (String column : record) { content.add(column); } contents.add(content); } } } } } }
06-02
可以通过以下方式对代码进行优化: 1. 首先,可以将重复的代码段提取为一个方法,以便在两个 if 块中重用。例如: ``` private List<MetaColumn> getTableColumns(String datasourceName, String tableName) { Long datasourceId; if ("原始库".equals(datasourceName)) { datasourceId = iDataSourceClient.queryRawDataSource().getId(); } else if ("标准库".equals(datasourceName)) { datasourceId = iDataSourceClient.queryModelDataSource().getId(); } return iDataSourceMetaClient.getTableColumns(datasourceId, tableName); } ``` 2. 其次,可以将 CSV 解析和数据处理逻辑提取为一个方法: ``` private List<List<String>> processCSVData(List<String> datas, List<String> headers) throws IOException { int headerSize = headers.size(); List<List<String>> contents = new ArrayList<>(); StringBuilder contextBuilder = new StringBuilder(); for (String data : datas) { contextBuilder.append(data.replaceAll("[\r\n\t]", " ")); contextBuilder.append("\n"); } StringReader reader = new StringReader(contextBuilder.toString()); Iterable<CSVRecord> records = CSVFormat.DEFAULT.parse(reader); for (CSVRecord record : records) { if (record.size() == headerSize) { List<String> content = new ArrayList<>(); for (String column : record) { content.add(column); } contents.add(content); } } return contents; } ``` 3. 然后,可以使用 Java 8 的 Lambda 表达式和方法引用来简化代码。例如: ``` dqExecuteResults.stream() .map(DqExecuteResult::getErrorOutputPath) .map(Path::new) .map(Path::toUri) .map(URI::getPath) .map(resourceClient::getFilesAtPath) .filter(Objects::nonNull) .filter(R::isSuccess) .flatMap(result -> result.getData().stream()) .map(Path::new) .map(Path::toUri) .map(URI::getPath) .map(fullPath -> resourceClient.viewFileByPath(fullPath, query.getCurrent(), query.getSize(), "\n")) .filter(Objects::nonNull) .filter(R::isSuccess) .flatMap(result -> { List<String> datas = result.getData(); List<String> headers = new ArrayList<>(); if ("原始库".equals(datasourceName) || "标准库".equals(datasourceName)) { getTableColumns(datasourceName, tableName).stream() .map(MetaColumn::getColumnName) .forEach(headers::add); } try { return processCSVData(datas, headers).stream(); } catch (IOException e) { e.printStackTrace(); return Stream.empty(); } }) .forEach(contents::add); ``` 这段代码使用了 stream 操作来简化循环和条件语句,使用方法引用、Lambda 表达式和函数式接口来写出更简洁的代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值