/** * @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; // } }