All Downloads are FREE. Search and download functionalities are using the official Maven repository.

shz.ToList Maven / Gradle / Ivy

package shz;

import shz.model.TreeNode;
import shz.model.TreeNodeMetadata;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@SuppressWarnings("unchecked")
public final class ToList {
    private final List list;

    private ToList(int initialCapacity, int idx) {
        list = new ArrayList<>(reduce(initialCapacity, idx));
    }

    private int reduce(int cap, int idx) {
        if (idx <= 0 || cap < 3) return cap;
        int newCap = cap;
        for (int i = idx; i > 0; --i) newCap = (newCap << 1) / 3;
        while (calc(newCap, idx) < cap) ++newCap;
        return newCap;
    }

    private int calc(int newCap, int idx) {
        while (idx > 0) {
            newCap = newCap + (newCap >> 1);
            --idx;
        }
        return newCap;
    }

    public static  ToList get(int initialCapacity, int idx) {
        return new ToList<>(initialCapacity, idx);
    }

    public static  ToList get(int initialCapacity) {
        return new ToList<>(initialCapacity, 0);
    }

    public  T build() {
        return (T) list;
    }

    public ToList add(Collection c) {
        list.addAll(c);
        return this;
    }

    public final  ToList add(EE e) {
        list.add(e);
        return this;
    }

    /**
     * 大致确定元素个数时的收集器
     *
     * @param initialCapacity 大致确定的初始容量
     * @param idx             初始容量衰减次数
     */
    public static  Collector> collector(int initialCapacity, int idx) {
        return Collector.of(
                //提供初始化容量的ArraysList
                () -> get(initialCapacity, idx).build(),
                List::add,
                (left, right) -> {
                    left.addAll(right);
                    return left;
                }
        );
    }

    public static  Collector> collector(int initialCapacity) {
        return collector(initialCapacity, 0);
    }

    /**
     * 大致确定元素个数时的流收集
     */
    public static  List explicitCollect(Stream stream, int initialCapacity, int idx) {
        List list = stream.collect(collector(initialCapacity, idx));
        return list.isEmpty() ? Collections.emptyList() : list;
    }

    public static  List explicitCollect(Stream stream, int initialCapacity) {
        return explicitCollect(stream, initialCapacity, 0);
    }

    /**
     * 无法确定元素个数时的收集器
     * 使用ArrayList 由于频繁扩容的原因,将会在此过程使用new 申请额外的数组内存
     * 若流中元素不超过73,在此过程中最多申请192个元素容量的数组内存(扩容5次),最终最多申请109个元素容量的数组内存,可以接受
     * 若流中元素超过366,在此过程中最少申请1623个元素容量的数组内存(扩容10次),最终最少申请549个元素容量的数组内存,勉强可以接受
     * 

* 以下情况建议使用此方法,可大幅度减少过程中的内存消耗 * 若流中元素超过823,在此过程中最少申请3680个元素容量的数组内存(扩容12次),最终最少申请1234个元素容量的数组内存,难以接受 * 若流中元素超过9369,在此过程中最少申请42139个元素容量的数组内存(扩容18次),最终最少申请14053个元素容量的数组内存,极难接受 * 若流中元素超过21079,在此过程中最少申请94836个元素容量的数组内存(扩容20次),最终最少申请31618个元素容量的数组内存,不可接受 * 若流中元素超过47427,在此过程中最少申请213403个元素容量的数组内存(扩容22次),最终最少申请71140个元素容量的数组内存,绝无可能 *

* 特别在并发时优势更明显 * 若有10个用户在操作,则在这个过程中最少申请的内存就要*10,最终额外声请的内存消耗也要*10 * 频繁的扩容不仅导致过程中申请大量的数组内存,垃圾回收器并不会立马回收,还会影响性能 */ public static Collector> collector() { return Collector.of( //使用LinkedList替换默认的ArrayList LinkedList::new, List::add, (left, right) -> { left.addAll(right); return left; } ); } /** * 无法确定元素个数时的流收集 * * @param extra 是否需要添加额外元素 */ public static List collect(Stream stream, boolean extra) { List list = stream.collect(collector()); return list.isEmpty() ? extra ? new LinkedList<>() : Collections.emptyList() : list; } public static List collect(Stream stream) { return collect(stream, false); } /** * 无法确定元素个数时的流收集(需要频繁的进行索引查询时选择此方法收集流) * * @param extra 申请额外空间 */ public static List collectArray(Stream stream, int extra) { int size = Math.max(extra, 0); List list = stream.collect(collector()); if (list.isEmpty()) return size == 0 ? Collections.emptyList() : new ArrayList<>(size); if (size == 0) return new ArrayList<>(list); //转ArrayList 提供更快的索引查询 List result = new ArrayList<>(size + list.size()); result.addAll(list); return result; } public static List collectArray(Stream stream) { return collectArray(stream, 0); } /** * 获取分组树 * * @param list 需要分组的数据 * @param mapper 数据映射器 * @param lastMapper 最后分组数据映射器 * @param lastCollector 最后分组数据收集器 * @param classifiers 分组函数集 */ public static , R> List groupTree(List list, BiFunction, ? extends E> mapper, BiFunction lastMapper, Collector lastCollector, Function... classifiers) { if (Validator.isEmpty(list)) return Collections.emptyList(); Validator.requireNonEmpty(classifiers); Collector> collector = Collectors.groupingBy(classifiers[classifiers.length - 1], lastCollector); for (int i = classifiers.length - 2; i >= 0; --i) collector = Collectors.groupingBy(classifiers[i], collector); return mergeGroup(list.stream().collect(collector), mapper, lastMapper); } private static , R> List mergeGroup(Map group, BiFunction, ? extends E> mapper, BiFunction lastMapper) { return explicitCollect(group.keySet().stream().map(k -> { Object nextGroup = group.get(k); return nextGroup instanceof Map ? mapper.apply(k, mergeGroup((Map) nextGroup, mapper, lastMapper)) : lastMapper.apply(k, (R) nextGroup); }), group.size()); } /** * 排序分组树 */ public static > void sort(List nodes, Comparator comparator) { if (Validator.isEmpty(nodes)) return; nodes.sort(comparator); nodes.forEach(node -> sort(node.getChildes(), comparator)); } /** * 合并分组树 */ public static > List mergeTree(List nodes, List otherNodes, BiFunction merger) { if (Validator.isEmpty(nodes)) return Validator.isEmpty(otherNodes) ? Collections.emptyList() : otherNodes; if (Validator.isEmpty(otherNodes)) return nodes; Map map = ToMap.collect(nodes.stream(), TreeNode::getId, Function.identity()); Map otherMap = ToMap.collect(otherNodes.stream(), TreeNode::getId, Function.identity()); Set ids = new HashSet<>(map.keySet()); Set otherIds = new HashSet<>(otherMap.keySet()); if (!otherIds.removeAll(ids) || !otherIds.isEmpty()) ids.addAll(otherIds); return explicitCollect(ids.stream().map(k -> { E e = map.get(k); E other = otherMap.get(k); if (e == null) return other; else if (other == null) return e; E result = merger.apply(e, other); result.setChildes(mergeTree(e.getChildes(), other.getChildes(), merger)); return result; }), ids.size()); } /** * 获取分组树(用于分组特殊设计表结构) */ public static > List groupTree(List list) { Map> map = list.stream().collect(Collectors.groupingBy(TreeNodeMetadata::getLevel, collector())); int level = 1; List es = map.get(level); map.remove(level); while (!map.isEmpty()) { for (E e : map.get(++level)) { E root = null; for (E e1 : es) { if (e.getRootId().equals(e1.getId())) { root = e1; break; } } Objects.requireNonNull(root); E parent = root; while (true) { List child = parent.getChildes(); if (child == null) { child = new LinkedList<>(); parent.setChildes(child); child.add(e); break; } if (e.getParentId().equals(parent.getId())) { child.add(e); break; } boolean flag = true; for (E e1 : child) { if (e.getTag().startsWith(parent.getTag())) { parent = e1; flag = false; break; } } Validator.requireNon(flag); } } map.remove(level); } return es; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy