学习笔记
Collection
LinkedList
底层通过双向链表实现
LinkedList通过first
和last
引用分别指向链表的第一个和最后一个元素。注意这里没有所谓的哑元,当链表为空的时候first
和last
都指向null
。
-
getFirst()
获取第一个元素getLast()
获取最后一个元素 -
removeFirst()
removeLast()
remove(Object)
remove(index)
删除第一次出现的这个元素, 如果没有这个元素,则返回false;判断的依据是equals方法, 如果equals,则直接unlink这个node;由于LinkedList可存放null元素,故也可以删除第一次出现null的元素。
-
add()
该方法在LinkedList的末尾插入元素add(int index, E element)
,该方法是在指定下表处插入元素,需要先通过线性查找找到具体位置,然后修改相关引用完成插入操作 -
get(index)
set(index,e)
add(index,e)
remove(index)
-
indexOf(Object)
lastIndexOf(Object)
-
Queue方法:
peek()
poll()
remove()
offer(e)
-
Deque是"double ended queue"表示双向的队列,方法:
offerFirst(e)
offerLast(e)
peekFirst()
peekLast()
pollFirst()
pollLast()
栈的相关操作push(e)
pop()
removeFirstOccurrence(o)
removeLastOccurrence(Object o)
ArrayDeque
循环数组实现,非线程安全
head
指向首端第一个有效元素,tail
指向尾端第一个可以插入元素的空位
空间问题是在插入之后解决的,因为tail
总是指向下一个可插入的空位,也就意味着elements
数组至少有一个空位,所以插入元素的时候不用考虑空间问题。
方法:addFirst()
addLast()
pollFirst()
pollLast()
peekFirst()
peekLast()
PriorityQueue
优先队列的作用是能保证每次取出的元素都是队列中权值最小
元素大小的评判可以通过元素本身的自然顺序,也可以通过构造时传入的比较器,通过完全二叉树实现的小顶堆来实现,可以用数组存储堆
add()
offer()
向优先队列中插入元素,前者失败抛出异常 后者失败返回falsepeek()
element()
获取但不删除队首元素remove()
poll()
获取并删除队首元素
HashMap
允许放入key
为null
的元素,也允许插入value
为null
的元素
不保证元素顺序,根据需要该容器可能会对元素重新哈希,元素的顺序也会被重新打散,因此不同时间迭代同一个HashMap
的顺序可能会不同。
HashMap
采用的是冲突链表方式
对HashMap
进行迭代时,需要遍历整个table以及后面跟的冲突链表。因此对于迭代比较频繁的场景,不宜将HashMap
的初始大小设的过大。
有两个参数可以影响HashMap
的性能: 初始容量(inital capacity
)和负载系数(load factor
)。初始容量指定了初始table
的大小,负载系数用来指定自动扩容的临界值。当entry
的数量超过capacity*load_factor
时,容器将自动扩容并重新哈希。对于插入元素较多的场景,将初始容量设大可以减少重新哈希的次数。
将对象放入到HashMap
或HashSet
中时,有两个方法需要特别关心: hashCode()
和equals()
。hashCode()
方法决定了对象会被放到哪个bucket
里,当多个对象的哈希值冲突时,equals()
方法决定了这些对象是否是“同一个对象”。如果是同一个对象则不会插入。所以,如果要将自定义的对象放入到HashMap
或HashSet
中,需要**@Override** hashCode()
和equals()
方法。
get()
:get(Object key)
方法根据指定的key
值返回对应的value
,该方法调用了getEntry(Object key)
得到相应的entry
,然后返回entry.getValue()
。因此getEntry()
是算法的核心。 算法思想是首先通过hash()
函数得到对应bucket
的下标,然后依次遍历冲突链表,通过key.equals(k)
方法来判断是否是要找的那个entry
。put()
:该方法首先会对map
做一次查找,看是否包含该元组,如果已经包含则直接返回,查找过程类似于getEntry()
方法;如果没有找到,则会通过addEntry(int hash, K key, V value, int bucketIndex)
方法插入新的entry
,插入方式为头插法(Java 8 为尾插法)。remove()
:remove(Object key)
的作用是删除key
值对应的entry
,该方法的具体逻辑是在removeEntryForKey(Object key)
里实现的。removeEntryForKey()
方法会首先找到key
值对应的entry
,然后删除该entry
(修改链表的相应引用)。查找过程跟getEntry()
过程类似。
Java 8 对 HashMap
进行了一些修改,最大的不同就是利用了红黑树,所以其由 数组+链表+红黑树 组成。
根据 Java 7 HashMap
的介绍,我们知道,查找的时候,根据 hash 值我们能够快速定位到数组的具体下标,但是之后的话,需要顺着链表一个个比较下去才能找到我们需要的,时间复杂度取决于链表的长度,为 O(n)
。
为了降低这部分的开销,在 Java 8 中,当链表中的元素达到了 8 个时,会将链表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为 O(logN)
。
@SuppressWarnings
告诉编译器忽略指定的警告,不用在编译完成后出现警告信息。
· @SuppressWarnings(“unchecked”)
告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。
· @SuppressWarnings(“serial”)
如果编译器出现这样的警告信息:The serializable class WmailCalendar does not declare a static final serialVersionUID field of type long,使用这个注释将警告信息去掉。
· @SuppressWarnings(“deprecation”)
如果使用了使用@Deprecated注释的方法,编译器将出现警告信息。使用这个注释将警告信息去掉。
· @SuppressWarnings(“unchecked”, “deprecation”)
告诉编译器同时忽略unchecked和deprecation的警告信息。
· @SuppressWarnings(value={“unchecked”, “deprecation”})
等同于@SuppressWarnings(“unchecked”, “deprecation”)
参考链接:https://pdai.tech/md/java/collection/java-map-HashMap&HashSet.html