Map转Bean反射 VS 内省 性能对比

青苗 青苗 | 474 | 2022-09-17

Bean 工具类如下:

public final class BeanMapUtils {
    private static final Map<Class, List<Field>> CLASS_FIELD_MAP = new ConcurrentHashMap<>();

    /**
     * 获取 Class 属性 Field
     *
     * @param clazz {@link Class}
     * @return
     */
    public static List<Field> getFields(Class clazz) {
        List<Field> fields = CLASS_FIELD_MAP.get(clazz);
        if (null == fields) {
            fields = Arrays.stream(clazz.getDeclaredFields()).filter(t -> {
                int mod = t.getModifiers();
                return !(Modifier.isStatic(mod) || Modifier.isFinal(mod));
            }).map(t -> {
                t.setAccessible(true);
                return t;
            }).collect(Collectors.toList());
            CLASS_FIELD_MAP.put(clazz, fields);
        }
        return fields;
    }

    private static final Map<Class, BeanInfo> CLASS_BEAN_INFO_MAP = new ConcurrentHashMap<>();

    public static <T> T transMap2Bean(Map<String, Object> map, Class<T> clz) {
        try {
            BeanInfo beanInfo = CLASS_BEAN_INFO_MAP.get(clz);
            if (null == beanInfo) {
                beanInfo = Introspector.getBeanInfo(clz);
                CLASS_BEAN_INFO_MAP.put(clz, beanInfo);
            }
            T obj = clz.getDeclaredConstructor().newInstance();
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                if (map.containsKey(key)) {
                    Object value = map.get(key);
                    Method setter = property.getWriteMethod();
                    setter.invoke(obj, value);
                }
            }
            return obj;
        } catch (Exception e) {
            throw new QcrudException(e);
        }
    }

    /**
     * 对象转Map
     *
     * @param object 待转换Map对象
     * @return
     * @throws IllegalAccessException
     */
    public static Map<String, Object> beanToMap(Object object) {
        try {
            Map map = new HashMap<String, Object>();
            List<Field> fields = getFields(object.getClass());
            for (Field field : fields) {
                map.put(field.getName(), field.get(object));
            }
            return map;
        } catch (Exception e) {
            throw new QcrudException(e);
        }
    }

    /**
     * map转对象
     *
     * @param map       {@link Map}
     * @param beanClass {@link Class}
     * @param <T>       转换对象
     * @return
     * @throws Exception
     */
    public static <T> T mapToBean(Map map, Class<T> beanClass) {
        try {
            T object = beanClass.getDeclaredConstructor().newInstance();
            List<Field> fields = getFields(beanClass);
            for (Field field : fields) {
                Object obj = map.get(field.getName());
                if (null != obj) {
                    field.set(object, obj);
                }
            }
            return object;
        } catch (Exception e) {
            throw new QcrudException(e);
        }
    }

    /**
     * List&lt;Map&lt;String, Object&gt;&gt; 转换为 List&lt;T&gt;
     *
     * @param maps  转换 MAP 集合
     * @param clazz 对象 Class
     * @return 返回转换后的 bean 集合
     */
    public static <T> List<T> mapsToBeans(List<Map<String, Object>> maps, Class<T> clazz) {
        if (null == maps || maps.isEmpty()) {
            return Collections.emptyList();
        }
        return maps.stream().map(e -> mapToBean(e, clazz)).toList();
    }
}

Bean 测试类:

@Getter
@Setter
public class Person {
    private Integer id;
    private String name;
}

JMH 测试类:


public class JmhTest {

    static Map<String, Object> TEST_MAP = new HashMap<>() {{
        put("id", 1);
        put("name", "lili");
    }};

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
            .include(JmhTest.class.getSimpleName())
            .forks(1)
            .build();

        new Runner(opt).run();
    }

    @Benchmark
    public void test() {
        BeanMapUtils.mapToBean(TEST_MAP, Person.class);
    }

    @Benchmark
    public void test2() {
        BeanMapUtils.transMap2Bean(TEST_MAP, Person.class);
    }
}

JMH 测试结果

Benchmark       Mode  Cnt         Score        Error  Units
JmhTest.test   thrpt    5  15151502.006 ± 981705.086  ops/s
JmhTest.test2  thrpt    5  10799191.625 ± 322695.424  ops/s

结果可以看出反射性能更高

关于 bean to map 反射调优

文章标签: Java
推荐指数:

真诚点赞 诚不我欺~

Map转Bean反射 VS 内省 性能对比

点赞 收藏 评论

关于作者

青苗
青苗

青苗幼儿园园长

等级 LV5

粉丝 20

获赞 47

经验 1182