In the project, we often use two sets of data comparison, find the different data, basically in the Android data volume is not too big, everyone is often use nested for loop directly fix, has it ever occurred to you When the data volume is very big, the use of nested for loop to identify different objects, how long it takes. This article will introduce you to efficient data comparison, and some special scenarios, bookmarking, you can use.

instructions

The test time varies with device performance. The following table describes the hardware of the test device

Preparation stage

Create an object model. The more complex the object model, the slower it is

    public static class User{
        private int id;
        private String name;

        public User(int id, String name) {
            this.id = id;
            this.name = name;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) { this.name = name; }}Copy the code

A lot of fake data is inserted through a loop

    List<User> list1 = new ArrayList<User>();
    List<User> list2 = new ArrayList<User>();
    for (int i = 0; i < 100000; i++) {
        list1.add(new User(i,"test"+i));
    }
    for (int i = 0; i < 500000; i++) {
        list2.add(new User(i,"test"+i));
    }

Copy the code

Methods a

List1.size ()*list2.size(

private static List<User> getDiffrent1(List<User> list1, List<User> diff = new ArrayList<User>(); Long start = system.currentTimemillis ();for (User user : list1) {
            if(! list2.contains(user)) { diff.add(user); }} system.out.println ();"Method 1 Time-consuming:" + (System.currentTimeMillis() - start) + "Ms");
        return diff;
    }

Copy the code

Method 2

The principle and method are the same, but the writing method is relatively simple or very time-consuming

private static List<User> getDiffrent2(List<User> list1, List<User> list2) { long start = System.currentTimeMillis(); list1.retainAll(list2); // The return value is Boolean system.out.println ("Method 2 Time-consuming:" + (System.currentTimeMillis() - start) + "Ms");
        return list1;
    }

Copy the code

Methods three

Use Map to store the List1 and List2 elements as keys, and value is the number of times they appear in List1 and List2

List1.size () + list2.size(), which is greatly simplified compared with methods 1 and 2

private static List<User> getDiffrent3(List<User> list1, List<User> list2) { List<User> diff = new ArrayList<User>(); long start = System.currentTimeMillis(); Map<User, Integer> map = new HashMap<User, Integer>(list1.size() + list2.size()); // Put the List1 element into the Map and count 1for(User user : list1) { map.put(user, 1); } // select * from List2; // select * from List2; If not found, put into map and count 1for (User user : list2) {
            Integer count = map.get(user);
            if(count ! = null) { map.put(user, ++count); // This can be optimized to reduce the number of put,continue;
            }
            map.put(user, 1);
        }
        for (Map.Entry<User, Integer> entry : map.entrySet()) {
            if (entry.getValue() == 1) {
                diff.add(entry.getKey());
            }
        }
        System.out.println("Method 3 Time-consuming:" + (System.currentTimeMillis() - start) + "Ms");
        return diff;
    }

Copy the code

Time consuming of each method

The phone would be ANR if it wasn’t asynchronous to process this kind of data on the phone, and of course it’s rare to actually have this much data on the phone, but when the data is in the thousands and the data model is complex, the for loop nesting is slower than you might think

Special demand

List1 does not exist, list2 does not exist, List1 does not exist, id is consistent with other attributes different!

Perhaps very strange, feeling never met such a demand, collection, maybe one day you will meet

Example: Compare two databases to find values that need to be inserted, updated, or deleted

Create a comparison model

    public class ComparisonModel {
    private ContentValues values;
    //type1 Same 2 Update 3 Insert 4 Delete private inttype;

    public ComparisonModel(ContentValues values, int type) {
        this.values = values;
        this.type = type;
    }

    public ContentValues getValues() {
        return values;
    }

    public void setValues(ContentValues values) {
        this.values = values;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type; }}Copy the code

The comparison code

Map<String, MapModel> map = new HashMap<String, MapModel>(wechatList.size() + list.size());

        for (ContentValues value : list) {
            map.put(value.get(key).toString(), new MapModel(value, 4));
        }
        for (ContentValues value : wechatList) {
            MapModel model = map.get(value.get(key).toString());
            if (model == null) {
                map.put(value.get(key).toString(), new MapModel(value, 3));
            } else {
                if (model.getValues().equals(value)) {
                    map.put(value.get(key).toString(), new MapModel(value, 1));
                } else{ map.put(value.get(key).toString(), new MapModel(value, 2)); }}}for (Map.Entry<String, MapModel> entry : map.entrySet()) {

            switch (entry.getValue().getType()) {
                case1: / / the samebreak;
                caseUpdate 2: / /break;
                case3: / / insertbreak;
                case4: / / deletedbreak;
                default:
            }
        }

Copy the code