如何将PriorityQueue、TransformingComparator 作为入口点和跳板去利用
首先看一下作为跳板的 TransformingComparator 类是怎么调用到利用链的
public int compare(final I obj1, final I obj2) {
final O value1 = this.transformer.transform(obj1);
final O value2 = this.transformer.transform(obj2);
return this.decorated.compare(value1, value2);
}
在 TransformingComparator#compare 方法中,调用到了transform 方法去修饰 obj1、obj2 的值。就是这个方法调用到了利用链
接着在看一下 PriorityQueue 类是怎么作为入口点去利用的
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in size, and any hidden stuff
s.defaultReadObject();
// Read in (and discard) array length
s.readInt();
queue = new Object[size];
// Read in all elements.
for (int i = 0; i < size; i++)
queue[i] = s.readObject();
// Elements are guaranteed to be in "proper order", but the
// spec has never explained what that might be.
heapify();
}
在PriorityQueue#readObject 方法中,将反序列化的数据存放在queue 字段中,之后调用 heapify 方法来对数据进行调整,形成二叉堆
在对数据进行调整的时候会对数据进行比较,将较小的数排列在前面。而在对数据进行比较的时候就会调用到compare 方法,从而让PriorityQueue 类和TransformingComparator产生联系。看一下这个操作是怎么在代码中实现的
private void heapify() {
for (int i = (size >>> 1) - 1; i >= 0; i--)
siftDown(i, (E) queue[i]);
}
在 heapify 方法中,采用将数向后移动的方式来对数据进行调整。
private void siftDown(int k, E x) {
if (comparator != null)
siftDownUsingComparator(k, x);
else
siftDownComparable(k, x);
}
在后移之前会判断,判断是否有比较器 (compar),如果有的话则调用if 中的方法,否则调用 else 中的方法。这里直接看i分钟的方法,因为只有当有比较器的时候才会调用比较器中的方法来比较两个数
private void siftDownUsingComparator(int k, E x) {
int half = size >>> 1;
while (k < half) {
int child