代码示例
摘取自:
http://java-er.com/blog/java-priority-queue/
package com.javaer.examples.datastruct;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import org.apache.poi.ss.formula.functions.Count;
public class PriorityQueueExample {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Queue qi = new PriorityQueue();
qi.add(5);
qi.add(2);
qi.add(1);
qi.add(10);
qi.add(3);
while (!qi.isEmpty()){
System.out.print(qi.poll() + ",");
}
System.out.println();
System.out.println("-----------------------------");
Comparator cmp;
cmp = new Comparator() {
public int compare(Integer e1, Integer e2) {
return e2 - e1;
}
};
Queue q2 = new PriorityQueue(5,cmp);
q2.add(2);
q2.add(8);
q2.add(9);
q2.add(1);
while (!q2.isEmpty()){
System.out.print(q2.poll() + ",");
}
}
}
output:
1,2,3,5,10,
-----------------------------
9,8,2,1,
优先级队列的特点
对它里面的元素,按照设定的规则进行排序. 从队列取数据的时候, 按照排序后的顺序取里面的元素.
PriorityQueue implement Queue
普通队列的特点是, 对取元素的操作进行了限制, 只能从队列头取元素, 不能从任意位置取元素.
而优先级队列对它里面的元素进行了排序, 默认使用元素的自然排序, 当然也可以构造PriorityQueue的时候, 指定一个比较器, 按照比较器的规则对元素进行排序.
这就要求插入到优先级队列中的元素, 都必须是实现了Comparable接口的对象.
PriorityQueue不是线程安全的, 如果有多个线程对同一个优先级队列进行操作, 需要使用PriorityBlockingQueue这个类.
Queue
BlockingQueue
PriorityBlockingQueue
PriorityBlockingQueue的应用场景.
Volley中使用PriorityBlockingQueue存储外界对volley的网络请求.
public class RequestQueue {
/** The cache triage queue. */
private final PriorityBlockingQueue> mCacheQueue =
new PriorityBlockingQueue>();
/** The queue of requests that are actually going out to the network. */
private final PriorityBlockingQueue> mNetworkQueue =
new PriorityBlockingQueue>();
}
在构造的时候, 并没有指定一个比较器, 实际上对元素进行排序时, 实际上是调用每个元素的getPriority()方法, 当priority一致的情况下, 比较的是request的mSequence值.
public abstract class Request implements Comparable> {
/**
* Sequence number of this request, used to enforce FIFO ordering.
*/
private Integer mSequence;
@Override
public int compareTo(Request other) {
Priority left = this.getPriority();
Priority right = other.getPriority();
// High-priority requests are "lesser" so they are sorted to the front.
// Equal priorities are sorted by sequence number to provide FIFO ordering.
return left == right ?
this.mSequence - other.mSequence :
right.ordinal() - left.ordinal();
}
}
//图片的网络请求类
public class ImageRequest extends Request {
@Override
public Priority getPriority() {
return Priority.LOW;
}
}
//文本的网络请求类根本就没有override getPriority()方法
public class StringRequest extends Request {
}
volley定义了4个请求优先级, 但实际上所有网络请求类的getPriority()返回的都是Priority.LOW, 并且没有提供设置优先级的API.
public abstract class Request implements Comparable> {
public enum Priority {
LOW,
NORMAL,
HIGH,
IMMEDIATE
}
}
对volley的扩展
要想设置优先级, 可以扩展自己的网络请求类.
public class MyImageRequest extends ImageRequest {
private Priority mPriority = Priority.LOW;
@Override
public Priority getPriority() {
return mPriority;
}
//新加个API去设置优先级
public void setPriority(Priority priority) {
mPriority = priority;
}
}
或是使用匿名内部类.
StringRequest request = new StringRequest(Request.Method.GET,"feed URL",volleyListener, volleyErrorListener) {
@Override
public Priority getPriority() {
return Priority.IMMEDIATE;
}
};
对volley的优化
volley还是不够灵活, 所有的请求都是FIFO ordering先进先出.
有这么一个场景, 在滑动listview的时候, 希望后添加进去的请求先被执行,因为后添加的item肯定是在用户的可见区, volley默认是实现不了的.
可以在初始化
private final PriorityBlockingQueue> mCacheQueue =
new PriorityBlockingQueue>();
时候, 给PriorityBlockingQueue提供一个自定义的比较器.
public PriorityBlockingQueue(int initialCapacity,
Comparator super E> comparator)
在比较器中, 实现API
public int compare(T lhs, T rhs);
这样就可以实现PriorityBlockingQueue中所有元素的反向排序, 实现先进后出.
通过设置不同的比较器, 实现优先级队列的正向, 反向排序, 使用的就是设计模式中的策略模式.
----DONE.---------