在工作了许久之后,也认识了很多对象属性拷贝工具,诸如标题所示的那些工具,于是就想看看哪个工具在对象拷贝方面性能更高,于是乎就有了这篇博文,希望对小伙伴们有点帮助。
由于是测试性能,代码写的比较露骨简单且基本相同,在每个工具类正式测试前,都做了代码预热,为了就是让结果尽量准确,各个工具的测试代码将贴在文末,下面直接附上测试结果。
类 | 方法 | 归属 | 单次耗时[ms] | 100万次耗时[ms] | 平均耗时[ms] |
---|---|---|---|---|---|
BeanUtils | copyProperties | Apache | 0.310196 | 30253.140057 | 0.030253 |
DozerBeanMapper | map | Dozer | 0.598338 | 19158.842820 | 0.019158 |
PropertyUtils | copyProperties | Apache | 0.164118 | 16714.877932 | 0.016714 |
BeanUtils | copyProperties | Spring | 0.072082 | 2155.744378 | 0.002155 |
BeanCopier | copy | Cglib | 0.005071 | 58.415201 | 0.000058 |
预热100次后结果排行
单次耗时:BeanCopier < BeanUtils(Spring) < PropertyUtils < BeanUtils(Apache) < DozerBeanMapper
100万次耗时:BeanCopier < BeanUtils(Spring) < PropertyUtils < DozerBeanMapper < BeanUtils(Apache)
平均耗时:BeanCopier < BeanUtils(Spring) < PropertyUtils < DozerBeanMapper < BeanUtils(Apache)
预热1000次后的结果:
类 | 方法 | 归属 | 单次耗时[ms] | 100万次耗时[ms] | 平均耗时[ms] |
---|---|---|---|---|---|
BeanUtils | copyProperties | Apache | 0.088523 | 32556.660915 | 0.032556 |
DozerBeanMapper | map | Dozer | 0.112480 | 17818.511072 | 0.017818 |
PropertyUtils | copyProperties | Apache | 0.055119 | 18046.194031 | 0.018046 |
BeanUtils | copyProperties | Spring | 0.025337 | 1969.376513 | 0.001969 |
BeanCopier | copy | Cglib | 0.001124 | 69.608191 | 0.000069 |
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
import java.math.BigInteger;
@Getter
@Setter
public class OriginBean {
private int intProperty;
private boolean booleanProperty;
private float floatProperty;
private double doubleProperty;
private long longProperty;
private char charProperty;
private byte byteProperty;
private short shortProperty;
private Integer integerProperty;
private Boolean booleanObjProperty;
private Float floatObjProperty;
private Double doubleObjProperty;
private Long longObjProperty;
private Short shortObjProperty;
private Byte byteObjProperty;
private BigInteger bigIntegerProperty;
private BigDecimal bigDecimalProperty;
private String stringProperty;
public OriginBean() {
this.intProperty = 10000;
this.booleanProperty = true;
this.floatProperty = 0.556F;
this.doubleProperty = 10000.221D;
this.longProperty = 99999999999L;
this.charProperty = 'a';
this.byteProperty = 123;
this.shortProperty = 12222;
this.integerProperty = 11111111;
this.booleanObjProperty = Boolean.TRUE;
this.floatObjProperty = 99.32322F;
this.doubleObjProperty = 222121.3232D;
this.longObjProperty = 333333L;
this.shortObjProperty = 12121;
this.byteObjProperty = 121;
this.bigIntegerProperty = new BigInteger("12121212121");
this.bigDecimalProperty = new BigDecimal(212123323323232L);
this.stringProperty = "功盖三分国,名成八阵图。江流石不转,遗恨失吞吴。";
}
}
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
import java.math.BigInteger;
@Getter
@Setter
public class TargetBean {
private int intProperty;
private boolean booleanProperty;
private float floatProperty;
private double doubleProperty;
private long longProperty;
private char charProperty;
private byte byteProperty;
private short shortProperty;
private Integer integerProperty;
private Boolean booleanObjProperty;
private Float floatObjProperty;
private Double doubleObjProperty;
private Long longObjProperty;
private Short shortObjProperty;
private Byte byteObjProperty;
private BigInteger bigIntegerProperty;
private BigDecimal bigDecimalProperty;
private String stringProperty;
}
import org.apache.commons.beanutils.BeanUtils;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
public class ApacheBeanUtil {
/**
* 预热
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public static void preheat() throws InvocationTargetException, IllegalAccessException {
List<OriginBean> originBeans = new ArrayList<>();
List<TargetBean> targetBeans = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
originBeans.add(new OriginBean());
targetBeans.add(new TargetBean());
}
for (int i = 0; i < 1000; i++) {
OriginBean originBean = originBeans.get(i);
TargetBean targetBean = targetBeans.get(i);
BeanUtils.copyProperties(targetBean, originBean);
}
}
/**
* 测试单个对象属性拷贝
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public static void copySingle() throws InvocationTargetException, IllegalAccessException {
OriginBean originBean = new OriginBean();
TargetBean targetBean = new TargetBean();
long start = System.nanoTime();
BeanUtils.copyProperties(targetBean, originBean);
long end = System.nanoTime() - start;
System.out.println(new BigDecimal(end).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
}
/**
* 测试列表对象属性拷贝
* @param times
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public static void copyList(int times) throws InvocationTargetException, IllegalAccessException {
List<OriginBean> originBeans = new ArrayList<>();
List<TargetBean> targetBeans = new ArrayList<>();
for (int i = 0; i < times; i++) {
originBeans.add(new OriginBean());
targetBeans.add(new TargetBean());
}
long start = System.nanoTime();
for (int i = 0; i < times; i++) {
OriginBean originBean = originBeans.get(i);
TargetBean targetBean = targetBeans.get(i);
BeanUtils.copyProperties(targetBean, originBean);
}
long end = System.nanoTime() - start;
System.out.println(new BigDecimal(end).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
System.out.println(new BigDecimal(end/times).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
}
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
preheat();
copySingle();
copyList(1000 * 1000);
}
}
import org.dozer.DozerBeanMapper;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
public class DozerBeanMapperUtil {
private static final DozerBeanMapper mapper = new DozerBeanMapper();
/**
* 预热
*/
public static void preheat() {
List<OriginBean> originBeans = new ArrayList<>();
List<TargetBean> targetBeans = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
originBeans.add(new OriginBean());
targetBeans.add(new TargetBean());
}
for (int i = 0; i < 1000; i++) {
OriginBean originBean = originBeans.get(i);
TargetBean targetBean = targetBeans.get(i);
mapper.map(originBean, targetBean);
}
}
/**
* 测试单个对象属性拷贝
*/
public static void copySingle(){
OriginBean originBean = new OriginBean();
TargetBean targetBean = new TargetBean();
long start = System.nanoTime();
mapper.map(originBean, targetBean);
long end = System.nanoTime() - start;
System.out.println(new BigDecimal(end).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
}
/**
* 测试列表对象属性拷贝
* @param times
*/
public static void copyList(int times) {
List<OriginBean> originBeans = new ArrayList<>();
List<TargetBean> targetBeans = new ArrayList<>();
for (int i = 0; i < times; i++) {
originBeans.add(new OriginBean());
targetBeans.add(new TargetBean());
}
long start = System.nanoTime();
for (int i = 0; i < times; i++) {
OriginBean originBean = originBeans.get(i);
TargetBean targetBean = targetBeans.get(i);
mapper.map(originBean, targetBean);
}
long end = System.nanoTime() - start;
System.out.println(new BigDecimal(end).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
System.out.println(new BigDecimal(end/times).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
}
public static void main(String[] args) {
preheat();
copySingle();
copyList(1000 * 1000);
}
}
import org.apache.commons.beanutils.PropertyUtils;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
public class PropertiesUtil {
/**
* 预热
*/
public static void preheat() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
List<OriginBean> originBeans = new ArrayList<>();
List<TargetBean> targetBeans = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
originBeans.add(new OriginBean());
targetBeans.add(new TargetBean());
}
for (int i = 0; i < 1000; i++) {
OriginBean originBean = originBeans.get(i);
TargetBean targetBean = targetBeans.get(i);
PropertyUtils.copyProperties(targetBean, originBean);
}
}
/**
* 测试单个对象属性拷贝
* @throws IllegalAccessException
* @throws NoSuchMethodException
* @throws InvocationTargetException
*/
public static void copySingle() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
OriginBean originBean = new OriginBean();
TargetBean targetBean = new TargetBean();
long start = System.nanoTime();
PropertyUtils.copyProperties(targetBean, originBean);
long end = System.nanoTime() - start;
System.out.println(new BigDecimal(end).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
}
/**
* 测试列表对象属性拷贝
* @param times
* @throws IllegalAccessException
* @throws NoSuchMethodException
* @throws InvocationTargetException
*/
public static void copyList(int times) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
List<OriginBean> originBeans = new ArrayList<>();
List<TargetBean> targetBeans = new ArrayList<>();
for (int i = 0; i < times; i++) {
originBeans.add(new OriginBean());
targetBeans.add(new TargetBean());
}
long start = System.nanoTime();
for (int i = 0; i < times; i++) {
OriginBean originBean = originBeans.get(i);
TargetBean targetBean = targetBeans.get(i);
PropertyUtils.copyProperties(targetBean, originBean);
}
long end = System.nanoTime() - start;
System.out.println(new BigDecimal(end).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
System.out.println(new BigDecimal(end/times).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
}
public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
preheat();
copySingle();
copyList(1000 * 1000);
}
}
import org.springframework.beans.BeanUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
public class SpringBeanUtil {
/**
* 预热
*/
public static void preheat() {
List<OriginBean> originBeans = new ArrayList<>();
List<TargetBean> targetBeans = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
originBeans.add(new OriginBean());
targetBeans.add(new TargetBean());
}
for (int i = 0; i < 1000; i++) {
OriginBean originBean = originBeans.get(i);
TargetBean targetBean = targetBeans.get(i);
BeanUtils.copyProperties(originBean, targetBean);
}
}
/**
* 测试单个对象属性拷贝
*/
public static void copySingle(){
OriginBean originBean = new OriginBean();
TargetBean targetBean = new TargetBean();
long start = System.nanoTime();
BeanUtils.copyProperties(originBean, targetBean);
long end = System.nanoTime() - start;
System.out.println(new BigDecimal(end).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
}
/**
* 测试列表对象属性拷贝
* @param times
*/
public static void copyList(int times) {
List<OriginBean> originBeans = new ArrayList<>();
List<TargetBean> targetBeans = new ArrayList<>();
for (int i = 0; i < times; i++) {
originBeans.add(new OriginBean());
targetBeans.add(new TargetBean());
}
long start = System.nanoTime();
for (int i = 0; i < times; i++) {
OriginBean originBean = originBeans.get(i);
TargetBean targetBean = targetBeans.get(i);
BeanUtils.copyProperties(originBean, targetBean);
}
long end = System.nanoTime() - start;
System.out.println(new BigDecimal(end).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
System.out.println(new BigDecimal(end/times).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
}
public static void main(String[] args) {
preheat();
copySingle();
copyList(1000 * 1000);
}
}
import org.springframework.cglib.beans.BeanCopier;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
public class BeanCopierUtil {
private static final BeanCopier copier = BeanCopier.create(OriginBean.class, TargetBean.class, false);
/**
* 预热
*/
public static void preheat() {
List<OriginBean> originBeans = new ArrayList<>();
List<TargetBean> targetBeans = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
originBeans.add(new OriginBean());
targetBeans.add(new TargetBean());
}
for (int i = 0; i < 1000; i++) {
OriginBean originBean = originBeans.get(i);
TargetBean targetBean = targetBeans.get(i);
copier.copy(originBean, targetBean, null);
}
}
/**
* 测试单个对象属性拷贝
*/
public static void copySingle(){
OriginBean originBean = new OriginBean();
TargetBean targetBean = new TargetBean();
long start = System.nanoTime();
copier.copy(originBean, targetBean, null);
long end = System.nanoTime() - start;
System.out.println(new BigDecimal(end).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
}
/**
* 测试列表对象属性拷贝
* @param times
*/
public static void copyList(int times) {
List<OriginBean> originBeans = new ArrayList<>();
List<TargetBean> targetBeans = new ArrayList<>();
for (int i = 0; i < times; i++) {
originBeans.add(new OriginBean());
targetBeans.add(new TargetBean());
}
long start = System.nanoTime();
for (int i = 0; i < times; i++) {
OriginBean originBean = originBeans.get(i);
TargetBean targetBean = targetBeans.get(i);
copier.copy(originBean, targetBean, null);
}
long end = System.nanoTime() - start;
System.out.println(new BigDecimal(end).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
System.out.println(new BigDecimal(end/times).divide(new BigDecimal(1000000), 6, RoundingMode.HALF_UP) + "[ms]");
}
public static void main(String[] args) {
preheat();
copySingle();
copyList(1000 * 1000);
}
}