平时自己用的小工具,基于反射做的,根据自己的需求,可以做一些扩展性的功能。 对象克隆,同类型同名称才会拷贝。 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();
}
}
}