当前位置: 代码网 > it编程>编程语言>Java > Java反射实现多属性去重与分组功能

Java反射实现多属性去重与分组功能

2025年06月08日 Java 我要评论
一、开发环境与基础组件准备1.环境配置:ide:intellij ideajdk 版本:1.8核心组件:自定义工具类库(common模块)2.代码结构说明:com.pearl.common/├─ en

一、开发环境与基础组件准备

1.环境配置:

  • ide:intellij idea
  • jdk 版本:1.8
  • 核心组件:自定义工具类库(common模块)

2. 代码结构说明:

com.pearl.common/
├─ entity/        # 实体类模块
│  └─ user.java   # 用户实体定义
└─ spring/        # 工具类模块
   └─ beanutils.java # 反射工具类

二、基础反射工具:beanutils 的设计与实现

1. 用户实体类:user.java

package com.pearl.common.entity;

/**
 * 业务实体:用户信息模型
 * @author yyb
 * @since 2025/05/06
 * @apinote 包含基础属性及java bean规范的访问器方法
 */
public class user {

    /**
     * id
     */
    private string id;
    /**
     * 姓名
     */
    private string name;
    /**
     * 年龄
     */
    private integer age;

    public string getid() {
        return id;
    }

    public void setid(string id) {
        this.id = id;
    }

    public string getname() {
        return name;
    }

    public void setname(string name) {
        this.name = name;
    }

    public integer getage() {
        return age;
    }

    public void setage(integer age) {
        this.age = age;
    }

    public user(string id, string name, integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @override
    public string tostring() {
        return "user{" +
                "id='" + id + ''' +
                ", name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

2. 反射工具类:beanutils 的核心能力

package com.pearl.common.spring;

import com.pearl.common.entity.user;
import java.lang.reflect.invocationtargetexception;

/**
 * bean对象反射操作工具类
 * @author yyb
 * @since 2025/05/06
 * @apinote 提供基于方法名反射的属性值获取能力
 */
public class beanutils {
    private static final string get_prefix = "get";  // getter方法前缀
    private static final string set_prefix = "set";  // setter方法前缀

    /**
     * 通过反射调用对象的getter方法获取属性值
     * @param target 对象实例
     * @param fieldname 目标字段名(驼峰命名,如"username")
     * @param <t> 泛型约束(需为java bean规范类)
     * @return 字段值字符串表示,异常时返回空字符串
     * @throws securityexception 反射权限异常
     * @example 获取user对象的name属性:getmethodvalue(user, "name")
     */
    public static <t> string getmethodvalue(t target, string fieldname) {
        string methodname = get_prefix + 
            fieldname.substring(0, 1).touppercase() + 
            fieldname.substring(1);  // 拼接方法名(如"getname")
        
        try {
            // 反射调用方法并转换为字符串
            return string.valueof(target.getclass()
                .getmethod(methodname)
                .invoke(target));
        } catch (nosuchmethodexception | illegalaccessexception | 
                 invocationtargetexception e) {
            e.printstacktrace();  // 生产环境建议日志记录
            return "";
        }
    }

    // main方法测试
    public static void main(string[] args) {
        //根据对象和字段名称获取get方法返回值
        user user = new user("1", "张三", 18);
        string namevale = getmethodvalue(user, "name");
        system.out.printf("name:" + namevale);

    }
}

三、基于反射的 list 集合去重:原理与实现

1. 核心工具类:collectionutils 的去重逻辑

package com.pearl.common.util;

import com.pearl.common.spring.beanutils;
import java.util.*;
import java.util.stream.collectors;

/**
 * 集合操作工具类
 * @author yyb
 * @since 2025/05/06
 * @apinote 提供基于反射的复杂去重与分组功能
 */
public class collectionutils {
    private static final string separator = ",";  // 默认分隔符

    /**
     * 多属性组合去重:基于treeset的自然排序特性
     * @param sourcelist 原始集合(支持null,但返回空集合)
     * @param fieldnames 参与去重的属性名数组(如["name", "age"])
     * @param <t> 泛型约束(需为java bean规范类)
     * @return 去重后的arraylist集合,保留首次出现的元素
     * @implnote 通过拼接属性值为唯一标识,利用treeset的唯一性实现去重
     */
    public static <t> list<t> listdistinct(list<t> sourcelist, string... fieldnames) {
        if (sourcelist == null || sourcelist.isempty()) {
            return new arraylist<>();  // 防御性编程:空集合返回空列表
        }

        return sourcelist.stream()
            .collect(collectors.collectingandthen(
                collectors.tocollection(() -> new treeset<>(
                    comparator.comparing(o -> buildkey(o, fieldnames, separator))
                )), 
                arraylist::new
            ));
    }

    // 辅助方法:拼接属性值为唯一键
    private static <t> string buildkey(t object, string[] fields, string separator) {
        stringbuilder keybuilder = new stringbuilder();
        for (string field : fields) {
            keybuilder.append(beanutils.getmethodvalue(object, field))
                      .append(separator);
        }
        // 移除末尾多余分隔符(如"name,age,"处理为"name,age")
        return keybuilder.length() > 0 ? 
            keybuilder.deletecharat(keybuilder.length() - 1).tostring() : 
            "";
    }
}

2 功能测试与结果分析

测试用例设计

public class collectiontest {
    public static void main(string[] args) {
        // 构造测试数据(包含重复属性组合)
        list<user> userlist = arrays.aslist(
            new user("1", "张三", 18),
            new user("3", "李四", 18),
            new user("5", "王五", 18),
            new user("2", "张三", 20),  // 与第一个用户name重复,但age不同
            new user("4", "李四", 18)   // 与第二个用户name+age均重复
        );

        // 单属性去重(按姓名)
        list<user> singledistinct = collectionutils.listdistinct(userlist, "name");
        system.out.println("单属性去重(name)结果:" + singledistinct);
        // 输出:[user{id='1', name='张三', age=18}, user{id='3', name='李四', age=18}, user{id='5', name='王五', age=18}]

        // 多属性去重(按name+age)
        list<user> multidistinct = collectionutils.listdistinct(userlist, "name", "age");
        system.out.println("多属性去重(name+age)结果:" + multidistinct);
        // 输出:[user{id='1', name='张三', age=18}, user{id='3', name='李四', age=18}, user{id='2', name='张三', age=20}, user{id='5', name='王五', age=18}]
    }
}

去重原理解析

  • 单属性去重:将每个对象的目标属性值(如name)作为唯一标识,相同值的对象仅保留第一个。
  • 多属性去重:通过separator拼接多个属性值(如"张三,18"),形成复合唯一键,确保只有属性组合完全相同的对象才会被去重。
  • 性能优化点:使用treeset结合自定义比较器,利用其内部红黑树结构实现 o (n log n) 时间复杂度的去重,优于传统双重循环的 o (n²) 复杂度。

四、基于反射的 list 集合分组:场景与实现

1. 分组工具方法:propertygroupmap 的设计

public static <t> map<string, list<t>> propertygroupmap(
    list<t> sourcelist, 
    string separator, 
    string... fieldnames) {

    map<string, list<t>> groupmap = new hashmap<>();
    if (sourcelist == null || sourcelist.isempty()) {
        return groupmap;
    }

    for (t item : sourcelist) {
        // 构建分组键(支持自定义分隔符,如"name-age")
        string groupkey = buildkey(item, fieldnames, separator);
        
        // 分组逻辑:同一键对应列表添加元素
        groupmap.computeifabsent(groupkey, k -> new arraylist<>())
                .add(item);
    }
    return groupmap;
}

2. 应用场景测试

场景 1:单属性分组(按姓名统计用户)

map<string, list<user>> namegroup = 
    collectionutils.propertygroupmap(userlist, "", "name");

// 输出结果:
// {
//   张三=[user{id='1', name='张三', age=18}, user{id='2', name='张三', age=20}],
//   李四=[user{id='3', name='李四', age=18}, user{id='4', name='李四', age=18}],
//   王五=[user{id='5', name='王五', age=18}]
// }

场景 2:多属性分组(按姓名 + 年龄分类)

map<string, list<user>> nameagegroup = 
    collectionutils.propertygroupmap(userlist, "-", "name", "age");

// 输出结果:
// {
//   张三-18=[user{id='1', name='张三', age=18}],
//   李四-18=[user{id='3', name='李四', age=18}, user{id='4', name='李四', age=18}],
//   张三-20=[user{id='2', name='张三', age=20}],
//   王五-18=[user{id='5', name='王五', age=18}]
// }

分组优势分析

  • 动态扩展性:通过可变参数fieldnames支持任意属性组合,无需为不同实体类编写重复分组代码。
  • 分隔符灵活性:通过separator参数可自定义键格式(如",""-"),适配不同业务场景的键存储需求。
  • 性能表现:基于 hashmap 的单次遍历分组,时间复杂度为 o (n),适用于大规模数据集。

五、总结

通过beanutilscollectionutils的组合,实现了基于反射的 java 集合动态去重与分组功能,显著提升了代码的通用性和可维护性。实际开发中,可进一步结合 spring 框架的beanwrapper或 mapstruct 工具,优化反射操作的性能与可读性。

以上就是java反射实现多属性去重与分组功能的详细内容,更多关于java多属性去重与分组的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com