• java 两个list 交集 并集 差集 去重复并集


      

      前提需要明白List是引用类型,引用类型采用引用传递。

      我们经常会遇到一些需求求集合的交集、差集、并集。例如下面两个集合:

            List<String> list1 = new ArrayList<String>();
            list1.add("A");
            list1.add("B");
    
            List<String> list2 = new ArrayList<String>();
            list2.add("B");
            list2.add("C");

     0.求差集

      例如,求List1中有的但是List2中没有的元素:

        public static void test3(List list1, List list2) {
            list1.removeAll(list2);
            System.out.println(list1);
        }

    结果:

    [A]

    查看ArrayList的removeAll的源码

        public boolean removeAll(Collection<?> c) {
            Objects.requireNonNull(c);
            return batchRemove(c, false);
        } 

    再查看batchRemove的源码:(如果传的第二个参数是false,保留差集;如果传的是true,保留的是交集)

        private boolean batchRemove(Collection<?> c, boolean complement) {
            final Object[] elementData = this.elementData;
            int r = 0, w = 0;
            boolean modified = false;
            try {
                for (; r < size; r++)
                    if (c.contains(elementData[r]) == complement)
                        elementData[w++] = elementData[r];
            } finally {
                // Preserve behavioral compatibility with AbstractCollection,
                // even if c.contains() throws.
                if (r != size) {
                    System.arraycopy(elementData, r,
                                     elementData, w,
                                     size - r);
                    w += size - r;
                }
                if (w != size) {
                    // clear to let GC do its work
                    for (int i = w; i < size; i++)
                        elementData[i] = null;
                    modCount += size - w;
                    size = w;
                    modified = true;
                }
            }
            return modified;
        }

      是重新定义elementData数组的元素,下面代码的作用是将本集合中不包含另一个集合的元素重新加入元素,以此实现删除的功能(注意上面调用的方法传的参数是false,也就是不包含的元素得以保留,实现差集的功能)

    if (c.contains(elementData[r]) == complement)
    elementData[w++] = elementData[r];

    1.求并集(不去重)---将一个集合全部加入另一个集合

        public static void test(List list1, List list2) {
            list1.addAll(list2);
            System.out.println(list1);
        }

    结果:

    [A, B, B, C]

    查看ArayList的addAll()源码是数组复制:

        public boolean addAll(Collection<? extends E> c) {
            Object[] a = c.toArray();
            int numNew = a.length;
            ensureCapacityInternal(size + numNew);  // Increments modCount
            System.arraycopy(a, 0, elementData, size, numNew);
            size += numNew;
            return numNew != 0;
        }

    再查看System的arraycopy发现是一个native方法(本地方法):---其实system类的好多方法都是native方法

        public static native void arraycopy(Object src,  int  srcPos,
                                            Object dest, int destPos,
                                            int length);

    2.求并集(去重)

      例如:求List1和List2的并集,并实现去重。

        思路是:先将list中与list2重复的去掉,之后将list2的元素全部添加进去。

        public static void test1(List list1, List list2) {
            list1.removeAll(list2);
            list1.addAll(list2);
            System.out.println(list1);
        }

    结果:

    [A, B, C]

    3.求交集

      例如:求List1和List2中都有的元素。

        public static void test2(List list1, List list2) {
            list1.retainAll(list2);
            System.out.println(list1);
        }

    结果:

    [B]

    在上面2的实验过程中,我们知道batchRemove(Collection,true)也是求交集,所以猜想  retainAll 内部应该是调用 batchRemove(Collection,true),查看ArrayList的源码如下:

        public boolean retainAll(Collection<?> c) {
            Objects.requireNonNull(c);
            return batchRemove(c, true);
        }
  • 相关阅读:
    Redis缓存穿透、缓存雪崩、redis并发问题 并发竞争key的解决方案 (阿里)
    CAP原则 (阿里)
    分布式系统一致性问题解决实战(阿里) 异步解耦+消息队列可作为分布式系统满足最终一致性的优秀方案
    高并发&高可用系统的常见应对策略 秒杀等-(阿里)
    Redis的内存回收策略和内存上限(阿里)
    如何保证MQ的顺序性?比如Kafka
    spring的controller默认是单例还是多例
    HashMap线程不安全的体现
    TCP的三次握手与四次挥手
    常见排序算法及对应的时间复杂度和空间复杂度
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/9812919.html
Copyright © 2020-2023  润新知