持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天
一、本篇笔记重点内容:
- Collection接口方法
- Iterator迭代器接口
- Collection子接口:List
- Collection子接口:Set接口
二、详细知识点介绍:
Collection接口方法
* 向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals().
//1.contains(Object obj):判断当前集合中是否包含obj
//在判断时会调用obj对象所在类的equals()。
coll.add(123);
System.out.println(coll.contains(new Person("Jerry",20)));//false -->true
@Override
public boolean equals(Object o) {
System.out.println("Person equals()....");
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);
}
//把123放入new对象所在类的equals方法形参
Iterator迭代器接口
内部方法:hasnext()和next() 调用后者前要用前者检测下一条记录是否有效,否则直接调用next()会抛出NoSuchElementException异常
- 使用Iterator遍历collection
while(iterator.hasNext()){
System.out.println(iterator.next());
}
错误方式一: nosuchelementexception空指针、间隔输出
Iterator iterator = coll.iterator();
while(iterator.next() != null){
System.out.println(iterator.next());
}
错误方式二: 死循环,每次实例化后都会生成一个指向容器顶部的iterator指针
while(coll.iterator().hasNext()){
System.out.println(coll.iterator().next());
}
Collection子接口:List
List接口的实现类常用的有:ArrayList、LinkedList和Vector
-
|----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储
-
|----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
-
|----Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储
jdk 8中ArrayLis底层 :变长数组
Object[] elementData初始化为{},第一次调用add时才创建了一个长度为10的数组。扩容方面:默认扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中
LinkedList底层:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。
vector底层:大多数操作与ArrayList相同,区别之处在于Vector是线程安全的。扩容方面:默认扩容为原来数组的两倍。
增强for循环
List接口常用方法
Collection子接口:Set接口
- |----
Set接口:存储无序的、不可重复的数据 -->“集合”
- |----
HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值 - |----
LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历。对于频繁的遍历操作,LinkedHashSet效率高于HashSet. - |----
TreeSet:可以按照添加对象的指定属性,进行排序。
向hashset中添加元素的过程
添加过程注释:
- 若此位置已有其他元素(或以链表形式存在多个),则比较元素的hash值:存在hash值不同但通过某种算法被分为同一索引位置的可能。(注:如果使用率超过0.75,底层数组会扩容为原来的二倍)。
- 如果hash值相同,需要调用元素a所在类的equals()方法: 存在由于hashcode计算方法设计出现的偶然情况(两个截然不同的实例有可能在逻辑上是相等的),如 a.name=jack (1) a.age=13(2) hashcode 1+2=3 b.name=ann(2) b.age=32(1) hashcode 2+1=3
通过equals来判断name和age是否相等 ~ 所以重写的hashCode()和equals()需要尽可能保持一致性: 相等的对象必须具有相等的散列码。
HashSet 集合判断两个元素相等的标准: 两个对象通过hashCode() 方法比较相等,并且两个对象的equals()方法返回值也相等。