Skip to content

TreeUtls

java
public class TreeUtil {
    /**
     * 使用Map合成树
     *
     * @param menuList       需要合成树的List
     * @param pId            对象中的父ID字段,如:Menu:getPid
     * @param id             对象中的id字段 ,如:Menu:getId
     * @param rootCheck      判断E中为根节点的条件,如:x->x.getPId()==-1L ,
     *                       x->x.getParentId()==null,x->x.getParentMenuId()==0
     * @param setSubChildren E中设置下级数据方法,如: Menu::setSubMenus
     * @param <T>            ID字段类型
     * @param <E>            泛型实体对象
     * @return
     */
    public static <T, E> List<E> makeTree(List<E> menuList, Function<E, T> pId, Function<E, T> id,
            Predicate<E> rootCheck, BiConsumer<E, List<E>> setSubChildren) {
        // 按原数组顺序构建父级数据Map,使用Optional考虑pId为null
        Map<Optional<T>, List<E>> parentMenuMap = menuList.stream().collect(Collectors.groupingBy(
                node -> Optional.ofNullable(pId.apply(node)),
                LinkedHashMap::new,
                Collectors.toList()));
        List<E> result = new ArrayList<>();
        for (E node : menuList) {
            // 添加到下级数据中
            setSubChildren.accept(node, parentMenuMap.get(Optional.ofNullable(id.apply(node))));
            // 如里是根节点,加入结构
            if (rootCheck.test(node)) {
                result.add(node);
            }
        }
        return result;
    }

    /**
     * 树中过滤
     * 
     * @param tree        需要过滤的树
     * @param predicate   过滤条件
     * @param getChildren 获取下级数据方法,如:MenuVo::getSubMenus
     * @return List<E> 过滤后的树
     * @param <E> 泛型实体对象
     */
    public static <E> List<E> filter(List<E> tree, Predicate<E> predicate, Function<E, List<E>> getChildren) {
        return tree.stream().filter(item -> {
            if (predicate.test(item)) {
                List<E> children = getChildren.apply(item);
                if (children != null && !children.isEmpty()) {
                    filter(children, predicate, getChildren);
                }
                return true;
            }
            return false;
        }).collect(Collectors.toList());
    }

    /**
     * 树中搜索
     * 
     * @param tree
     * @param predicate
     * @param getSubChildren
     * @return 返回搜索到的节点及其父级到根节点
     * @param <E>
     */
    public static <E> List<E> search(List<E> tree, Predicate<E> predicate, Function<E, List<E>> getSubChildren) {
        Iterator<E> iterator = tree.iterator();
        while (iterator.hasNext()) {
            E item = iterator.next();
            List<E> childList = getSubChildren.apply(item);
            if (childList != null && !childList.isEmpty()) {
                search(childList, predicate, getSubChildren);
            }
            if (!predicate.test(item) && (childList == null || childList.isEmpty())) {
                iterator.remove();
            }
        }
        return tree;
    }

}

public class TreeTest {

    // 树节点数
    public static Integer size = 5000000;
    // 树深度
    public static Integer deep = 100;
    private static List<MenuVo> menuVos = new ArrayList<>();

    @BeforeAll
    public static void init() {
        long currentId = 1;
        List<MenuVo> currentLevel = new ArrayList<>();
        MenuVo root = new MenuVo(currentId++, 0L, "Root");
        menuVos.add(root);
        currentLevel.add(root);
        for (int level = 1; level < deep && currentId <= size; level++) {
            List<MenuVo> nextLevel = new ArrayList<>();
            for (MenuVo parent : currentLevel) {
                for (int i = 0; i < size / Math.pow(10, level); i++) {
                    if (currentId > size)
                        break;
                    MenuVo child = new MenuVo(currentId++, parent.getId(), String.format("测试name:%s", currentId));
                    menuVos.add(child);
                    nextLevel.add(child);
                }
            }
            currentLevel = nextLevel;
        }
    }

    @Test
    public void testBigTree() {
        List<MenuVo> tree = TreeUtil.makeTree(menuVos, MenuVo::getPId, MenuVo::getId, x -> x.getPId() == 0,
                MenuVo::setSubMenus);
        System.out.println(tree);
    }

}

@AllArgsConstructor
@Data
public class MenuVo {

    private Long id;
    private Long pId;
    private String name;
    private List<MenuVo> subMenus;  

    public MenuVo() {
    }

    public MenuVo(Long id, Long pId, String name) {
        this.id = id;
        this.pId = pId;
        this.name = name;
    }

}

DateUtils

java
//根据年月获取第一天
public static Date getFistDayByYearAndMonth(Integer year, Integer month) {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.MONTH, month - 1);
    calendar.set(Calendar.YEAR, year);
    calendar.add(Calendar.MONTH, 0);
    calendar.set(Calendar.DAY_OF_MONTH, 1);
    return calendar.getTime();
}

//根据年月获取其最后一天
public static Date getLastDayByYearAndMonth(Integer year, Integer month) {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.MONTH, month - 1);
    calendar.set(Calendar.YEAR, year);
    calendar.add(Calendar.MONTH, 1);
    calendar.set(Calendar.DAY_OF_MONTH, 0);
    return calendar.getTime();
}

static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
static DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
static ZoneId zoneId = ZoneId.systemDefault();


@Test
public void toLocalDate() {
    Date date = new Date();
    LocalDateTime localDateTime = date.toInstant().atZone(zoneId).toLocalDateTime();
    System.out.println(dateTimeFormatter2.format(localDateTime));
    LocalDate localDate = date.toInstant().atZone(zoneId).toLocalDate();
    System.out.println(dateTimeFormatter.format(localDate));
}

@Test
public void toDate() {
    LocalDateTime localDateTime = LocalDateTime.now();
    Date date = Date.from(localDateTime.atZone(zoneId).toInstant());
    System.out.println(DateFormatUtils.format(date, "yyyy-MM-dd HH:mm:ss"));

    LocalDate localDate = LocalDate.now();
    Date date1 = Date.from(localDate.atStartOfDay(zoneId).toInstant());
    System.out.println(DateFormatUtils.format(date1, "yyyy-MM-dd"));
}

@Test
public void firstOrLast() {
    LocalDate localDate = LocalDate.of(2020, 1, 10);
    System.out.println(dateTimeFormatter.format(localDate.with(TemporalAdjusters.firstDayOfMonth())));//当月第一天
    System.out.println(dateTimeFormatter.format(localDate.with(TemporalAdjusters.lastDayOfMonth())));//当月最后一天
}

@Test
public void between() {
    LocalDate localDate1 = LocalDate.of(2020, 10, 10);
    LocalDate localDate2 = LocalDate.of(2020, 10, 12);
    System.out.println(localDate2.toEpochDay() - localDate1.toEpochDay());//2天

    LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 10, 18, 0, 0);
    LocalDateTime localDateTime2 = LocalDateTime.of(2020, 10, 10, 21, 0, 0);
    System.out.println(
            (localDateTime2.atZone(zoneId).toEpochSecond() - localDateTime1.atZone(zoneId).toEpochSecond()) / 60 / 60
    );//3小时
}

IOUtils

InputStream<--> String

java

@Test
public void stringToInputStream() throws IOException {
    InputStream inputStream = new ByteArrayInputStream("hello world".getBytes(StandardCharsets.UTF_8));
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    String collect = bufferedReader.lines().collect(Collectors.joining());
    System.out.println(collect);
}

路径处理

可以自动处理windows/linux的斜杠反斜杠的问题

Paths.get("/opt/test").normalize()

输出数据到指定文件中

java
//将list中的数据一行一行写到指定文件中
public static <T> void fileWriterList1(String path, List<T> list) {
    try {
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path), StandardCharsets.UTF_8));
        for (T t : list) {
            bufferedWriter.write(t.toString());
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }
        bufferedWriter.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

NumberUtils

java
//分转为万元
public static double changeF2WY(Long amount) {
    return BigDecimal.valueOf(amount).divide(new BigDecimal(1000000), BigDecimal.ROUND_HALF_UP).doubleValue();
}

//计算百分比
public static String getPercentNumber(BigDecimal a, BigDecimal b) {
    return b == null ? "-" :
            b.compareTo(new BigDecimal(0)) == 0 ? "-" :
                    a == null ? "0.00" :
                            a.multiply(new BigDecimal(100)).divide(b, 2, BigDecimal.ROUND_HALF_UP).toString();
}

StringUtils

java

// 1.2.3转为000001000002000003
public static String turnString(String values) {
    StringBuilder obj = new StringBuilder();
    if (null == values || values.length() == 0) {
        return "";
    } else {
        for (String value : values.split("\\.")) {
            int length = value.length();
            if (length > 6) {
                obj.append(value, 0, 6);
            } else {
                for (int i = 0; i < 6 - length; i++) {
                    obj.append("0");
                }
                obj.append(value);
            }
        }
    }
    return obj.toString();
}

// 000001000002000003转为1.2.3
public static String turnStringToDot(String values) {
    StringBuilder obj = new StringBuilder();
    if (null == values || values.length() < 6 || values.contains("\\.")) {
        return values;
    } else {
        for (int i = 0; i < values.length() / 6; i++) {
            String value = values.substring(i * 6, i * 6 + 6);
            String res = value.replaceAll("^(0+)", "");
            obj.append(res.length() == 0 ? "0." : res + ".");
        }
    }
    return obj.toString();
}
java

// 1.2.3转为000001000002000003
public static String turnString(String values) {
    StringBuilder obj = new StringBuilder();
    if (null == values || values.length() == 0) {
        return "";
    } else {
        for (String value : values.split("\\.")) {
            int length = value.length();
            if (length > 6) {
                obj.append(value, 0, 6);
            } else {
                for (int i = 0; i < 6 - length; i++) {
                    obj.append("0");
                }
                obj.append(value);
            }
        }
    }
    return obj.toString();
}

// 000001000002000003转为1.2.3
public static String turnStringToDot(String values) {
    StringBuilder obj = new StringBuilder();
    if (null == values || values.length() < 6 || values.contains("\\.")) {
        return values;
    } else {
        for (int i = 0; i < values.length() / 6; i++) {
            String value = values.substring(i * 6, i * 6 + 6);
            String res = value.replaceAll("^(0+)", "");
            obj.append(res.length() == 0 ? "0." : res + ".");
        }
    }
    return obj.toString();
}

List/Arrays/String

java

@Test
void B() {
    // List -->  Arrays
    List<string> list = new ArrayList<string>(2);
    list.add("1");
    list.add("2");
    String[] arrays = new String[list.size()];
    //如果使用toArray的无参方法,返回值是object[],容易出现类型转换异常
    arrays = list.toArray(arrays);


    // Arrays ---> List 
    //asList()返回的对象是一个Arrays内部类,没有实现集合的修改方法
    list = new ArrayList<>(Arrays.asList(arrays));


    // List --> String
    //可以使用common.lang中StringUtils中的join方法
    String s = StringUtils.join(list, ",");
    //或者使用 Java8中的String.join();
    String string = String.join(",", arrays);

    // String --> List
    stringbuilder sb = new stringbuilder("1,2,3,");
    sb.deleteCharAt(0);
    List list = new ArrayList(Arrays.asList(sb.toString().split(',')));

    //使用Arrays.asList构造的list没有重写add,remove方法,其size不可变,
    //为了避免使用该list增删改的接口报错,
    //使用new ArrayList()将其包起来即可。
    //另外的,当asList的构造参数为基础数据类型数组,
    //不能被泛型化的数组时,不能正确转list,
    //会把整个数组作为一个元素转为list。此时可以使用

    int[] intArr = {1, 2, 3};
    List<Integer> list = Arrays.stream(intArr).boxed().collect(Collectors.toList());
}