统计两组数据的交集和补集(新旧数据的差异比较算法)遍历一次

旧数据A = {}
新数据B = {}

新增项:B - A = { x | x∈B且x∉A}
删除项:A - B = { x | x∈A且x∉B}
共有项:B ∩ A = { x | x∈B且x∈A}

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class RecordDiff {
    public static void main(String[] args) {

        // 根据新数据对旧数据的改变进行统计:新旧项来自数据库约束为自增长整数的原始键字段,即不重复整数,已升序排序

        Integer[] as = new Integer[] { 1, 2, 3, 8, 9, 12 };
        Integer[] bs = new Integer[] { 1, 2, 3, 9, 10, 12, 18, 22 };
        // bs = new Integer[] { 1, 2, 3, 9 };
        System.out.println("旧项:" + Arrays.toString(as));
        System.out.println("新项:" + Arrays.toString(bs));
        System.out.println("====================");
        List<Integer> aList = Arrays.asList(as);// old data
        List<Integer> bList = Arrays.asList(bs);// new data

        Diff<Integer> diff1 = Diff.difference(aList, bList);

        System.out.println("都有项:" + Arrays.toString(diff1.unionList.toArray()));
        System.out.println("新增项:" + Arrays.toString(diff1.addedList.toArray()));
        System.out.println("删除项:" + Arrays.toString(diff1.removedList.toArray()));
        System.out.println("====================");

        List<Integer> fromOnlyList = new ArrayList<Integer>();
        List<Integer> againstOnlyList = new ArrayList<Integer>();
        List<Integer> bothList = new ArrayList<Integer>();
        Diff.diff(aList, bList, fromOnlyList, againstOnlyList, bothList);
        System.out.println("都有项:" + Arrays.toString(bothList.toArray()));
        System.out.println("新增项:" + Arrays.toString(againstOnlyList.toArray()));
        System.out.println("删除项:" + Arrays.toString(fromOnlyList.toArray()));
    }

    /**
     * 对两组数据进行差异比较,得出新旧的差异:都有项,新增项,删除项
     *
     * @author fangss
     *
     * @param <T>
     */
    public static class Diff<T extends Comparable<T>> {
        /** 共有项 */
        List<T> unionList;
        /** 差异项 */
        List<T> addedList, removedList;

        /**
         *
         * @param unionList
         *          接受都有项的结果Buffer
         * @param addedList
         *          接受新增项的结果Buffer
         * @param removedList
         *          接受删除项的结果Buffer
         */
        public Diff(List<T> unionList, List<T> addedList, List<T> removedList) {
            super();
            this.unionList = unionList;
            this.addedList = addedList;
            this.removedList = removedList;
        }

        /**
         * 新旧数据列表两个都只遍历一次,适用于数据只能向前滚动一次,如读文件行 <br>
         * A B 6 1 7 \ 2 8 \ 3 9 \ 5 10 . 6 11 . 10 12 16 17 18
         *
         * @param fromList
         *          必须有序,且升序,一般是旧数据, The List to compare from
         * @param againstList
         *          必须有序,且升序,一般是新数据 A List to compare against
         * @param fromOnlyList
         *          补集
         * @param againstOnlyList
         *          补集
         * @param bothList
         *          交集
         */
        public static <T extends Comparable<T>> void diff(List<T> fromList, List<T> againstList, List<T> fromOnlyList,
                List<T> againstOnlyList, List<T> bothList) {

            // 0 - both, ‘f‘ - from, ‘a‘ - against, 和比较结果一致:一样大小都移动,否则谁小谁移动
            int whoMakeWay = ‘b‘;
            Iterator<T> fromIterator = fromList.iterator();
            Iterator<T> againstIterator = againstList.iterator();

            T from = null, against = null;
            while (true) {
                T fromNext = null;
                if (‘a‘ != whoMakeWay) {
                    if (hasNextOrExhaustRival(fromIterator, null, againstIterator, againstOnlyList)) {
                        from = fromIterator.next();
                        fromNext = from;
                    } else {
                        return;
                    }
                }
                if (‘f‘ != whoMakeWay) {
                    if (hasNextOrExhaustRival(againstIterator, fromNext, fromIterator, fromOnlyList)) {
                        against = againstIterator.next();
                    } else {
                        return;
                    }
                }
                // 先两个都判断有下一个,然后再移动,否则先移动有下一个而另一个没有,前一个仅自己有的就丢失一项
                int cmpResult = from.compareTo(against);
                // 谁小移动谁,一样就都移动。
                if (0 == cmpResult) {
                    whoMakeWay = ‘b‘;
                    bothList.add(from);
                } else if (0 > cmpResult) {
                    // from < against: fromIterator continue until 持平0或超过1
                    whoMakeWay = ‘f‘;
                    fromOnlyList.add(from);
                } else {
                    // from > against: againstIterator continue until 持平0或超过1
                    whoMakeWay = ‘a‘;
                    againstOnlyList.add(against);
                }
            }

        }

        public static <T extends Comparable<T>> boolean hasNextOrExhaustRival(Iterator<T> hasNext, T rivalCurVal,
                Iterator<T> rival, List<T> list) {
            if (hasNext.hasNext()) {
                return true;
            }
            if (null != rivalCurVal) {
                list.add(rivalCurVal);
            }
            while (rival.hasNext()) {
                list.add(rival.next());
            }
            return false;
        }

        /**
         * 新旧数据列表两个遍历可能不只一次
         *
         * @param newList
         *          必须有序,且升序
         * @param oldList
         *          必须有序,且升序
         * @param unionList
         * @param addedList
         * @param removedList
         */
        private static <T> void innerDifference(List<T> newList, List<T> oldList, List<T> unionList, List<T> addedList,
                List<T> removedList) {
            for (Iterator<T> iterator = removedList.iterator(); iterator.hasNext();) {
                T item = iterator.next();
                if (addedList.contains(item)) {
                    unionList.add(item);
                    iterator.remove();
                    addedList.remove(item);
                }
            }
        }

        /**
         * 新旧数据列表两个遍历可能不只一次
         *
         * @param newList
         *          新数据,必须有序,且升序
         * @param oldList
         *          旧数据,必须有序,且升序
         * @return
         */
        public static <T extends Comparable<T>> Diff<T> difference(List<T> newList, List<T> oldList) {
            List<T> unionList = new ArrayList<T>();
            List<T> addedList = new ArrayList<T>(oldList);
            List<T> removedList = new ArrayList<T>(newList);
            innerDifference(newList, oldList, unionList, addedList, removedList);
            return new Diff<T>(unionList, addedList, removedList);
        }

        /**
         * 新旧数据列表两个遍历可能不只一次
         *
         * @param cursorList
         *          新数据,必须有序,且升序
         * @param baseList
         *          旧数据,必须有序,且升序
         * @param unionList
         * @param addedList
         * @param removedList
         */
        public static <T extends Comparable<T>> void difference(List<T> cursorList, List<T> baseList, List<T> unionList,
                List<T> addedList, List<T> removedList) {
            addedList.addAll(cursorList);
            removedList.addAll(baseList);
            innerDifference(cursorList, baseList, unionList, addedList, removedList);
        }

    }

    public List diff(String aFilePath, String bFilePath, String resultFilePath) throws FileNotFoundException {
        BufferedReader aReader = null, bReader = null;
        String aLine, bLine;
        String delimiter = " ";
        try {
            aReader = new BufferedReader(new FileReader(aFilePath));
            bReader = new BufferedReader(new FileReader(aFilePath));
            if (null != (aLine = aReader.readLine())) {
            }
        } catch (Exception e) {
            // TODO: handle exception
        } finally {
            closeQuietly(aReader);
            closeQuietly(bReader);
            closeQuietly(aReader);
        }
        return null;
    }

    public static <T extends Closeable> T closeQuietly(T c) {
        if (null != c) {
            try {
                c.close();
            } catch (IOException e) {
                // ALog.d("close", e.getMessage());
            }
        }
        return null;
    }
}
时间: 2025-01-07 05:04:03

统计两组数据的交集和补集(新旧数据的差异比较算法)遍历一次的相关文章

大数据的五大核心技术,给大数据同行入门研究参考的小知识

21世纪,世界已经进入数据大爆炸的时代,大数据时代已经来临.从商业公司内部的各种管理和运营数据,到个人移动终端与消费电子产品的社会化数据,再到互联网产生的海量信息数据等,每天世界上产生的信息量正在飞速增长.2009年数据信息量达到8 000亿GB,而到2011年达到1.8 ZB.图灵奖获得者Jim Gray提出的“新摩尔定律”:“每18个月全球新增信息量是计算机有史以来全部信息量的总和”,已经得到验证. 大数据的“大”不仅仅体现在数据的海量性,还在于其数据类型的复杂性.随着报表.账单.影像.办公

取两个DataTable的交集,删除重复数据

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 /// <summary>         /// 取两个DataTable的交集,删除重复数据         /// </summary>         /// <param name="sourceDataTable">源DataTable</param>         

Java中List和Map的特性对两组大批量数据进行匹配 (转)

在项目中遇到一个问题:要将通过http方式发送过来的大批量数据(这个数据保守估计每次请求在10万条左右),要和数据库中的另一批数据(数据库中的记录1万条左右)进行匹配(匹配:指两组数据中的某几个字段值相等),匹配上的数据保存在数据库中,匹配不上的直接扔掉.或者说:有一个List<String> strList,List<Person> personList,strNoList.size是1万,personList.size是10万, 然后要从personList中把person的i

js取两个数组的交集|差集|并集|补集|去重示例代码

http://www.jb51.net/article/40385.htm 代码如下: /** * each是一个集合迭代函数,它接受一个函数作为参数和一组可选的参数 * 这个迭代函数依次将集合的每一个元素和可选参数用函数进行计算,并将计算得的结果集返回 {%example <script> var a = [1,2,3,4].each(function(x){return x > 2 ? x : null}); var b = [1,2,3,4].each(function(x){re

Oracle 取两个表中数据的交集并集差异集合

Oracle 取两个表中数据的交集 关键字: Oracle 取两个表中数据的交集 INTERSECT Oracle 作为一个大型的关系数据库,日常应用中往往需要提取两个表的交集数据 例如现有如下表,要求找出工资2500(不含2500)以上并且是男性(M)的员工编号,那么就要利用这两个表的关系做一个交集了 employee CODE NAME GENDER 001 Tom M 002 Jerry M 003 Ana F salary CODE SALARY 001 2800 002 2500 00

PTA-1021—— Deepest Root(最后两组数据错误)

题目: A graph which is connected and acyclic can be considered a tree. The hight of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root. Input Specification

JS - 计算两个数组的交集、差集、并集、补集(多种实现方式)

方法一:最普遍的做法 使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本.也不用引入其他第三方库. 1,直接使用 filter.concat 来计算 var a = [1,2,3,4,5] var b = [2,4,6,8,10] //交集 var c = a.filter(function(v){ return b.indexOf(v) > -1 }) //差集 var d = a.filter(function(v){ return b.index

集合运算符之全集、交集、补集【weber出品必属精品】

集合的概念 与数学中的全集.交集.补集的概念是一样的 常用的集合运算符 集合运算符的作用:把两个查询构造为一个联合查询 1. 全集:求连个查询的全集 union all:将两个查询的所有数据全部列出,不进行排序,不去掉重复的部分 SQL> create table t1 as select * from emp where deptno in (10,20); Table created. SQL> create table t2 as select * from emp where dept

两个数组取交集的算法

在Lucene中,如果用户的查询向量Term t = {xx,xx,……},BooleanQuery为AND时,每个t---->对应得到的倒排列表,倒排列表由许多的倒排索引项构成,然后取其中重复的文档编号,然后进行排序.器核心思想类似于如下问题: 现有两个数组:int []data1 = {12,45,65,2,5} int []data2 = {12,5,-8,9},取其中的交集. 实现的方案有很多,现在采取一种时间和空间相对较好的算法:集合压缩算法,即:1.分别计算两个数组的min和max(