java集合详解(集合与其它数据结构体之间的转换)——全网最通俗易懂的讲解(上)

1. 集合的交集、并集、补集、差集

1.1 概念

Java List 集合取 交集、并集、差集、补集的概念定义:
交集: 取2个集合中,相同的部分 (A 交集 B,取 A和B 中相同的元素)
并集: 将2个集合,合并为一个集合中
差集: 取2个集合中,不相同的部分 (A差集 B,取 A中与B不相同的元素)
补集: 取2个集合中,不相同的部分 ,组成新集合 ( A 差集 B 并 B 差集 A)

在这里插入图片描述

专业词汇

并集 = union
交集 = intersection
补集 = complement
析取,补集 = disjunction
减去 = subtract

数据准备:

首先我们定义两个list集合, 通过循环都可以实现上述集合运算,因此通过循环方法本文就不列出了。
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
ArrayList<Integer> list2 = new ArrayList<Integer>( Arrays.asList(3,4,5));

// 引入的包
<dependency>
  <groupId>commons-collections</groupId>
  <artifactId>commons-collections</artifactId>
  <version>3.2.2</version>
</dependency>
通过CollectionUtils工具包 (推荐),需要引入CollectionUtils 工具包

1.2 交集

1. 通过CollUtil的工具类

(1)不去重交集

public static Collection intersection(Collection coll1, Collection coll2);

解析:

两个集合的交集 针对一个集合中存在多个相同元素的情况,计算两个集合中此元素的个数,保留最少的个数
 例如:集合1[a, b, c, c, c],集合2[a, b, c, c] 结果:[a, b, c, c],此结果中只保留了两个c
Params: coll1 – 集合1, coll2 – 集合2
Type parameters: <T> – 集合元素类型
Returns: 交集的集合,返回 ArrayList

案例:

    @Test
    public void test12(){
   
        List<String> A = Arrays.asList("a", "b", "c", "c", "c");
        List<String> B = Arrays.asList("a", "b", "c", "c");
        Collection<String> result = CollUtil.intersection(A, B);
        System.out.println("result:  "+result);
    }
   result:  [a, b, c, c]

(2)去重交集

public static Set intersectionDistinct(Collection coll1,Collection coll2, Collection… otherColls)

两个集合的交集,仅仅保留两个集合中相同的部分,每个相同的元素只保留一个,即去重
 例如:集合1[a, b, c, c, c],集合2[a, b, c, c] 结果:[a, b, c],此结果中只保留了a,b,c三个元素
Params: coll1 – 集合1, coll2 – 集合2
Type parameters: <T> – 集合元素类型
Returns: 交集的集合,返回 ArrayList

案例:

    @Test
    public void test13(){
   
        List<String> A = Arrays.asList("a", "b", "c", "c", "c");
        List<String> B = Arrays.asList("a", "b", "c", "c");
        Set<String> result = CollUtil.intersectionDistinct(A, B);
        System.out.println("result:  "+result);
    }
   result:  [a, b, c]

(3)求多个集合的交集

public static Collection intersection(Collection coll1, Collection coll2, Collection… otherColls)

两多集合的交集,仅仅保留多个集合中相同的部分,每个相同的元素只保留一个,即去重
 例如:集合1[a, b, c, c, c],集合2[a, b, c, c] ,集合2[a, b, c, c] ,集合2[e, b, g, c]
  结果:[b, c],此结果中只保留了b和c元素
Params: coll1 – 集合1, coll2 – 集合2,otherColl-是一个可变参数,可以同时传多个集合进行求并集
Type parameters: <T> – 集合元素类型
Returns: 交集的集合,返回 ArrayList

案例:

@Test
    public void test15(){
   
        List<String> A = Arrays.asList("a", "b", "c", "c", "c");
        List<String> B = Arrays.asList("a", "b", "c", "c");
        List<String> C = Arrays.asList("a", "b", "c", "c");
        List<String> D = Arrays.asList("e", "b", "g", "c");
        Collection<String> result = CollUtil.intersection(A, B, C, D);
        System.out.println("result:  "+result);
    }
    result:  [b, c]

2. 通过CollectionUtils的工具类

Collection intersection = CollectionUtils.intersection(list1, list2);
System.out.println("intersection CollectionUtils 交集结果是: " + intersection);
------------
intersection CollectionUtils 交集结果是: [3]

注意:使用这种方式并不能做到取完交集后去重重复的元素

 List<String> A = Arrays.asList("a", "b", "c", "c", "c");
 List<String> B = Arrays.asList("a", "b", "c", "c");
 Collection<String> result  = CollectionUtils.intersection(A, B);
 System.out.println("result:  "+result);
 result:  [a, b, c, c]

3. 通过List集合的retainAll方法

注意:使用这种方式并不能做到取完交集后去重重复的元素

@Test
    public void test10(){
   
        ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 3));
        ArrayList<Integer> list2 = new ArrayList<Integer>( Arrays.asList(3,4,5));
        boolean b = list1.retainAll(list2);
        System.out.println("list1 retainAll 方法 交集结果是: " + list1);
        System.out.println("list2: " + list2);
    }
----------
list1 retainAll 方法 交集结果是: [3, 3]
list2: [3, 4, 5]

注意:通过retainAll方法,会修改原集合。即修改调用retainAll集合的内容,最终的结果是谁调用retainAll方法,谁的最终结果就是交集后的结果

4. 其它求交集的方式(了解)

(1)内置函数实现

1、removeAll方法:从list中删除指定集合中包含的所有元素。
2、retainAll方法:从list中删除指定集合中不包含的所有元素。
3、addAll方法:用来向Set集合添加另一个集合对象所包含的所有内容

public class CollectionTest {
   
 
    public static void main(String[] args) {
   
        List<String> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
 
        list1.add("a");
        list1.add("b");
        list1.add("c");
 
        list2.add("b");
        list2.add("e");
        list2.add("d");
 
        //求交集
        list1.retainAll(list2);
        System.out.println(list1.toString()); // b
 
        //求并集
        list1.removeAll(list2);
        list1.addAll(list2);
        System.out.println(list1.toString());  // a c b e d
 
        //求差集(list1有而list2没有)
        list1.removeAll(list2);   // a c
 
    }
}

(2)for循环遍历实现 求两个集合的交集
利用集合的contains方法,来对比第二个集合中是否存在相同的元素的方法,同时将交集结果返回。时间复杂度是O(n)。
contains方法:用于判断list集合是否包含某个元素。

public List<Object> intersectionForList_1(List<Object> arr1, List<Object> arr2) {
   
    long startTime = System.currentTimeMillis();
    List<Object> result = new ArrayList<>();
    for (Object arr : arr1) {
   
        if (arr2.contains(arr)) {
   
            result.add(arr);
         }
    }
    long endTime = System.currentTimeMillis();
    log.info("intersectionForList_1:" + (endTime - startTime));
    return result;
}

(3)、使用Java 8 Stream API 求两个集合的交集
首先把两个集合转换成Stream,然后使用filter()方法筛选出交集元素,最后把结果转换成集合。 时间复杂度是O(n)。
.stream().filter()方法:来筛选出满足条件的对象,最终返回的筛选过后的列表。
Collectors.toList()和Collectors.toSet()方法都是将map后的stream转换为一个列表对象,toSet()会去重重复的对象

Set<Integer> set1 = new HashSet<>();
set1.add(1);
set1.add(2);
set1.add(3);
set1.add(4);

Set<Integer> set2 = new HashSet<>();
set2.add(3);
set2.add(4);
set2.add(5);
Set<Integer> intersection = set1.stream().filter(set2::contains).collect(Collectors.toSet());
System.out.println(intersection); // 输出 [3, 4]

(4)使用迭代器求两个集合的交集

public List<Object> intersectionForList_2(List<Object> arr1, List<Object> arr2) {
   

      List<Object> resultList = new ArrayList<>();
 
      List<Object> maxList;
      List<Object> minList;
      if (arr1.size()>arr2.size()){
   
          maxList = arr1;
          minList = arr2;
      }else {
   
          maxList = arr2;
          minList = arr1;
      }
 
      Iterator<Object> iterator = maxList.iterator();
      while (iterator.hasNext()){
   
          Object next = iterator.next();
          if (minList.contains(next)){
   
              resultList.add(next);
          }
      }

      return resultList;
  }

(5)使用map 求两个集合的交集
首先将list集合中的元素依次存入一个map中去,然后再以map的get方法来判断是否存在这样的元素。
这种方法的效率最高,在10万条数据的测试下,这种方法耗时仅仅在十几毫秒,而其他方法在将近一百多毫秒。
在百万条数据进行对比处理的时候,使用map特性的方法时间消耗大概在40毫秒左右,但是其他方法要将近10秒钟,
所以在对于大量数据的处理过程中,还是非常建议使用这种方法的。

public List<Object> intersectionForList_3(List<Object> arr1, List<Object> arr2) {
   

    List<Object> resultList = new ArrayList<>();
    Map<String,Object> map = new HashMap<>();
    arr1.forEach(a1->{
   
         map.put(a1+"",a1);
    });
 
    arr2.forEach(a2->{
   
        Object obj = map.get(a2 + "");
        if (obj!=null){
   
            resultList.add(obj);
        }
    });

    return resultList;
}

(6)取交集 — 手动遍历集合实现

/**@Description: 取交集
 * @version v1.0
 * @author wu
 * @date 2022/7/30 22:41
 */
@Test
public void intersectionTest1(){
   
    ArrayList<Object> destList = Lists.newArrayList();
    for (Integer e1 : list1) {
   
        for (Integer e2 : list2) {
   
            if(e1.equals(e2)){
   
                destList.add(e1);
            }
        }
    }
    System.out.println("intersectionTest1 交集结果是: " + destList);
 
    list1.retainAll(list2);
    System.out.println("intersectionTest1 retainAll 方法 交集结果是: " + list1);
}

(7)取交集 — 通用方法 实现
list1 交集 list2 ,不用生成新的list ,使用 迭代器 Iterator 删除 list1中和list2 不相同的元素。

   /**
     * Description: 测试 通用List集合取值交集的方法
     * @return  void
     * @version v1.0
     * @author wu
     * @date 2022/11/15 22:15
     */
    @Test
    public void intersectionListTest() throws Exception {
   
        System.out.println("srcList : \n"+ JSON.toJSONString(list));
        System.out.println("subList : \n"+ JSON.toJSONString(subList));
 
        intersectionList(list,subList,(t1,t2)->{
   
           if(t1.equals(t2)){
   
               return 0;
           }
          return -1;
        });
 
    }
 
    /**
     * Description: 通用List集合取值交集的方法
     * @param srcList
     * @param subList
     * @param comparator
     * @return  void
     * @version v1.0
     * @author wu
     * @date 2022/11/15 22:05
     */
    public <E>void intersectionList(List<E> srcList , List<E> subList , Comparator<E> comparator){
   
        for (Iterator<E> it = srcList.iterator(); it.hasNext(); ) {
   
            final E next = it.next();
            boolean isMatch = false;
            for (E e : subList) {
   
                if(comparator.compare(next,e) == 0){
   
                    isMatch = true;
                    break;
                }
            }
            if(!isMatch){
   
                it.remove();
            }
        }
        System.out.println("srcList 交集后: \n"+ JSON.toJSONString(list));
        System.out.println("subList 交集后: \n"+ JSON.toJSONString(subList));
    }              

1.3 并集

1. 通过CollUtil的工具类

(1)不去重并集
API

public static Collection union(Collection coll1,Collection coll2);

解析:

两个集合的并集 针对一个集合中存在多个相同元素的情况,计算两个集合中此元素的个数,保留最多的个数 
例如:集合1[a, b, c, c, c],集合2[a, b, e, c] 结果:[a, b, c, c,
  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值