/** * 必须是同一类型的Bean比较<br> * 深层次使用LE.equals方法对比Field的实际值,对某些特别的值进行了特别的trim,处理具体看{@link * #equal_trick_trim}方法,如"NULL"字符串认为就是null * * @param bean1 比较对象1 * @param bean2 比较对象2 * @return 两个Bean的内容是否相同 */ public static boolean equalsForBean(Object bean1, Object bean2) { if (bean1.getClass() != bean2.getClass()) return false; CE ce = CE.of(bean1.getClass()); Field[] fields = ce.getFields(); Set<String> fns = new HashSet<String>(); for (Field field : fields) { fns.add(field.getName()); try { // 特别的trim处理 LE.makeAccessible(field); Object v1 = equal_trick_trim(field.get(bean1)); Object v2 = equal_trick_trim(field.get(bean2)); if (!LE.equals(v1, v2)) { return false; } } catch (Exception e) { return false; } } return true; }
/** * 两个对象必须是相同类型的Bean 即getClass()相等,具备相同的方法属性签名,进行copy动作,可用于clone方法的内部实现 * * @param src 源对象 * @param to 目标对象(必须已经实例化) */ public static void copy(Object src, Object to) { if (src.getClass() != to.getClass()) return; String[] props = LE.getPropertyNames(to.getClass(), true); for (String prop : props) { Object value = LE.getPropertyValue(src, prop); LE.setPropertyValue(to, prop, value); } }
/** * 获取一个类的某个一个泛型参数 * * @param klass 类 * @param index 参数下标 (从 0 开始) * @return 泛型参数类型 */ @SuppressWarnings("unchecked") public static <T> Class<T> getTypeParam(Class<?> klass, int index) { Type[] types = extractTypeParams(klass); if (index >= 0 && index < types.length) { Type t = types[index]; Class<T> tClass = (Class<T>) LE.asClass(t); if (tClass == null) throw LE.makeThrow("Type '%s' is not a Class", t.toString()); return tClass; } throw LE.makeThrow("Class type param out of range %d/%d", index, types.length); }
/** * 将集合变成数组,数组的类型为集合的第一个元素的类型。如果集合为空,则返回 null * * @param coll 集合对象 * @return 数组 */ @SuppressWarnings("unchecked") public static <E> E[] coll2array(Collection<E> coll) { if (coll == null || coll.size() == 0) return (E[]) new Object[0]; Class<E> eleType = (Class<E>) LE.first(coll).getClass(); return coll2array(coll, eleType); }
/** * 将一个集合变成 Map。 * * @param typeOfMap Map 的类型 * @param coll 集合对象 * @param keyFieldName 采用集合中元素的哪个一个字段为键。 * @return Map 对象 */ public static <T extends Map<Object, Object>> Map<?, ?> coll2map( Class<T> typeOfMap, Collection<?> coll, String keyFieldName) { if (null == coll) return null; Map<Object, Object> map = createMap(typeOfMap); if (coll.size() > 0) { Iterator<?> it = coll.iterator(); Object obj = it.next(); Object key = LE.getPropertyValue(obj, keyFieldName); map.put(key, obj); for (; it.hasNext(); ) { obj = it.next(); key = LE.getPropertyValue(obj, keyFieldName); map.put(key, obj); } } return map; }
/** * 将一段字符串写入一个文本输出流,并将该流关闭 * * @param writer 文本输出流 * @param str 字符串 */ public static void writeAll(Writer writer, String str) { try { writer.write(str); writer.flush(); } catch (IOException e) { throw LE.wrapThrow(e); } finally { IOUtils.close(writer); } }
/** * 使用CE查找,调用某个对象(包括父类)的任意指定的方法 <br> * </> 可以是public 也可以是private ... * * @param src 被调用对象实例(类型和CE类型相同) * @param name 方法名称 * @param value 方法参数值数组 * @return 方法调用的返回 */ public static Object invoke(Object src, String name, Object... value) { Class<?>[] param_cls = LE.evalToTypes(value); CE<?> ce = CE.of(src); try { Method method = ce.findMethod(name, param_cls); LE.makeAccessible(method); return method.invoke(src, value); } catch (NoSuchMethodException e) { throw new FailToInvokingException( e, "Can not find any method [ %s ( %s ) ] on class[ %s ]", name, value.getClass(), src.getClass()); } catch (Throwable e) { throw new FailToInvokingException( e, "Invoke method [ %s ] on class[ %s ] error.", name, src.getClass()); } }
private static <T extends Map<Object, Object>> Map<Object, Object> createMap(Class<T> mapClass) { Map<Object, Object> map; try { map = mapClass.newInstance(); } catch (Exception e) { map = new HashMap<Object, Object>(); } if (!mapClass.isAssignableFrom(map.getClass())) { throw LE.makeThrow("Fail to create map [%s]", mapClass.getName()); } return map; }
/** * 将一个数组变成 Map * * @param typeOfMap Map 的类型 * @param array 数组 * @param keyFieldName 采用集合中元素的哪个一个字段为键。 * @return Map 对象 */ public static <T extends Map<Object, Object>> Map<?, ?> array2map( Class<T> typeOfMap, Object array, String keyFieldName) { if (array == null) return null; Map<Object, Object> map = createMap(typeOfMap); int len = Array.getLength(array); if (len > 0) { Object obj = Array.get(array, 0); // CE<?> ce = CE.of(obj.getClass()); for (int i = 0; i < len; i++) { obj = Array.get(array, i); Object key = LE.getPropertyValue(obj, keyFieldName); map.put(key, obj); } } return map; }
/** * 从一个文本输入流读取所有内容,并将该流关闭 * * @param reader 文本输入流 * @return 输入流所有内容 */ public static String readAll(Reader reader) { if (!(reader instanceof BufferedReader)) reader = new BufferedReader(reader); try { StringBuilder sb = new StringBuilder(); char[] data = new char[64]; int len; while (true) { if ((len = reader.read(data)) == -1) break; sb.append(data, 0, len); } return sb.toString(); } catch (IOException e) { throw LE.wrapThrow(e); } finally { IOUtils.close(reader); } }
/** * 设置对象的属性值 * * @param bean * @param property * @param value */ public static void setPropertyValue(Object bean, String property, Object value) { Class<?> clss = bean.getClass(); try { Field fld = clss.getField(property); fld.set(bean, value); } catch (Throwable t) { Method m = null; try { PropertyDescriptor pd = new PropertyDescriptor(property, clss); m = pd.getWriteMethod(); } catch (IntrospectionException e) { throw new FailToSetValueException( e, "Failed to find writeMethod of property[%s] on class[%s] failed.", property, bean.getClass()); } if (null == m) { throw new FailToSetValueException( "Failed to find writeMethod of property[%s] on class[%s] failed.", property, bean.getClass()); } try { m.invoke(bean, value); } catch (Throwable e) { throw new FailToSetValueException( e, "Set property[%s] value[%s] with type[%s] on class[%s] failed.", property, value, value == null ? "NULL type" : LE.toString(CE.of(value.getClass()).getExtractTypes(), ""), bean.getClass()); } } }
/** * 判断两个对象是否相等。 这个函数用处是: * * <ul> * <li>可以容忍 null, 如果两个对象都是null,则认为相等 * <li>辨识Identifiable接口对象实例,自动使用getId()方式比较 * <li>可以容忍不同类型的 Number * <li>对数组,集合,Map 会深层比较 * </ul> * * 重写的 equals方法优先 * * @param a1 比较对象1 * @param a2 比较对象2 * @return 是否相等 */ @SuppressWarnings("unchecked") public static boolean equals(Object a1, Object a2) { if (a1 == null && a2 == null) return true; if (a1 == null || a2 == null) return false; if (a1.equals(a2)) return true; CE<?> ce1 = CE.of(a1); if (ce1.isStringLike()) { return a1.toString().equals(a2.toString()); } if (ce1.isDateLike()) { Calendar calendar1 = Calendar.getInstance(); calendar1.setTime((java.util.Date) a1); Calendar calendar2 = Calendar.getInstance(); calendar2.setTime((java.util.Date) a2); if (calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR) && calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH) && calendar1.get(Calendar.DATE) == calendar2.get(Calendar.DATE)) { return true; } else { return false; } } if (ce1.isTimeLike()) { return a1.equals(a2); } if (ce1.isNumber()) { return a2 instanceof Number && a1.toString().equals(a2.toString()); } if ((a1 instanceof Identifiable) && (a2 instanceof Identifiable)) { return equals(((Identifiable) a1).getId(), ((Identifiable) a2).getId()); } if (!a1.getClass().isAssignableFrom(a2.getClass()) && !a2.getClass().isAssignableFrom(a1.getClass())) return false; if (a1 instanceof Map && a2 instanceof Map) { Map<?, ?> m1 = (Map<?, ?>) a1; Map<?, ?> m2 = (Map<?, ?>) a2; if (m1.size() != m2.size()) return false; for (Map.Entry<?, ?> e : m1.entrySet()) { Object key = e.getKey(); if (!m2.containsKey(key) || !equals(m1.get(key), m2.get(key))) return false; } return true; } else if (a1.getClass().isArray()) { if (a2.getClass().isArray()) { int len = Array.getLength(a1); if (len != Array.getLength(a2)) return false; for (int i = 0; i < len; i++) { if (!equals(Array.get(a1, i), Array.get(a2, i))) return false; } return true; } else if (a2 instanceof List) { return equals(a1, LE.coll2array((List<Object>) a2, Object.class)); } return false; } else if (a1 instanceof List) { if (a2 instanceof List) { List<?> l1 = (List<?>) a1; List<?> l2 = (List<?>) a2; if (l1.size() != l2.size()) return false; int i = 0; for (Iterator<?> it = l1.iterator(); it.hasNext(); ) { if (!equals(it.next(), l2.get(i++))) return false; } return true; } else if (a2.getClass().isArray()) { return equals(LE.coll2array((List<Object>) a1, Object.class), a2); } return false; } else if (a1 instanceof Collection && a2 instanceof Collection) { Collection<?> c1 = (Collection<?>) a1; Collection<?> c2 = (Collection<?>) a2; if (c1.size() != c2.size()) return false; return c1.containsAll(c2) && c2.containsAll(c1); } return false; }
public static void main(String[] args) { String ss = " "; System.out.println(LE.isEmpty(ss)); }
/** * 用回调的方式,遍历一个对象,可以支持遍历 * * <ul> * <li>数组 * <li>集合 * <li>Map * <li>单一元素 * </ul> * * @param elems 对象 * @param callback 回调 */ @SuppressWarnings({"unchecked", "rawtypes"}) public static <T> void each(Object elems, Each<T> callback) { if (null == elems || null == callback) return; try { Class<T> eType = getTypeParam(callback.getClass(), 0); if (elems.getClass().isArray()) { int len = Array.getLength(elems); for (int i = 0; i < len; i++) try { callback.loop(i, (T) Array.get(elems, i), len); } catch (ExitLoop e) { break; } } else if (elems instanceof Collection) { int len = ((Collection) elems).size(); int i = 0; for (Iterator<T> it = ((Collection) elems).iterator(); it.hasNext(); ) try { callback.loop(i++, it.next(), len); } catch (ExitLoop e) { break; } } else if (elems instanceof Map) { Map map = (Map) elems; int len = map.size(); int i = 0; if (null != eType && eType != Object.class && eType.isAssignableFrom(Map.Entry.class)) { for (Object v : map.entrySet()) try { callback.loop(i++, (T) v, len); } catch (ExitLoop e) { break; } } else { for (Object v : map.entrySet()) try { callback.loop(i++, (T) ((Map.Entry) v).getValue(), len); } catch (ExitLoop e) { break; } } } else if (elems instanceof Iterator<?>) { Iterator<?> it = (Iterator<?>) elems; int i = 0; while (it.hasNext()) { try { callback.loop(i++, (T) it.next(), -1); } catch (ExitLoop e) { break; } } } else try { callback.loop(0, (T) elems, 1); } catch (ExitLoop e) { } } catch (LoopException e) { throw LE.wrapThrow(e.getCause()); } }