之前遇到如何能高效的比较两个List的增量的问题,由于时间紧迫最起初的方式也是最原始的,就是使用各循环对比两个List两次并设置标示符的方式来进行比较。在两个List的数据量较小的时候,这种方式对效率的影响不会很明显,但当数量级达到一定程度的时候,效率问题就会浮出水面。想到Map集合Key值的唯一性,是否可以使用重写某个对象的equals()方法的方式来比较两个对象的一致性,再将对象放入Map中,相同的对象就修改该Key的Value,不同的以新的Key和Value插入Map,再通过Map的相关方法,就可以拿到两个List的增量。
首先,先建立一个UserInfo的对象,并重写他的equals()方法,这里,我只是通过UserInfo的name属性来比较两个UserInfo是否相同。UserInfo的代码如下:
/**
* Copyright (C) 2012 http://blog.csdn.net/Just_szl
*
* 修订历史记录:
*
* Revision 1.0 2013-6-19 Geray 创建。
*
*/
package com.geray.CompareDifferenceBetweenTowCollections;
/**
*
* @author <a href="mailto:just_szl@hotmail.com"> Geray</a>
* @version 1.0,2013-6-19
*/
public class UserInfo {
private String name;
private int age;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UserInfo other = (UserInfo) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
然后建立比较的方法,先建立一个原始的比较方法compareDifferenceBetweenTwoArray(),也就是利用循环的方式比较两个List的增量。再使用Map的方式比较两个List的增量。ComDifClass代码如下:
/**
* Copyright (C) 2012 http://blog.csdn.net/Just_szl
*
* 修订历史记录:
*
* Revision 1.0 2013-6-19 Geray 创建。
*
*/
package com.geray.CompareDifferenceBetweenTowCollections;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author <a href="mailto:just_szl@hotmail.com"> Geray</a>
* @version 1.0,2013-6-19
*/
public class ComDifClass {
/**
* 最初的方式比较两个List的增量
* @param list1 原有的List
* @param list2 将要比较的List
*/
public static void compareDifferenceBetweenTwoArray(List<UserInfo> list1, List<UserInfo> list2){
long currTime = System.currentTimeMillis();
List<UserInfo> removeList = new ArrayList<UserInfo>();
List<UserInfo> addList = new ArrayList<UserInfo>();
loop1:for(int i = 0; i < list1.size() ; i++){
boolean isExisted = false;
UserInfo u1 = list1.get(i);
for(int j = 0 ; j < list2.size() ; j++){
UserInfo u2 = list2.get(j);
if(u1.equals(u2)){
isExisted = true;
continue loop1;
}
}
if(!isExisted){
removeList.add(u1);
}
}
for(int i = 0; i < list2.size() ; i++){
boolean isExisted = false;
UserInfo u1 = list2.get(i);
loop2:for(int j = 0 ; j < list1.size() ; j++){
UserInfo u2 = list1.get(j);
if(u1.equals(u2)){
isExisted = true;
continue loop2;
}
}
if(!isExisted){
addList.add(u1);
}
}
long endTime = System.currentTimeMillis();
System.out.println("删除数据大小:"+ removeList.size());
System.out.println("新增数据大小: " + addList.size());
System.out.println("方法所用时间:"+(endTime-currTime)+"毫秒");
}
/**
* 修改后比较两个List的异同
* @param list1 原有的List
* @param list2 将要比较的List
*/
public static void compareDifferenceBetweenTwoArray2(List<UserInfo> list1, List<UserInfo> list2){
long currTime = System.currentTimeMillis();
//此处是对效率的进一步优化,将Size较大的List先放入Map中,
boolean listIsChanged = false;
List<UserInfo> maxList = list1;
List<UserInfo> minList = list2;
if(list1.size()<list2.size()){
listIsChanged = true;
maxList = list2;
minList = list1;
}
Map<UserInfo,Integer> targetMap = new HashMap<UserInfo,Integer>();
//将较大的List放入Map中,并将其value设为1
for(UserInfo u : maxList){
targetMap.put(u, 1);
}
//将较小的List放入Map中,如果存在则将其value设置为2,如果不存在则将其value设为-1
for(UserInfo u : minList){
boolean isExisted = targetMap.containsKey(u);
if(isExisted){
targetMap.put(u, 2);
}else{
targetMap.put(u, -1);
}
}
long middleTime = System.currentTimeMillis();
List<UserInfo> removeList = new ArrayList<UserInfo>();
List<UserInfo> addList = new ArrayList<UserInfo>();
if(listIsChanged){
for(Map.Entry<UserInfo, Integer> entry : targetMap.entrySet()){
if(entry.getValue() == 1){
addList.add(entry.getKey());
}else if(entry.getValue() == -1){
removeList.add(entry.getKey());
}
}
}else{
for(Map.Entry<UserInfo, Integer> entry : targetMap.entrySet()){
if(entry.getValue() == 1){
removeList.add(entry.getKey());
}else if(entry.getValue() == -1){
addList.add(entry.getKey());
}
}
}
System.out.println("当前Map大小:"+targetMap.size());
System.out.println("删除数据大小:"+ removeList.size());
System.out.println("新增数据大小: " + addList.size());
long endTime = System.currentTimeMillis();
System.out.println("抽取前所用时间:"+(middleTime-currTime)+"毫秒");
System.out.println("方法所用时间:"+(endTime-currTime)+"毫秒");
}
/**
* @param args
*/
public static void main(String[] args) {
List<UserInfo> list1 = new ArrayList<UserInfo>();
List<UserInfo> list2 = new ArrayList<UserInfo>();
for(int i = 0 ; i <10000 ; i++){
UserInfo u1 = new UserInfo();
u1.setName("S"+i);
UserInfo u2 = new UserInfo();
u2.setName("S"+i*2);
list1.add(u1);
list2.add(u2);
}
ComDifClass.compareDifferenceBetweenTwoArray(list1, list2);
System.out.println("--------------华丽的分割线---------------");
ComDifClass.compareDifferenceBetweenTwoArray2(list1, list2);
}
}
下面看一下两种方式对效率的提升。