/**
* @author sean 2019/11/13.
*/
public class CollectionUtils {
/**
* 查找
*
* @param list source
* @param filter filter
* @param <T> type
* @return object
*/
public static <T> T find(Collection<T> list, Filter<T> filter) {
for (T object : list) {
if (filter.accept(object)) {
return object;
}
}
return null;
}
/**
* 筛选
*
* @param list source
* @param filter filter
* @param <T> type
* @return filtered list
*/
public static <T> List<T> filter(Collection<T> list, Filter<T> filter) {
List<T> result = new ArrayList<>();
for (T object : list) {
if (filter.accept(object)) {
result.add(object);
}
}
return result;
}
/**
* 从 B 中选择一个字段
*
* @param list source
* @param fieldProvider field provider
* @param distinct 去重
* @param <B> Bean
* @param <F> Field
* @return field list
*/
public static <B, F> Collection<F> select(Collection<B> list, FieldProvider<B, F> fieldProvider, boolean distinct) {
Collection<F> result;
if (distinct) {
result = new HashSet<>();
} else {
result = new ArrayList<>();
}
for (B item : list) {
result.add(fieldProvider.provide(item));
}
return result;
}
/**
* 根据某字段分组
*
* @param list source
* @param fieldProvider field provider
* @param <B> B
* @param <F> F
* @return grouped
*/
public static <B, F> List<List<B>> groupBy(List<B> list, FieldProvider<B, F> fieldProvider) {
if (list == null || list.size() == 0) {
return null;
}
HashSet<F> fieldValueSet = new HashSet<>();
for (B item : list) {
fieldValueSet.add(fieldProvider.provide(item));
}
List<List<B>> result = new ArrayList<>();
for (F field : fieldValueSet) {
List<B> group = new ArrayList<>();
for (B item : list) {
F fieldItem = fieldProvider.provide(item);
boolean equals;
if (fieldItem != null) {
equals = fieldItem.equals(field);
} else {
equals = field == null;
}
if (equals) {
group.add(item);
}
}
result.add(group);
}
return result;
}
/**
* 计算 B list 中 某数字字段的和
*
* @param list source
* @param provider field provider
* @param <B> B
* @param <N> Number
* @return sum
*/
public static <B, N extends Number> BigDecimal sum(Collection<B> list, FieldProvider<B, N> provider) {
BigDecimal result = BigDecimal.ZERO;
boolean highPrecision = list.iterator().next() instanceof BigDecimal;
for (B item : list) {
N n = provider.provide(item);
if (n != null) {
if (highPrecision) {
result = result.add((BigDecimal) n);
} else {
result = result.add(BigDecimal.valueOf(n.doubleValue()));
}
}
}
return result;
}
/**
* 平均值
*/
public static <B, N extends Number> BigDecimal average(Collection<B> list, FieldProvider<B, N> provider) {
BigDecimal sum = BigDecimal.ZERO;
BigDecimal size = BigDecimal.ZERO;
for (B item : list) {
N n = provider.provide(item);
if (n != null) {
sum = sum.add(BigDecimal.valueOf(n.doubleValue()));
size = size.add(BigDecimal.valueOf(1));
}
}
if (size.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO;
}
return sum.divide(size, 6, BigDecimal.ROUND_HALF_UP);
}
/**
* 类型转换
*
* @param list source
* @param converter converter
* @param <T> type
* @param <R> result
* @return result list
*/
public static <T, R> List<R> convert(Collection<T> list, Converter<T, R> converter) {
List<R> result = new ArrayList<>();
for (T item : list) {
R converted = converter.convert(item);
if (converted != null) {
result.add(converted);
}
}
return result;
}
@SuppressWarnings("unchecked")
public static <T, R> R[] convert(T[] array, Converter<T, R> converter) {
Object[] result = new Object[array.length];
for (int i = 0; i < array.length; i++) {
result[i] = converter.convert(array[i]);
}
return (R[]) result;
}
/**
* 选择器
*
* @param <T> Type
*/
public interface Filter<T> {
/**
* 筛选是否通过
*
* @param item obj
* @return is accept?
*/
boolean accept(T item);
}
/**
* 转换器
*
* @param <T> input type
* @param <R> result
*/
public interface Converter<T, R> {
/**
* 转换类型
*
* @param item obj
* @return converted
*/
R convert(T item);
}
/**
* 字段选择器
*
* @param <B> Bean
* @param <F> Field
*/
public interface FieldProvider<B, F> {
/**
* 提供 Bean 中一个字段
*
* @param item B
* @return F
*/
F provide(B item);
}
}
/**
* @author sean
*/
public class FileUtils {
public static boolean copy(String src, String dest) {
File srcFile = new File(src);
File destFile = new File(dest);
return copy(srcFile, destFile);
}
public static boolean copy(File src, File dest) {
if (!src.exists()) {
return false;
}
if (dest.exists()) {
boolean deleted = dest.delete();
if (!deleted) {
return false;
}
}
try {
File parent = dest.getParentFile();
if (parent == null) {
return false;
}
boolean dirs = parent.mkdirs();
boolean created = dest.createNewFile();
if (!created) {
return false;
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
try (FileChannel srcChannel = new FileInputStream(src).getChannel();
FileChannel dstChannel = new FileOutputStream(dest).getChannel()) {
srcChannel.transferTo(0, srcChannel.size(), dstChannel);
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 删除文件或文件夹
*
* @param file file or directory
* @return success?
*/
public static boolean delete(File file) {
if (!file.exists()) {
return false;
}
if (file.isDirectory()) {
File[] listFiles = file.listFiles();
if (listFiles == null) {
return false;
}
for (File child : listFiles) {
if (child.isDirectory()) {
if (!delete(child)) {
return false;
}
} else {
if (!child.delete()) {
return false;
}
}
}
}
return file.delete();
}
public static byte[] read(File file) {
try (FileChannel fileChannel = new RandomAccessFile(file, "r").getChannel()) {
long fileSize = fileChannel.size();
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
byte[] result = new byte[(int) fileSize];
mappedByteBuffer.get(result, 0, mappedByteBuffer.remaining());
return result;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static boolean write(File dest, String content) {
if (dest.exists()) {
boolean deleted = dest.delete();
if (!deleted) {
return false;
}
}
try {
File parent = dest.getParentFile();
if (parent == null) {
return false;
}
boolean dirs = parent.mkdirs();
boolean created = dest.createNewFile();
if (!created) {
return false;
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
try (FileChannel channel = new FileOutputStream(dest).getChannel()) {
ByteBuffer buffer = StandardCharsets.UTF_8.encode(content);
channel.write(buffer);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
import android.text.TextUtils;
import android.util.Log;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import logger.Logger;
/**
* 转换实体类
*
* @author sean 2019/5/8.
*/
public class BeanUtils {
private static final String TAG = BeanUtils.class.getSimpleName();
private static final Class[] BASE_CLASS_TYPES = new Class[]{int.class, long.class, float.class, double.class};
private static final Class[] PACKAGE_CLASS_TYPES = new Class[]{Integer.class, Long.class, Float.class, Double.class};
private static final Object[] NUMBER_DEFAULT_VALUE = new Object[]{0, 0L, 0F, 0D};
/**
* 调用该方法需要有对应 setter
* 暂时不支持父类
*
* @param tClass JavaBean的Class
* @param map 存储数据的Map Key: 实体类的参数名 Value: 值
* @return JavaBean
*/
public static <T> T mapToBean(Class<T> tClass, Map<String, ?> map) throws IllegalAccessException, InstantiationException, InvocationTargetException {
T t = tClass.newInstance();
for (Map.Entry entry : map.entrySet()) {
if (entry.getValue() == null) {
continue;
}
try {
Method method = tClass.getDeclaredMethod("set" + firstToUpperCase((String) entry.getKey()), entry.getValue().getClass());
method.setAccessible(true);
method.invoke(t, entry.getValue());
} catch (NoSuchMethodException e) {
for (int i = 0; i < PACKAGE_CLASS_TYPES.length; i++) {
if (entry.getValue().getClass() == PACKAGE_CLASS_TYPES[i]) {
try {
Method method = tClass.getDeclaredMethod("set" + firstToUpperCase((String) entry.getKey()), BASE_CLASS_TYPES[i]);
method.setAccessible(true);
method.invoke(t, entry.getValue());
break;
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
}
}
}
}
}
return t;
}
/**
* 不跳过null
*/
public static <T> T stringMapToBeanDonotSkipNull(T t, Class<T> tClass, Map<String, String> map) throws IllegalAccessException, InvocationTargetException {
for (Map.Entry<String, String> entry : map.entrySet()) {
insertIntoBean(t, tClass, entry.getKey(), entry.getValue());
}
return t;
}
public static <T> T stringMapToBean(Class<T> tClass, Map<String, String> map) throws IllegalAccessException, InstantiationException, InvocationTargetException {
T t = tClass.newInstance();
for (Map.Entry<String, String> entry : map.entrySet()) {
if (entry.getValue() == null) {
continue;
}
insertIntoBean(t, tClass, entry.getKey(), entry.getValue());
}
return t;
}
private static <T> T insertIntoBean(T t, Class<T> tClass, String k, String v) throws InvocationTargetException, IllegalAccessException {
try {
Method method = tClass.getDeclaredMethod("set" + firstToUpperCase(k), String.class);
method.setAccessible(true);
method.invoke(t, v);
} catch (NoSuchMethodException e) {
//只有在无法找到对应方法时尝试匹配
//这里是处理一些字符串格式的 boolean
if ("true".equalsIgnoreCase(v) || "false".equalsIgnoreCase(v)) {
try {
Method method = tClass.getDeclaredMethod("set" + firstToUpperCase(k), boolean.class);
method.setAccessible(true);
method.invoke(t, "true".equalsIgnoreCase(v));
return t;
} catch (NoSuchMethodException e1) {
Log.e(TAG, k + " is not a boolean.");
}
}
//这里是处理字符串格式的数字
for (int i = 0; i < BASE_CLASS_TYPES.length; i++) {
Class<?> numType = BASE_CLASS_TYPES[i];
Class<?> packageType = PACKAGE_CLASS_TYPES[i];
Object defaultValue = NUMBER_DEFAULT_VALUE[i];
try {
Method method = tClass.getDeclaredMethod("set" + firstToUpperCase(k), numType);
method.setAccessible(true);
if (v == null) {
method.invoke(t, defaultValue);
return t;
}
Object num = null;
try {
Method valueOf = packageType.getDeclaredMethod("valueOf", String.class);
num = valueOf.invoke(null, v);
} catch (NumberFormatException en) {
en.printStackTrace();
}
if (num != null) {
method.invoke(t, num);
}
return t;
} catch (NoSuchMethodException e1) {
if (i == BASE_CLASS_TYPES.length - 1) {
Log.e(TAG, k + " is not a number.");
}
}
}
//判断BigDecimal
try {
Method method = tClass.getDeclaredMethod("set" + firstToUpperCase(k), BigDecimal.class);
method.setAccessible(true);
if (v != null) {
Double value = null;
try {
value = Double.valueOf(v);
} catch (NumberFormatException en) {
en.printStackTrace();
}
if (value != null) {
method.invoke(t, BigDecimal.valueOf(value));
}
} else {
method.invoke(t, (BigDecimal) null);
}
} catch (NoSuchMethodException e1) {
Log.e(TAG, k + " is not a BigDecimal.");
if (tClass.getSuperclass() != null && tClass.getSuperclass() != Object.class) {
return insertIntoBean(t, (Class<T>) tClass.getSuperclass(), k, v);
} else {
Logger.t(TAG).e("Can't set field: " + k + " From: " + tClass.getSimpleName());
}
}
}
return t;
}
/**
* JavaBean 转换 Map
*
* @param bean Bean
* @return Map
*/
public static <T> Map<String, Object> beanToMap(T bean) throws IllegalAccessException, InvocationTargetException {
Map<String, Object> map = new HashMap<>(32);
Class<?> clazz = bean.getClass();
while (clazz != null) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
try {
Method method = clazz.getDeclaredMethod("get" + firstToUpperCase(field.getName()));
method.setAccessible(true);
Object value = method.invoke(bean);
if (value != null) {
map.put(field.getName(), value);
}
} catch (NoSuchMethodException e) {
//可能是boolean
try {
Method method = clazz.getDeclaredMethod("is" + firstToUpperCase(field.getName()));
method.setAccessible(true);
Object value = method.invoke(bean);
if (value != null) {
map.put(field.getName(), value);
}
} catch (NoSuchMethodException e1) {
//还找不到可能就是带 is 的
//之所以先尝试加上 is 是因为可能为is开头的词
if (field.getName().startsWith("is") || field.getName().startsWith("Is")) {
try {
Method method = clazz.getDeclaredMethod(firstToLowerCase(field.getName()));
method.setAccessible(true);
Object value = method.invoke(bean);
if (value != null) {
map.put(field.getName(), value);
}
continue;
} catch (NoSuchMethodException e2) {
//
}
}
Logger.t(TAG).e("Can't set field: " + field.getName() + " From: " + clazz.getSimpleName());
}
}
}
clazz = clazz.getSuperclass();
if (clazz == Object.class) {
break;
}
}
return map;
}
public static <T> Map<String, String> beanToStringMap(T bean) throws IllegalAccessException, InvocationTargetException {
Map<String, ?> map = beanToMap(bean);
Map<String, String> stringMap = new HashMap<>(32);
for (Map.Entry entry : map.entrySet()) {
stringMap.put((String) entry.getKey(), String.valueOf(entry.getValue()));
}
return stringMap;
}
/**
* 同类型 Bean 数据copy
*
* @param source source bean
* @param target target bean
* @param ignoreFields ignore filter
*/
public static <T> void copy(T source, T target, String... ignoreFields) throws IllegalAccessException, InvocationTargetException {
if (source == target) {
return;
}
Class<?> clazz = source.getClass();
if (clazz == ArrayList.class) {
((ArrayList) target).clear();
((ArrayList) target).addAll((ArrayList) source);
}
while (clazz != null) {
Field[] fields = clazz.getDeclaredFields();
fieldsLoop:
for (Field field : fields) {
field.setAccessible(true);
try {
for (String ignore : ignoreFields) {
if (field.getName().equals(ignore)) {
if (field.get(source) instanceof BigDecimal) {
if (((BigDecimal) field.get(source)).intValue() == 0) {
continue fieldsLoop;
}
} else {
continue fieldsLoop;
}
}
}
if (field.get(source) == null) {
continue;
}
Method method = clazz.getDeclaredMethod("set" + firstToUpperCase(field.getName()), field.getType());
method.setAccessible(true);
method.invoke(target, field.get(source));
} catch (NoSuchMethodException e) {
if (field.getName().startsWith("is") || field.getName().startsWith("Is")) {
try {
Method method = clazz.getDeclaredMethod("set" + firstToUpperCase(field.getName().substring(2)), field.getType());
method.setAccessible(true);
method.invoke(target, field.get(source));
} catch (NoSuchMethodException e1) {
Logger.t(TAG).e("Can't copy field: " + field.getName() + " From: " + clazz.getSimpleName());
}
}
}
}
clazz = clazz.getSuperclass();
if (clazz == Object.class) {
break;
}
}
}
private static String firstToUpperCase(String s) {
if (Character.isUpperCase(s.charAt(0))) {
return s;
} else {
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
}
}
private static String firstToLowerCase(String s) {
if (Character.isLowerCase(s.charAt(0))) {
return s;
} else {
return Character.toLowerCase(s.charAt(0)) + s.substring(1);
}
}
public static void initFieldValue(Object target, String fileName) {
if (target == null || TextUtils.isEmpty(fileName)) {
return;
}
Class _class = target.getClass();
for (; _class != Object.class; _class = _class.getSuperclass()) {
try {
Field field = _class.getDeclaredField(fileName);
field.setAccessible(true);
Object value = field.getType().newInstance();
field.set(target, value);
return;
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
/**
* 对象深拷贝 需要 Serializable
*
* @param object obj
* @param <T> type
* @return cloned obj
* @throws IOException e
*/
public static <T> T clone(T object) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos;
T cloneObject = null;
try {
oos = new ObjectOutputStream(bos);
oos.writeObject(object);
oos.flush();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
cloneObject = (T) ois.readObject();
ois.close();
bis.close();
oos.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return cloneObject;
}
// /**
// * 查找 Class 包含的所有 bean
// * 如果 Class 本身也是 Bean, 返回的 Set 会包含它本身
// *
// * @param clazz clz
// * @return class set
// */
// public static Set<Class> getAllBeanTypes(Class clazz) {
// if (clazz == null) {
// return null;
// }
// Set<Class> types = new HashSet<>();
// Class c = ClassUtils.getClassByClassName(clazz.getSimpleName());
// if (c != null) {
// types.add(c);
// }
// for (Class tempClz = clazz; tempClz != Object.class; tempClz = tempClz.getSuperclass()) {
// Field[] fields = tempClz.getDeclaredFields();
// for (Field field : fields) {
// if (field.getType() == List.class) {
// Type type = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
// if (ClassUtils.getClassByClassName(((Class) type).getSimpleName()) != null) {
// types.add(((Class) type));
// types.addAll(getAllBeanTypes(((Class) type)));
// }
// } else if (ClassUtils.getClassByClassName(field.getType().getSimpleName()) != null) {
// types.add(field.getType());
// types.addAll(getAllBeanTypes(field.getType()));
// }
// }
// }
// return types;
// }
}