以ArrayList为例,分析它的创建过程,分析JVM怎么分配它的内存,从而分析Arraylist里面的数组对象判断是否相等的原理。
分析ArrayList创建过程(代码在后面)
- 创建ArrayList对象,对象名称为userList,因为ArrayLIst类是泛型类,传入的对象参数为User。
- 查看ArrayList代码可知,里面有一个空的静态数组对象 实例变量。
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access
- 当执行List userList = new ArrayList<>(); 方法时,userList作为对象的引用变量存储在虚拟机栈 中,在堆中建立一个空的数组。
- User user1 = new User(“cjm”, “1”),userList.add(user1);执行代码,首先创建user1对象,对象的实例数据的内存堆中,user1作为实例引用存储在虚拟机栈中,而userList.add(user1),执行的操作是,user1作为虚拟机栈地址存储在数组的静态内存空间中 ,有连续的内存和下标。这个时候数组的长度为10。user1存储的位置为第一个。
- 同理再一次添加一个对象。userList.add(new User(“qj”,”2”)); 保存对象的引用地址在数组的第二个位置。
- .新建第二个userList1对象。注意,其中user1对象是同一个对象。但是在userList和userList1中,user1存储在数组中的地址是不一样的。
- . 现在在执行removeAll方法,分析源码知,在Arraylist中判断数组存储的对象是否相等,使用的是equal。举例user1,比较就是创建user1这个对象时,存储在内存堆的数据。所以user1是相等的。
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
结论:
在执行ArrayList的removeAll方法,判断它的成员变量是否相等,判断的是成员变量对象在内存堆中的值是否相等。
ArrayList中静态数组存储的都是实例变量对象的引用地址。
示例代码
public class User {
private String name;
private String orgId;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getOrgId() {
return orgId;
}
public void setOrgId(String orgId) {
this.orgId = orgId;
}
public User(String name, String orgId) {
this.name = name;
this.orgId = orgId;
}
}
public class CollectionTest {
public static void main(String[] args) {
List<User> userList = new ArrayList<>();
userList.add(new User("qj","2"));
User user1 = new User("cjm", "1");
userList.add(user1);
userList.add(new User("zlz","3"));
List<User> userList1 = new ArrayList<>();
userList1.add(new User("zzq","4"));
userList1.add(user1);
boolean a = userList.removeAll(userList1);
System.out.println(a);
print(userList);
}
private static void print(List<User> userList){
for (User user : userList){
System.out.println(user.getName());
}
}
}