首页 > 其他分享 >对象属性值按长度拆分扩展一个新集合

对象属性值按长度拆分扩展一个新集合

时间:2024-04-30 16:45:52浏览次数:17  
标签:java String object List private 拆分 集合 import 属性

package com.xx.xx.core.utils;

import cn.hutool.core.util.ReflectUtil;
import com.xx.tools.utils.BeanUtil;
import com.xx.tools.utils.StringUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import tk.mybatis.mapper.weekend.reflection.ReflectionOperationException;

import java.beans.Introspector;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 使用方式:
 * 第一步:指定规则:拆分字段名,拆分长度
 *  List<ListSplitHelper.FieldSplitRule> fields = ListUtil.of(
 *                 ListSplitHelper.of(NursingRecordMaternal::getHandlingContent, 6)
 *         );
 * 第二步:扩展集合
 *  List<NursingRecordMaternal> dataList = ListSplitHelper.process(list,  fields, false);
 *
 *  业务场景:参考 护理文书>护理记录单>产前记录:处置或附注, 要求超出部分放到下一个单元格展示
 *
 **/
public class ListSplitHelper {

    private static final Pattern GET_PATTERN = Pattern.compile("^get[A-Z].*");
    private static final Pattern IS_PATTERN = Pattern.compile("^is[A-Z].*");

    /**
     *
     * @Description: 扩展原集合 : 根据字段允许的最大属性值进行拆分扩展
     * @param: list 原集合
     * @param: ruleFields 待拆分的属性
     * @param isAllCopy 是否全量拷贝 : true 全量拷贝,false 只拷贝id及规则属性
     * @Return: java.util.List<T>
     * @Throws:
     * @Date: 2024/4/28 17:51
     **/
    public static <T> List<T> process(List<T> list, List<FieldSplitRule> ruleFields, boolean isAllCopy) {
        List<T> expandedList = new ArrayList<>();

        for (T original : list) {
            //包装适配
            List<FieldWrapper> fieldWrapperList = wrapper(ruleFields, original);

            //新集合长度
            Integer size = fieldWrapperList.stream().map(field -> field.getArr().length).max(Integer::compare).orElse(0);

            AtomicInteger index = new AtomicInteger(0);

            //扩展新集合
            for (int i = 0; i < size; i++) {
                T newObj = (T) ReflectUtil.newInstance(original.getClass());

                if(isAllCopy) {
                    BeanUtil.copyProperties(original, newObj);
                } else {
                    if(index.get() == 0) {
                        BeanUtil.copyProperties(original, newObj);
                    } else {
                        ReflectUtil.setFieldValue(newObj, "id", ReflectUtil.getFieldValue(original, "id"));
                    }
                }

                for (FieldWrapper wrapper : fieldWrapperList) {
                    String[] arr = wrapper.getArr();
                    if(arr.length > i) {
                        ReflectUtil.setFieldValue(newObj, wrapper.getFieldName(), arr[i]);
                    }
                }

                expandedList.add(newObj);
                index.incrementAndGet();
            }
        }

        return expandedList;
    }

    public static <T, B> FieldSplitRule of(MyFn<T, B> fieldFunction, int ruleCutLength) {
        String fieldName = fnToFieldName(fieldFunction);
        return new FieldSplitRule(fieldName, ruleCutLength);
    }

    private static <T> List<FieldWrapper> wrapper(List<FieldSplitRule> ruleFields, T object) {
        List<FieldWrapper> fieldWrapperList = ruleFields.stream()
                .map(rule -> new FieldWrapper(rule, object))
                .collect(Collectors.toList());
        return fieldWrapperList;
    }

    private static String fnToFieldName(MyFn<?, ?> fn) {
        try {
            Method method = fn.getClass().getDeclaredMethod("writeReplace");
            method.setAccessible(Boolean.TRUE);
            SerializedLambda serializedLambda = (SerializedLambda)method.invoke(fn);
            String getter = serializedLambda.getImplMethodName();
            if (GET_PATTERN.matcher(getter).matches()) {
                getter = getter.substring(3);
            } else if (IS_PATTERN.matcher(getter).matches()) {
                getter = getter.substring(2);
            }

            return Introspector.decapitalize(getter);
        } catch (ReflectiveOperationException var4) {
            throw new ReflectionOperationException(var4);
        }
    }

    @AllArgsConstructor
    @NoArgsConstructor
    @Accessors(chain = true)
    @Data
    public static class FieldSplitRule {
        /** 分割-属性名 */
        private String ruleFieldName;

        /** 分割-长度 */
        private int ruleCutLength;
    }

    @Accessors(chain = true)
    @Data
    private static class FieldWrapper<T> {
        /** 对象 */
        private T object;

        private FieldSplitRule fieldSplitRule;

        /** 分割后的数组 */
        private String[] arr;

        private FieldWrapper() {

        }

        private FieldWrapper(FieldSplitRule fieldSplitRule, T object) {
            this.fieldSplitRule = fieldSplitRule;
            this.object = object;
            this.arr = cutStrValue(object);
        }

        private String getFieldName() {
            return fieldSplitRule.getRuleFieldName();
        }

        /**
         * @return 属性值
         **/
        private Object getFieldValue(T object) {
            return ReflectUtil.getFieldValue(object, fieldSplitRule.getRuleFieldName());
        }

        /**
         * 分割字段内容
         * @return 分割后的内容列表
         **/
        private String[] cutStrValue(T object) {
            Object fieldValue = getFieldValue(object);
            if(fieldValue == null) {
                return new String[0];
            }
            if(!(fieldValue instanceof String)) {
                throw new RuntimeException("类型不是字符串");
            }
            String[] arr = StringUtil.cut(String.valueOf(fieldValue), fieldSplitRule.getRuleCutLength());
            setArr(arr);
            return arr;
        }


    }

    public interface MyFn<T, R> extends Function<T, R>, Serializable {
    }

}

 

标签:java,String,object,List,private,拆分,集合,import,属性
From: https://www.cnblogs.com/smileblogs/p/18168287

相关文章

  • cesium 加载各类地图的方法集合
    1.天地图服务//矢量底图viewer.imageryLayers.addImageryProvider(newCesium.WebMapTileServiceImageryProvider({url:"http://t0.tianditu.com/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=vec&tileMatrixSet=w&TileMatrix={T......
  • Go语言系列——数组和切片、可变参数函数、Maps、字符串、指针、结构体、方法、接口(一
    文章目录11-数组和切片数组数组的声明数组是值类型数组的长度使用range迭代数组多维数组切片创建一个切片切片的修改切片的长度和容量使用make创建一个切片追加切片元素切片的函数传递多维切片内存优化12-可变参数函数什么是可变参数函数语法通过一些例子理解可变参......
  • 【Redis】Redis的操作命令(四)——Redis 集合(SET)
    Redis的SET是String类型的无序列表。添加无序列表语句:SADDsetDemoredis获取无序列表语句SMEMBERSsetDemoRedis集合命令如下:命令描述例子SADDkeymember1[member2]向集合添加一个或多个成员 SCARDkey获取集合的成员数 SDIFFkey1[key2]返回......
  • 文件属性
    查看[root@localhost~]#ls-ltotal64dr-xr-xr-x2rootroot4096Dec142012bin[root@localhost~]#ll总用量4-rw-------.1rootroot12583月714:47anaconda-ks.cfg#第一个字符当为d则是目录当为-则是文件;若是l则表示为链接文档(linkfil......
  • 41天【代码随想录算法训练营34期】第九章 动态规划part03 (● 343. 整数拆分 ● 96.
    343.整数拆分classSolution:defintegerBreak(self,n:int)->int:dp=[0]*(n+1)dp[2]=1foriinrange(3,n+1):forjinrange(1,i//2+1):dp[i]=max(dp[i],(i-j)*j,dp[i-j]*j)......
  • vue之计算属性与监听属性
    一、计算属性1、什么是计算属性--computed计算属性是Vue中的⼀种特殊属性,⽤于对已有的数据进⾏计算和衍⽣,以⽣成新的数据。计算属性的值是根据依赖的数据动态计算得出的,当依赖的数据发⽣变化时,计算属性会⾃动重新计算。2、计算属性的作用计算属性的主要作⽤是对数据进⾏处......
  • SAP MM 定义物料类型的属性配置里的New entries按钮
    SAPMM定义物料类型的属性配置里的Newentries按钮  在SAP的很多后台配置界面上都有NewEntries(新条目)按钮,方便企业用户可以根据企业特有业务需求来增加新的配置条目。 事实上,并不是所有的配置界面里,都能很随意很方便的允许企业用户点击’NewEntries’按钮来做定制配......
  • 为什么打印对象,点开查看某属性有值,但是直接打印无值
    1.现象某些刚学习一段时间前端,或者学习一段时间后的一些人不知道为什么打印对象,点开查看某属性有值,但是直接打印无值.比较常见的一个开发现象就是发现自己直接打印对象有值,但是进行页面跳转或者其他业务请求之类的时候发现参数拿不到2.原因直接打开控制台的时候里面没......
  • 组件的使用、父子通信、ref属性(父子通信)、动态组件、 keep-alive、插槽
    【组件的使用】1<!DOCTYPEhtml>2<htmllang="en">3<head>4<metacharset="UTF-8">5<title>Title</title>6<scriptsrc="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">&......
  • Azure Storage (30) 基于属性的访问控制(ABAC)
    《WindowsAzurePlatform系列文章目录》 我们在使用AzureStorage的时候,经常会基于属性来进行访问控制,我们假设一个场景1:(1)用户:productionuser01可以访问到container以production开头的文件内容,如contoso.blob.core.windows.net/production01contoso.blob.c......