java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java List集合取交集

Java List集合取交集的8种不同实现方式总结

作者:码到三十五

工作中经常遇到需要取两个集合之间的交集、差集情况,下面这篇文章主要给大家总结介绍了关于Java List集合取交集的8种不同实现方式,文中通过代码介绍的非常详细,需要的朋友可以参考下

方法一:使用Java 8的Stream API

这种方法利用Stream API的filter和collect操作来找到两个列表的交集。

List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(4, 5, 6, 7, 8);

List<Integer> intersection = list1.stream()
        .filter(list2::contains)
        .collect(Collectors.toList());

方法二:使用传统的for循环遍历

这种方法通过遍历一个列表,并检查其元素是否存在于另一个列表中来实现交集。

List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(4, 5, 6, 7, 8);
List<Integer> intersection = new ArrayList<>();

for (Integer item : list1) {
    if (list2.contains(item)) {
        intersection.add(item);
    }
}

使用HashSet优化遍历方法:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ListIntersection {
    public static void main(String[] args) {
        List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> list2 = Arrays.asList(4, 5, 6, 7, 8);

        Set<Integer> set1 = new HashSet<>(list1);
        List<Integer> intersection = new ArrayList<>();

        for (Integer num : list2) {
            if (set1.contains(num)) {
                intersection.add(num);
            }
        }

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

list1转换为HashSet,以提高查找效率。然后,我们遍历list2,并检查其元素是否存在于set1中。如果存在,则将其添加到交集列表中。请注意,由于HashSet不保证元素的顺序,因此交集列表中的元素顺序可能与原始列表不同。如果需要保持顺序,可以使用LinkedHashSet代替HashSet

方法三:使用Set的retainAll方法

这种方法首先将两个列表转换为Set,然后利用Set的retainAll方法来找到交集。retainAll方法会保留在指定集合(参数)中存在的元素。

List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(4, 5, 6, 7, 8);

Set<Integer> set1 = new HashSet<>(list1);
Set<Integer> set2 = new HashSet<>(list2);
set1.retainAll(set2); // set1现在只包含交集元素

List<Integer> intersection = new ArrayList<>(set1);

方法四:使用Java的CollectionUtils(Apache Commons Collections)

如果你的项目中已经包含了Apache Commons Collections库,你可以使用其提供的CollectionUtils类来方便地找到交集。

import org.apache.commons.collections4.CollectionUtils;

List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(4, 5, 6, 7, 8);

List<Integer> intersection = (List<Integer>) CollectionUtils.intersection(list1, list2);

注意:Apache Commons Collections库中的intersection方法返回的是java.util.Collection类型,所以需要进行类型转换。

方法五:使用Java Stream API的anyMatch

之前已经用filter方法展示了如何使用Stream API找交集,但其实也可以用anyMatch来实现类似的功能。不过,这种方法通常不是最高效的,因为它需要对每个元素进行遍历检查。

List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(4, 5, 6, 7, 8);

List<Integer> intersection = list1.stream()
    .filter(item -> list2.stream().anyMatch(item::equals))
    .collect(Collectors.toList());

注意:这种方法的时间复杂度较高,因为对于list1中的每个元素,它都会遍历整个list2。因此,对于大型列表,这种方法不推荐使用。

方法六:使用Java 8的并行流(Parallel Streams)

如果列表很大,并且你的机器有多个处理器核心,你可以考虑使用并行流来加速交集的计算。

List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(4, 5, 6, 7, 8);

Set<Integer> set2 = new HashSet<>(list2); // 使用HashSet提高查找效率

List<Integer> intersection = list1.parallelStream()
    .filter(set2::contains)
    .collect(Collectors.toList());

注意:并行流并不总是比顺序流更快,特别是在处理小数据集或数据集不适合并行处理时。此外,并行流的使用也会增加线程的开销。

方法七:使用Java的并发工具类

如果你在处理非常大的数据集,并且希望利用多核处理器的能力,你可以考虑使用Java的并发工具类,如ForkJoinPool,来并行计算交集。

这种方法比较复杂,通常用于高级并发编程场景。基本思路是将大任务拆分成小任务,然后使用ForkJoinPool来并行处理这些小任务,并最终合并结果。

方法八:使用第三方库(如Guava)

除了Apache Commons Collections,还有其他第三方库如Guava也提供了集合操作的工具类。

例如,使用Guava的Sets.intersection(Set<E> set1, Set<E> set2)方法可以很容易地找到两个集合的交集:

import com.google.common.collect.Sets;

List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(4, 5, 6, 7, 8);

Set<Integer> set1 = new HashSet<>(list1);
Set<Integer> set2 = new HashSet<>(list2);

Set<Integer> intersectionSet = Sets.intersection(set1, set2);
List<Integer> intersection = new ArrayList<>(intersectionSet);

注意:Guava的Sets.intersection方法返回的是一个不可修改的视图,它表示两个原始集合的交集。这个视图会随着原始集合的变化而变化,但它本身不占用额外的空间。如果你需要一个独立的交集集合,可以像上面那样将其复制到一个新的ArrayList中。

通过以上方法的介绍和实践,希望能够帮助你更好地理解Java中List集合交集的计算,并能够在实际开发中灵活运用。

附:Java两个较大的List快速取交集

public static void main(String[] args) {
        //模拟数据
        List<Integer> list1 = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();
        for (int i = 1; i <= 1000000; i++) {
            list1.add(i);
            list2.add(1000000 - i);
        }
        //记录开始时间
        long startTime = System.currentTimeMillis();
        //最后结果集
        List<Integer> resultList = new ArrayList<>();
        //中间存储
        Map<String, Integer> map = new HashMap<>();

        list2.forEach(i2 -> {
            map.put(i2 + "", i2);
        });

        list1.forEach(i1 -> {
            Integer m = map.get(i1 + "");
            //如果不为空,则证明list1和list2都拥有该数据
            if (m != null) {
                resultList.add(i1);
            }
        });
        System.out.println("耗时:" + (System.currentTimeMillis() - startTime) + "ms");
        System.out.println(resultList.size());
    } 

运行结果 

总结

到此这篇关于Java List集合取交集的8种不同实现方式的文章就介绍到这了,更多相关Java List集合取交集内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文