Java代码-List集合求交集、补集(差集)

关键字

代码、代码片段、集合、交集、差集、补集

场景

很多人写Java代码时,都比较喜欢用List集合,而不是用Set集合,虽然应该Set集合的不重复特性更符合他的业务场景。虽然教科书式的Java教程叫我们重写equals、hashCode方法,但实际上有些人却不想这么干。

下面的代码片段,特点在于使用自定义的java.util.function.BiPredicate(jdk8+才有这个类)接口来为两个java.util.List计算交集、补集(差集)。BiPredicate接口可以自己实现test方法逻辑,返回boolean,以判定List中的元素是否相同。

上代码

	/**
     * 取{@code firstList}参数与{@code secondList}参数的交集
     *
     * <p>通过传入{@link BiPredicate}接口的实现,自定义判断 {@code firstList}与{@code secondList}的哪些元素相同。
     * 效果类似于实现了{@code T}的{@code equals}方法,但此方法的优点是不要求你这么做,可以让你通过{@link BiPredicate}接口无侵入式的自定义{@code equals}逻辑。</p>
     * <p>假设{@code firstList}中的元素为[1,2,3],{@code secondList}中的元素为[2,3,4],则返回{@code firstList}中的[2,3]</p>
     *
     * @param firstList 第一个集合
     * @param secondList 第二个集合
     * @param equalPredicate 判断两个元素是否相同
     * @return 返回 {@link ArrayList}实例,其中的元素是{@code firstList}参数与{@code secondList}的交集。注意,{@link ArrayList}实例中的元素引用来源于{@code firstList}而不是{@code secondList}
     * @throws NullPointerException 如果<code>firstList</code>、<code>secondList</code>、<code>equalPredicate</code>参数为null
     * @author laozhu
     */
    public  static <T> ArrayList<T> retain(List<T> firstList, List<T> secondList, BiPredicate<T,T> equalPredicate){
        Objects.requireNonNull(firstList);
        Objects.requireNonNull(secondList);
        Objects.requireNonNull(equalPredicate);

        ArrayList<T> resultList = new ArrayList<>();

        for(int i = 0; i < firstList.size();  i++){
            for(int j = 0; j < secondList.size();  j++){
                if(equalPredicate.test(firstList.get(i),secondList.get(j))){
                    //相同元素
                    resultList.add(firstList.get(i));
                    //break能够防止secondList中有重复的元素,导致resultList中添加了两个相同的firstList中的元素
                    break;
                }
            }
        }
        return resultList;
    }

    /**
     * 取{@code firstList}参数与{@code secondList}的补集(又叫差集)
     *
     * <p>通过传入{@link BiPredicate}接口的实现,自定义判断 {@code firstList}与{@code secondList}的哪些元素相同。
     * 效果类似于实现了{@code T}的{@code equals}方法,但此方法的优点是不要求你这么做,可以让你通过{@link BiPredicate}接口无侵入式的自定义{@code equals}逻辑。</p>
     * <p>假设{@code firstList}中的元素为[1,2,3],{@code secondList}中的元素为[2,3,4],则返回{@code firstList}中的[1]</p>
     *
     * @param firstList 第一个集合
     * @param secondList 第二个集合
     * @param equalPredicate 判断两个元素是否相同
     * @return 返回 {@link ArrayList}实例,其中的元素是{@code firstList}参数与{@code secondList}的补集(又叫差集)。注意,{@link ArrayList}实例中的元素引用来源于{@code firstList}而不是{@code secondList}
     * @throws NullPointerException 如果<code>firstList</code>、<code>secondList</code>、<code>equalPredicate</code>参数为null
     * @author laozhu
     */
    public  static <T> List<T>  diff(List<T> firstList, List<T> secondList, BiPredicate<T,T> equalPredicate){
        Objects.requireNonNull(firstList);
        Objects.requireNonNull(secondList);
        Objects.requireNonNull(equalPredicate);

        ArrayList<T> resultList = new ArrayList<>();

        for(int i = 0; i < firstList.size();  i++){
            boolean hasEqualElementInSecondList = false;
            for(int j = 0; j < secondList.size();  j++){
                if(equalPredicate.test(firstList.get(i),secondList.get(j))){
                    //相同元素
                    hasEqualElementInSecondList = true;
                    break;
                }
            }
            if(!hasEqualElementInSecondList){
                resultList.add(firstList.get(i));
            }
        }
        return resultList;
    }

调用示例

交集

代码:

public class HelloWorld {

    public static void main(String[] args) {
        Student s1 = new Student("100","zhangsan");
        Student s2 = new Student("101","zhangsan");
        Student s3 = new Student("102","zhangsan");
        Student s4 = new Student("103","zhangsan");

        List<Student> list1 = Arrays.asList(s1,s2);
        List<Student> list2 = Arrays.asList(s2,s3,s4);

        List result = SetUtil.retain(list1,list2,(a,b)->a.getSid().equals(b.getSid()));

        System.out.println("交集:");
        System.out.println(result);
    }

}

打印结果:

交集:
[Student{sid='101', name='zhangsan'}]

补集(差集)

代码:

public class HelloWorld {

    public static void main(String[] args) {
        Student s1 = new Student("100","zhangsan");
        Student s2 = new Student("101","zhangsan");
        Student s3 = new Student("102","zhangsan");
        Student s4 = new Student("103","zhangsan");

        List<Student> list1 = Arrays.asList(s1,s2);
        List<Student> list2 = Arrays.asList(s2,s3,s4);

        List result = SetUtil.diff(list1,list2,(a,b)->a.getSid().equals(b.getSid()));

        System.out.println("补集(差集):");
        System.out.println(result);
    }

}

打印结果:

补集(差集):
[Student{sid='100', name='zhangsan'}]
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值