很早之前我写过一篇博客用来分析LinkedList
Collection源码之路(2)——LinkedList
那个时候提到了LinkedList实现了Deque接口,Deque其实就是在Queue的基础上增加了一些方法变成了可以操作两端的队列,那就让我们在这篇博客里面聊聊这个Queue吧
public interface Queue<E> extends Collection<E> {
boolean add(E e);//队列添加一个元素,如果队列数量无限制的优先使用
boolean offer(E e);//队列添加一个元素,如果队列数量有限制的优先使用
E remove(); //获取队列的第一个元素,同时删除掉此元素,如果队列为空抛出NoSuchElementException异常
E poll(); //获取队列的第一个元素,同时删除掉此元素
E element();//获取队列的第一个元素,但是不删除该元素,如果队列为空会抛出NoSuchElementException异常
E peek(); //获取队列的第一个元素,但是不删除该元素
}
口说无凭让我们通过代码测试下这几个方法
public static void main(String[] args) {
LinkedList<String> linkedList = new LinkedList<>();
for (int i = 0; i < 10; i++) {
linkedList.offer(i + "");
}
while (!linkedList.isEmpty()){
System.out.println(linkedList.poll());
}
}
输出结果
0
1
2
3
4
5
6
7
8
9
接下来我们测试peek方法
public static void main(String[] args) {
LinkedList<String> linkedList = new LinkedList<>();
for (int i = 0; i < 10; i++) {
linkedList.offer(i + "");
}
System.out.println("第一个元素是"+linkedList.peek());
while (!linkedList.isEmpty()){
System.out.println(linkedList.poll());
}
}
输出结果是:
第一个元素是0
0
1
2
3
4
5
6
7
8
9
可以看出来peek是只执行获取操作而不会删除元素,下面测试下remove方法
public static void main(String[] args) {
LinkedList<String> linkedList = new LinkedList<>();
for (int i = 0; i < 10; i++) {
linkedList.offer(i + "");
}
System.out.println("第一个元素是"+linkedList.remove());
while (!linkedList.isEmpty()){
System.out.println(linkedList.poll());
}
}
输出结果就变了:
第一个元素是0
1
2
3
4
5
6
7
8
9
这也就意味着第一个元素的话remove方法已经把元素删除了而且是删除的第一个元素,几乎可以等价poll方法
我们平时项目中会有一些要求队列的需求,比如播放语音——普通消息的话就按照先后顺序来播放,但是如果是重要的消息就插队优先播放该消息,下面看下我一个项目的demo
private static LinkedList<QueueBean> queue;
private static class QueueBean {
//语音文字
public String msg;
//语音文字的优先级
public boolean isHighPriorty;
}
/**
* 普通优先级的语音消息进入队列
*
* @param msg
*/
public static synchronized void enqueueMsg(String msg) {
if (queue != null) {
QueueBean bean = new QueueBean();
bean.msg = msg;
bean.isHighPriorty = false;
queue.offer(bean);
playInternalQueueVoice();
}
}
/**
* 高优先级的语音消息进入队列
*
* @param msg
*/
public static synchronized void enqueueHighPriorityMsg(String msg) {
if (queue != null) {
queue.clear();
QueueBean bean = new QueueBean();
bean.msg = msg;
bean.isHighPriorty = true;
queue.offer(bean);
playInternalQueueVoice();
}
}
/**
* 播放语音队列
*/
private static synchronized void playInternalQueueVoice() {
if (mTts == null || queue == null) {
return;
}
if (queue.peek() == null) {
return;
}
QueueBean bean = queue.peek();
if (mTts.isSpeaking() && !bean.isHighPriorty) {
//如果此时有语音播放就不用去播放了,因为else方法里面会去将所有的消息播放完毕的并清空队列的
//如果是低优先级的消息就不播放了,如果是高优先级的消息需要插队播放
} else {
QueueBean bean1 = queue.poll();
if (bean1 == null) return;
//播放提示音,钱包入袋 派单等balala
try {
playPaySound(bean1);
playOrderSound(bean1);
}catch (Exception e){
CrashReport.postCatchedException(e);
}
int code = mTts.startSpeaking(bean1.msg, new SynthesizerListener() {
@Override
public void onSpeakBegin() {
}
@Override
public void onBufferProgress(int i, int i1, int i2, String s) {
}
@Override
public void onSpeakPaused() {
}
@Override
public void onSpeakResumed() {
}
@Override
public void onSpeakProgress(int i, int i1, int i2) {
}
@Override
public void onCompleted(SpeechError speechError) {
playInternalQueueVoice();
}
@Override
public void onEvent(int i, int i1, int i2, Bundle bundle) {
}
});
AliyunLogClient.asyncUploadLog(Utils.getContext(), AliyunLogClient.SYSTEMLOG, "语音合成完成", "message:" + bean1.msg + " : code:" + code);
Log.i("TAG", "startPlayerVoice: " + bean1.msg);
}
}