目录
1. 集合中重写equals()方法
- 集合只能存储引用数据类型,基本数据类型是自动装箱成包装类,包装类重写了equals方法,所以也是比较的值
- 向Collection接口的实现类的对象中添加数据obj时,即向list中添加对象时,要求 对象所在类要重写equals
Person.class
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
测试
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add(new String("Tom"));
System.out.println("String相等的判断 :" + coll.contains(new String("Tom"))); // true
coll.add(12);
System.out.println("基本数据类型的比较 : " + coll.contains(12)); // true
coll.add(new Person("Jerry", 22));
System.out.println("对象的比较 : "+ coll.contains(new Person("Jerry", 22))); // true , 如果没有重写Person中的equals方法,得到的就是false
}
2. ArrayList源码分析
jdk1.7和jdk1.8略有不同
jdk 1.7
- 底层创建了长度是10的Object[]数组 elementData
java.util.ArrayList;
包
2. 扩容,并复制原有数组元素到新的数组中。
list.add(),如果此次的添加导致底层elementData数组容量不够,则扩容。默认情况下,扩容为原来的1.5倍。
jdk 1.8
4. 底层 Object[] elementData初始化为{},并没有创建长度为10的数组
list.add(123)//第一次调用add时,底层才创建了长度10的数组,并将123添加到elementData[0]中
jdk7中的ArrayList的对象的创建类似于单例的饿汉式,而jdk8中的ArrayList的对象的创建类似于单例的懒汉式,延迟了数组的创建,节省内存
结论,建议开发中使用带参的构造器,ArrayList list = new ArrayList(int capacity),减少扩容操作,降低损耗。
3. LinkedList源码分析
内部声明了Node类型的first和last属性,默认值为null,LinkedList的底层结构是双向链表。
Node定义为
向链表中添加一个元素,相当于在链表尾部加上一个Node结点
4. Vector源码分析
jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组。扩容方面,默认扩容为原来的数组的2倍。
5. ArrayList、LinkedList、Vector三者的异同
相同点:
- 三个类都是实现了List接口
- 存储数据的特点相同:存储有序的,可重复的数据
不同点:
- ArrayList:作为List接口的主要实现类,线程不安全的,效率高。底层使用Object[] elementData存储
- LinkedList:作为频繁的插入,删除操作,使用此类效率比ArrayList高,底层使用双向链表
数组的添加删除操作,需要移动所需添加元素后的所有的数据。链表的添加删除,只需要改变指针指向。如果不指定位置,直接在list最后添加元素,使用ArrayList效率更高。这种情况下,不需要移动数组元素,减少操作指针的效率损失。 - Vector:作为List接口的古老实现类,线程安全,效率高。底层使用Object[] elementData存储