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

cn.woodwhales.common.business.collection.CollectionMathResult Maven / Gradle / Ivy

package cn.woodwhales.common.business.collection;

import com.google.common.collect.Sets;
import cn.woodwhales.common.business.DataTool;

import java.util.List;
import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptySet;
import static org.apache.commons.collections4.CollectionUtils.isEmpty;
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;

/**
 * @author woodwhales on 2020-12-13 16:32
 */
public class CollectionMathResult implements CollectionMath {

    /**
     * 集合 A
     */
    private List sourceList1;

    /**
     * 集合 B
     */
    private List sourceList2;

    /**
     * 交集
     */
    private Set> intersectionSet;

    /**
     * 并集
     */
    private Set> unionSet;

    /**
     * 正差集 A - B
     */
    private Set> positiveDifferenceSet;

    /**
     * 负差集 B - A
     */
    private Set> negativeDifferenceSet;

    /**
     * 是否懒计算
     * 是 - 每调用方法时计算
     * 否 - new 实例完成时初始化
     */
    private boolean lazyCompute;

    /**
     * 数据源集合 A 生成 set 集合的接口
     */
    private Function keyFunction1;

    /**
     * 数据源集合 B 生成 set 集合的接口
     */
    private Function keyFunction2;

    /**
     * 集合操作
     * @param sourceList1 集合 A
     * @param keyFunction1 集合 A 生成 set 的接口
     * @param sourceList2 集合 B
     * @param keyFunction2 集合 B 生成 set 的接口
     * @param  要比较的数据类型
     * @param  集合 A 的数据类型
     * @param  集合 B 的数据类型
     * @return CollectionMathResult
     */
    public static  CollectionMathResult compute(List sourceList1,
                                                                  Function keyFunction1,
                                                                  List sourceList2,
                                                                  Function keyFunction2) {
        return compute(sourceList1, keyFunction1, sourceList2, keyFunction2, false);
    }

    /**
     * 集合操作
     * @param sourceList1 集合 A
     * @param keyFunction1 集合 A 生成 set 的接口
     * @param sourceList2 集合 B
     * @param keyFunction2 集合 B 生成 set 的接口
     * @param lazyCompute 是否懒计算
     * @param  要比较的数据类型
     * @param  集合 A 的数据类型
     * @param  集合 B 的数据类型
     * @return CollectionMathResult
     */
    public static  CollectionMathResult compute(List sourceList1,
                                                                  Function keyFunction1,
                                                                  List sourceList2,
                                                                  Function keyFunction2,
                                                                  final boolean lazyCompute) {
        CollectionMathResult collectionMathResult = new CollectionMathResult<>(sourceList1, keyFunction1,
                                                                                        sourceList2, keyFunction2,
                                                                                        lazyCompute);
        if(lazyCompute) {
            return collectionMathResult;
        }

        if(isNotEmpty(sourceList1) && isEmpty(sourceList2)) {
            checkNotNull(keyFunction1, "keyFunction1 不允许为空");
            Set> set = DataTool.toSet(sourceList1, source1 -> CollectionContainer.build(source1, keyFunction1));
            collectionMathResult.setUnionSet(set)
                    .setPositiveDifferenceSet(set)
                    .setIntersectionSet(emptySet())
                    .setNegativeDifferenceSet(emptySet());
            return collectionMathResult;
        }

        if(isEmpty(sourceList1) && isNotEmpty(sourceList2)) {
            checkNotNull(keyFunction1, "keyFunction2 不允许为空");
            Set> set = DataTool.toSet(sourceList2, source2 -> CollectionContainer.build(source2, keyFunction2));
            collectionMathResult.setUnionSet(set)
                    .setPositiveDifferenceSet(emptySet())
                    .setIntersectionSet(emptySet())
                    .setNegativeDifferenceSet(set);
            return collectionMathResult;
        }

        checkNotNull(keyFunction1, "keyFunction1 不允许为空");
        checkNotNull(keyFunction1, "keyFunction2 不允许为空");

        Set> set1 = DataTool.toSet(sourceList1, source1 -> CollectionContainer.build(source1, keyFunction1));
        Set> set2 = DataTool.toSet(sourceList2, source2 -> CollectionContainer.build(source2, keyFunction2));
        collectionMathResult.setPositiveDifferenceSet(Sets.difference(set1, set2))
                .setNegativeDifferenceSet(Sets.difference(set2, set1))
                .setUnionSet(Sets.union(set1, set2))
                .setIntersectionSet(Sets.intersection(set1, set2));
        return collectionMathResult;
    }

    public List getSourceList1() {
        return sourceList1;
    }

    public List getSourceList2() {
        return sourceList2;
    }

    @Override
    public Set> getIntersectionSet() {
        return getSet(intersectionSet, (set1, set2) -> Sets.intersection(set1, set2));
    }

    @Override
    public Set getIntersectionKeySet() {
        return getKeySet(intersectionSet, getIntersectionSet());
    }

    public CollectionMathResult setIntersectionSet(Set> intersectionSet) {
        this.intersectionSet = intersectionSet;
        return this;
    }

    @Override
    public Set getUnionKeySet() {
        return getKeySet(unionSet, getUnionSet());
    }

    @Override
    public Set> getUnionSet() {
        return getSet(unionSet, Sets::union);
    }

    public CollectionMathResult setUnionSet(Set> unionSet) {
        this.unionSet = unionSet;
        return this;
    }

    /**
     * 正差集 A - B
     * @return 正差集 A - B
     */
    @Override
    public Set getPositiveDifferenceKeySet() {
        return getKeySet(positiveDifferenceSet, getPositiveDifferenceSet());
    }

    /**
     * 正差集 A - B
     * @return 正差集 A - B
     */
    @Override
    public List getPositiveDifferenceList() {
        return getList(this.sourceList1, getPositiveDifferenceSet(), keyFunction1);
    }

    /**
     * 正差集 A - B
     * @return 正差集 A - B
     */
    @Override
    public Set> getPositiveDifferenceSet() {
        return getSet(positiveDifferenceSet, (set1, set2) -> CollectionTool.difference(set1, set2));
    }

    /**
     * 负差集 B - A
     * @return 负差集 B - A
     */
    @Override
    public Set getNegativeDifferenceKeySet() {
        return getKeySet(negativeDifferenceSet, getNegativeDifferenceSet());
    }

    /**
     * 负差集 B - A
     * @return 负差集 B - A
     */
    @Override
    public List getNegativeDifferenceList() {
        return getList(this.sourceList2, getNegativeDifferenceSet(), keyFunction2);
    }

    /**
     * 负差集 B - A
     * @return 负差集 B - A
     */
    @Override
    public Set> getNegativeDifferenceSet() {
        return getSet(negativeDifferenceSet, (set1, set2) -> CollectionTool.difference(set2, set1));
    }

    private static  CollectionMathResult empty() {
        return new CollectionMathResult()
                .setIntersectionSet(emptySet())
                .setUnionSet(emptySet())
                .setPositiveDifferenceSet(emptySet())
                .setNegativeDifferenceSet(emptySet());
    }

    private CollectionMathResult(List sourceList1,
                                 Function keyFunction1,
                                 List sourceList2,
                                 Function keyFunction2,
                                 final boolean lazyCompute) {
        this.sourceList1 = sourceList1;
        this.keyFunction1 = keyFunction1;
        this.sourceList2 = sourceList2;
        this.keyFunction2 = keyFunction2;
        this.lazyCompute = lazyCompute;
    }

    private CollectionMathResult() {
    }

    private Set getKeySet(Set> set, Set> keySet) {
        if (this.lazyCompute) {
            return keySet.stream()
                    .map(CollectionFieldComparable::getDataKey)
                    .collect(Collectors.toSet());
        }
        return getKeySet(set);
    }

    private Set getKeySet(Set> set) {
        return CollectionTool.toSet(set, CollectionFieldComparable::getDataKey);
    }

    private Set> getSet(Set> set,
                                                     BinaryOperator>> setFunction) {
        if(!lazyCompute) {
            return set;
        }
        Set> set1 = DataTool.toSet(sourceList1, source1 -> CollectionContainer.build(source1, keyFunction1));
        Set> set2 = DataTool.toSet(sourceList2, source2 -> CollectionContainer.build(source2, keyFunction2));
        return setFunction.apply(set1, set2);
    }

    private  List getList(List list, Set> set, Function keyFunction) {
        if(isEmpty(list)) {
            return emptyList();
        }

        Set keySet = set.stream()
                            .map(CollectionFieldComparable::getDataKey)
                            .collect(Collectors.toSet());

        return DataTool.filter(list, source -> keySet.contains(keyFunction.apply(source)));
    }

    public CollectionMathResult setPositiveDifferenceSet(Set> positiveDifferenceSet) {
        this.positiveDifferenceSet = positiveDifferenceSet;
        return this;
    }

    public CollectionMathResult setNegativeDifferenceSet(Set> negativeDifferenceSet) {
        this.negativeDifferenceSet = negativeDifferenceSet;
        return this;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy