Java CloneUtils 克隆、类型转换工具类

282 阅读2分钟

平时自己用的小工具,基于反射做的,根据自己的需求,可以做一些扩展性的功能。 对象克隆,同类型同名称才会拷贝。 Map与List的转换、Map与对象转换等等方法。

public class CloneUtils {

    /**
     * 克隆方法,两个不同的类,相同的属性直接 clone - 不包含 list 属性
     * @param prototype 原型对象
     * @param clone 克隆对象
     * @date: 2020/8/25 10:23
     * @author: 
     */
    public static void cloneObj(Object prototype, Object clone) {
        clone(prototype, clone, (value, field) -> value);
    }

    /**
     * 克隆方法,两个不同的类,相同的属性直接 clone - 包含 list 属性
     * @param prototype 原型对象
     * @param clone 克隆对象
     * @date: 2020/8/25 10:24
     * @author: 
     */
    public static void cloneObjAndList(Object prototype, Object clone) {
        clone(prototype, clone, (value, field) -> {
            if (field.getType() == List.class) {
                ParameterizedType genericType = (ParameterizedType) field.getGenericType();
                Class<?> clazz = (Class<?>) genericType.getActualTypeArguments()[0];
                value = transList(clazz, (List<?>) value);
            }
            return value;
        });
    }

    public static <T, U> void cloneTwoList(List<U> prototype, List<T> clone, BiConsumer<U, T> biConsumer) {
        if (prototype.size() != clone.size()) {
            return;
        }
        IntStream.range(0, clone.size()).forEach(index -> {
            U obj = prototype.get(index);
            T t = clone.get(index);
            biConsumer.accept(obj, t);
        });
    }

    /**
     * 克隆核心方法
     * @param prototype 原型对象
     * @param clone 克隆对象
     * @param biFunction 给 value 赋值的抽象过程
     * @date: 2020/8/25 10:26
     * @author: 
     */
    private static void clone(Object prototype, Object clone, BiFunction<Object, Field, Object> biFunction) {

        // get class
        Class<?> class1 = prototype.getClass();
        Class<?> class2 = clone.getClass();

        // get object field array
        Field[] fields1 = class1.getDeclaredFields();
        Field[] fields2 = class2.getDeclaredFields();

        // temp names set , who value's length short one who first
        Set<String> names = new HashSet<>();

        // compare prototype and clone
        if (fields1.length <= fields2.length) {
            for (Field field1 : fields1) {
                String name = field1.getName();
                names.add(name);
            }

            for (Field field2 : fields2) {
                // 字段为 final 跳过
                if (Modifier.isFinal(field2.getModifiers())) {
                    continue;
                }
                String name = field2.getName();
                if (names.contains(name)) {
                    try {
                        // get value
                        Field field1 = class1.getDeclaredField(name);
                        field1.setAccessible(true);
                        Object value = field1.get(prototype);
                        // set value
                        if (field1.getType() == field2.getType()) {
                            field2.setAccessible(true);
                            value = biFunction.apply(value, field2);
                            field2.set(clone, value);
                        }
                    } catch (NoSuchFieldException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }

        } else {
            for (Field field2 : fields2) {
                // 字段为 final 跳过
                if (Modifier.isFinal(field2.getModifiers())) {
                    continue;
                }
                String name = field2.getName();
                names.add(name);
            }
            for (Field field1 : fields1) {
                String name = field1.getName();
                if (names.contains(name)) {
                    try {
                        // get value
                        field1.setAccessible(true);
                        Object value = field1.get(prototype);
                        // set value
                        Field field2 = class2.getDeclaredField(name);
                        if (field1.getType() == field2.getType()) {
                            field2.setAccessible(true);
                            value = biFunction.apply(value, field2);
                            field2.set(clone, value);
                        }
                    } catch (NoSuchFieldException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 转换列表为 Map
     * @param list 需要转换的对象列表
     * @param key map 中的 key 值抽象方法
     * @param value map 中的 value 值抽象方法
     * @param <T> list 的类型
     * @param <K> key 的类型
     * @param <V> value 的类型
     * @return 转成指定 map
     * @date: 2020/8/26 17:42
     * @author: 
     */
    public static<T, K, V> Map<K, V> transListToMap(List<T> list, Function<T, K> key, Function<T, V> value) {
        if (list == null) {
            return new HashMap<>(0);
        }
        Map<K, V> map = new HashMap<>(list.size());
        list.forEach(o -> {
            map.put(key.apply(o), value.apply(o));
        });
        return map;
    }


    /**
     * 转换 Map 为 List 列表
     * @param map map集合
     * @param clazz 列表类型
     * @param key set 到 t 的那个字段
     * @param value set 到 t 的那个字段
     * @param <T> list 类型
     * @param <K> k 类型
     * @param <V> v 类型
     * @return 指定的 List 集合
     */
    public static<T, K, V> List<T> transMapToList(Map<K, V> map, Class<T> clazz, BiConsumer<T, K> key, BiConsumer<T, V> value) {
        return transMapToList(map, clazz, key, value, t -> {});
    }

    /**
     * 转换 Map 为 List 列表
     * @param map map集合
     * @param clazz 列表类型
     * @param key set 到 t 的那个字段
     * @param value set 到 t 的那个字段
     * @param consumer 特殊字段处理
     * @param <T> list 类型
     * @param <K> k 类型
     * @param <V> v 类型
     * @return 指定的 List 集合
     */
    public static<T, K, V> List<T> transMapToList(Map<K, V> map, Class<T> clazz, BiConsumer<T, K> key, BiConsumer<T, V> value, Consumer<T> consumer) {
        List<T> list = new LinkedList<>();
        try {
            for (K k : map.keySet()) {
                V v = map.get(k);
                T t = clazz.newInstance();
                key.accept(t, k);
                value.accept(t, v);
                consumer.accept(t);
                list.add(t);
            }
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 转换列表类型,为指定类型
     * @param clazz 转换后的类型
     * @param list 原始列表对象
     * @param <T> 泛型
     * @return 指定类型的列表
     * @date: 2020/8/25 09:09
     * @author: 
     */
    public static <T> List<T> transList(Class<T> clazz, List<?> list) {
        return transList(clazz, list, (o, t) -> {});
    }

    /**
     * 转换列表类型,为指定类型
     * @param clazz 转换后的类型
     * @param list 原始列表对象
     * @param <T> 返回对象的泛型
     * @param <U> 传入对象的泛型
     * @return 指定类型的列表
     * @date: 2020/8/26 17:55
     * @author: 
     */
    public static <T, U> List<T> transList(Class<T> clazz, List<U> list, BiConsumer<U , T> utBiConsumer) {
        if (list == null) {
            return new ArrayList<>();
        }
        return list.stream().map(obj -> {
            try {
                T t = clazz.getDeclaredConstructor().newInstance();
                utBiConsumer.accept(obj, t);
                cloneObj(obj, t);
                return t;
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException();
            }
        }).collect(Collectors.toList());
    }

    /**
     * 转换对象类型,为指定的类型
     * @param clazz 转换后的类型
     * @param obj 原始对象
     * @param <T> 泛型
     * @return 指定类型的对象
     * @date: 2020/8/25 09:09
     * @author: 
     */
    private static <T> T transObj(Class<T> clazz, Object obj) {
        if (clazz.isInstance(obj)) {
            return clazz.cast(obj);
        } else {
            throw new RuntimeException();
        }
    }

}