欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java反射實現(xiàn)多屬性去重與分組功能

 更新時間:2025年06月08日 11:34:49   作者:程序員岳焱  
在Java開發(fā)中,??List是一種非常常用的數(shù)據(jù)結(jié)構(gòu),通常我們會遇到這樣的問題:如何處理??List???中的相同字段?無論是去重還是分組,合理的操作可以提高代碼的性能和可讀性,本文將詳細介紹如何基于反射的Java集合動態(tài)去重與分組功能,需要的朋友可以參考下

一、開發(fā)環(huán)境與基礎(chǔ)組件準備

1.環(huán)境配置:

  • IDE:IntelliJ IDEA
  • JDK 版本:1.8
  • 核心組件:自定義工具類庫(common模塊)

2. 代碼結(jié)構(gòu)說明:

com.pearl.common/
├─ entity/        # 實體類模塊
│  └─ User.java   # 用戶實體定義
└─ spring/        # 工具類模塊
   └─ BeanUtils.java # 反射工具類

二、基礎(chǔ)反射工具:BeanUtils 的設(shè)計與實現(xiàn)

1. 用戶實體類:User.java

package com.pearl.common.entity;

/**
 * 業(yè)務實體:用戶信息模型
 * @author yyb
 * @since 2025/05/06
 * @apiNote 包含基礎(chǔ)屬性及Java Bean規(guī)范的訪問器方法
 */
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方法前綴

    /**
     * 通過反射調(diào)用對象的Getter方法獲取屬性值
     * @param target 對象實例
     * @param fieldName 目標字段名(駝峰命名,如"userName")
     * @param <T> 泛型約束(需為Java Bean規(guī)范類)
     * @return 字段值字符串表示,異常時返回空字符串
     * @throws SecurityException 反射權(quán)限異常
     * @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 {
            // 反射調(diào)用方法并轉(zhuǎn)換為字符串
            return String.valueOf(target.getClass()
                .getMethod(methodName)
                .invoke(target));
        } catch (NoSuchMethodException | IllegalAccessException | 
                 InvocationTargetException e) {
            e.printStackTrace();  // 生產(chǎn)環(huán)境建議日志記錄
            return "";
        }
    }

    // main方法測試
    public static void main(String[] args) {
        //根據(jù)對象和字段名稱獲取get方法返回值
        User user = new User("1", "張三", 18);
        String nameVale = getMethodValue(user, "name");
        System.out.printf("name:" + nameVale);

    }
}

三、基于反射的 List 集合去重:原理與實現(xiàn)

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 參與去重的屬性名數(shù)組(如["name", "age"])
     * @param <T> 泛型約束(需為Java Bean規(guī)范類)
     * @return 去重后的ArrayList集合,保留首次出現(xiàn)的元素
     * @implNote 通過拼接屬性值為唯一標識,利用TreeSet的唯一性實現(xiàn)去重
     */
    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 功能測試與結(jié)果分析

測試用例設(shè)計

public class CollectionTest {
    public static void main(String[] args) {
        // 構(gòu)造測試數(shù)據(jù)(包含重復屬性組合)
        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)結(jié)果:" + 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)結(jié)果:" + 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"),形成復合唯一鍵,確保只有屬性組合完全相同的對象才會被去重。
  • 性能優(yōu)化點:使用TreeSet結(jié)合自定義比較器,利用其內(nèi)部紅黑樹結(jié)構(gòu)實現(xiàn) O (n log n) 時間復雜度的去重,優(yōu)于傳統(tǒng)雙重循環(huán)的 O (n²) 復雜度。

四、基于反射的 List 集合分組:場景與實現(xiàn)

1. 分組工具方法:propertyGroupMap 的設(shè)計

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) {
        // 構(gòu)建分組鍵(支持自定義分隔符,如"name-age")
        String groupKey = buildKey(item, fieldNames, separator);
        
        // 分組邏輯:同一鍵對應列表添加元素
        groupMap.computeIfAbsent(groupKey, k -> new ArrayList<>())
                .add(item);
    }
    return groupMap;
}

2. 應用場景測試

場景 1:單屬性分組(按姓名統(tǒng)計用戶)

Map<String, List<User>> nameGroup = 
    CollectionUtils.propertyGroupMap(userList, "", "name");

// 輸出結(jié)果:
// {
//   張三=[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");

// 輸出結(jié)果:
// {
//   張三-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}]
// }

分組優(yōu)勢分析

  • 動態(tài)擴展性:通過可變參數(shù)fieldNames支持任意屬性組合,無需為不同實體類編寫重復分組代碼。
  • 分隔符靈活性:通過separator參數(shù)可自定義鍵格式(如",""-"),適配不同業(yè)務場景的鍵存儲需求。
  • 性能表現(xiàn):基于 HashMap 的單次遍歷分組,時間復雜度為 O (n),適用于大規(guī)模數(shù)據(jù)集。

五、總結(jié)

通過BeanUtilsCollectionUtils的組合,實現(xiàn)了基于反射的 Java 集合動態(tài)去重與分組功能,顯著提升了代碼的通用性和可維護性。實際開發(fā)中,可進一步結(jié)合 Spring 框架的BeanWrapper或 MapStruct 工具,優(yōu)化反射操作的性能與可讀性。

以上就是Java反射實現(xiàn)多屬性去重與分組功能的詳細內(nèi)容,更多關(guān)于Java多屬性去重與分組的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spring boot整合連接池實現(xiàn)過程圖解

    Spring boot整合連接池實現(xiàn)過程圖解

    這篇文章主要介紹了Spring boot整合連接池實現(xiàn)過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • Java樹形菜單的創(chuàng)建

    Java樹形菜單的創(chuàng)建

    這篇文章主要為大家詳細介紹了Java圖形用戶界面中樹形菜單的創(chuàng)建樹形菜單的創(chuàng)建,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-10-10
  • Java操作pdf文件的方法大全

    Java操作pdf文件的方法大全

    這篇文章主要為大家詳細介紹了Java操作pdf文件的相關(guān)知識,例如合并pdf文件,手繪pdf文件以及導出PDF文件等,有需要的小伙伴可以參考一下
    2024-04-04
  • Maven方式構(gòu)建SpringBoot項目的實現(xiàn)步驟(圖文)

    Maven方式構(gòu)建SpringBoot項目的實現(xiàn)步驟(圖文)

    Maven是一個強大的項目管理工具,可以幫助您輕松地構(gòu)建和管理Spring Boot應用程序,本文主要介紹了Maven方式構(gòu)建SpringBoot項目的實現(xiàn)步驟,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • java使用servlet實現(xiàn)驗證碼

    java使用servlet實現(xiàn)驗證碼

    這篇文章主要介紹了java使用servlet實現(xiàn)驗證碼,簡單實用,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Java中正則表達式的語法以及matches方法的使用方法

    Java中正則表達式的語法以及matches方法的使用方法

    正則表達式(Regular Expression)是一門簡單語言的語法規(guī)范,是強大、便捷、高效的文本處理工具,這篇文章主要給大家介紹了關(guān)于Java中正則表達式的語法以及matches方法的使用方法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-05-05
  • 關(guān)于springboot配置文件密文解密方式

    關(guān)于springboot配置文件密文解密方式

    這篇文章主要介紹了關(guān)于springboot配置文件密文解密方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Java如何將String轉(zhuǎn)換成json對象或json數(shù)組

    Java如何將String轉(zhuǎn)換成json對象或json數(shù)組

    這篇文章主要介紹了Java如何將String轉(zhuǎn)換成json對象或json數(shù)組,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • SpringBoot通過自定義注解與異步來管理日志流程

    SpringBoot通過自定義注解與異步來管理日志流程

    實現(xiàn)日志管理說實話方式還挺多,個人使用過直接在Controller代碼里面寫、AOP+自定義注解、ConstraintValidator。本文主要和大家講的是自定義注解與異步來管理日志流程,感興趣的可以了解一下
    2023-03-03
  • Java微服務實戰(zhàn)項目尚融寶接口創(chuàng)建詳解

    Java微服務實戰(zhàn)項目尚融寶接口創(chuàng)建詳解

    這篇文章主要介紹了Java微服務實戰(zhàn)項目尚融寶的接口創(chuàng)建流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08

最新評論