日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JAVA循环队列

發布時間:2023/12/9 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA循环队列 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

關于自定義循環隊列的實現原理和要點可以參見之前的博文系列:循環隊列及C語言實現。這里主要對JAVA下的具體實現方式與原理進行說明。

一、JAVA 中已經自帶了 Queue、DQueue、ArrayList、LinkedList 等常用的數據結構,為什么還要單獨實現循環隊列?

之所以使用自定義循環隊列,出發點還是基于我們在實際應用中對于數據處理各種各樣的需求。使用自定義數據結構的好處就在于可以更加靈活的處理各種數據,增加自己需要的接口。然而弊端就是你的 code 可能會引入各種未知的 Bug。所以,在滿足我們使用前提的場景下,使用上述已有數據結構等是比較推薦的,如果滿足不了實際項目需求,再通過自定義的方式等實現是我們理想的一種選擇。

二、什么場景需要使用自定義循環隊列?

對于數據的處理要求比較靈活,比如:我們需要開發一個安卓服務器程序,需要不斷處理每個客戶端的請求以及完成與客戶端的交互。發送來的數據需要及時處理,但同時數據以自定義格式進行傳輸:包頭+長度+數據+包尾+校驗。如上格式,服務器端需要不斷將接收的數據進行緩存與解析,如果未滿一幀那么需要緩存到下次數據接收過來再進行解析。這時,我們需要批量從隊列讀取數據以及如果一幀數據不完全,將讀取的數據復原到隊列中(更改隊列當前讀位置)的功能。此時,就可以考慮自己實現隊列滿足這些特殊的需求。

三、循環隊列的特點與要素

1、先進先出(FIFO);

2、隊列首尾元素位置;

3、常用隊列操作:初始化、銷毀、遍歷、讀寫等;

四、源碼實現

為便于使用,這里將該循環隊列以類的方式實現:

/** Copyright (c) 2017, SoldierJazz. All rights reserved.* Use is subject to license terms.**/package com.exmple.java.text;/*** DataQueue 類實現為FIFO循環隊列** <p> 使用前需要根據實際需求為隊列分配合理的隊列空間大小** 創建一個4K空間的隊列如下所示:** DataQueue mdataqueue= new DataQueue(4096);** <p> 更多使用信息可以參考引用該類的例程,有關問題,可發送到* SoldierJazz@163.com 尋求支持。** @author SoldierJazz* @version 1.0.0*/public class DataQueue {Queue q = null;public class Queue {byte[] data = null;int read;int write;int size;int space;}Object mSemaphore = new Object();DataQueue(int size) {q = new Queue();Queue_Init(q, size);}/*** 返回當前隊列可用數據量** @param q 目標隊列**/int Avail(Queue q) {return q.size - q.space;}/*** 初始化隊列** @param q 目標隊列* * @param size 隊列分配內存大小**/void Queue_Init(Queue q, int size) {synchronized (mSemaphore) {q.data = new byte[size];q.read = 0;q.write = 0;q.size = size;q.space = size;}}/*** 銷毀隊列** @param q 目標隊列**/void Queue_Destroy(Queue q) {synchronized (mSemaphore) {q.read = q.write = 0;q.space = q.size;}}/*** 判斷當前隊列是否為空** @param q 目標隊列** @return true表示隊列為空<br>false表示隊列不為空**/boolean Queue_Empty(Queue q) {return (q.space == q.size);}/*** 判斷當前隊列是否已滿** @param q 目標隊列** @return true表示隊列已滿<br>false表示隊列未滿**/boolean Queue_Full(Queue q) {return (q.space == 0);}/*** 寫一個byte到目標隊列** @param q 目標隊列* * @param val 寫入的byte值** @return true表示寫入成功<br>false表示寫入失敗**/boolean AddQueue(Queue q, byte val) {if (!Queue_Full(q)) {q.data[q.write] = val;q.write = (q.write + 1) % q.size;q.space--;return true;} return false;}/*** 從隊列中讀取一個字節** @param q 目標隊列* * @param data 讀取的字節** @return true表示讀取成功<br>false表示讀取失敗**/boolean DelQueue(Queue q, Byte data) {if (!Queue_Empty(q)) {data = q.data[q.read];q.read = (q.read + 1) % q.size;q.space++;return true;}return false;}/*** 批量寫入長度為len的字節到隊列** @param q 目標隊列* * @param data 寫入的byte數組* * @param len 寫入的數組長度** @return 成功寫入的字節數量**/int WriteQueue(Queue q, byte[] data, int len){int ret = 0;int rest = q.size - q.write;synchronized (mSemaphore) {if (!Queue_Full(q)) {if (q.space >= len) {ret = len;if (rest >= len) {System.arraycopy(data, 0, q.data, q.write, len);q.write = (q.write + len) % q.size;q.space -= len;} else {System.arraycopy(data, 0, q.data, q.write, rest);q.write = 0;System.arraycopy(data, rest, q.data, 0, len - rest);q.write = len -rest;q.space -= len;}} else {ret = q.space;if (rest >= q.space) {System.arraycopy(data, 0, q.data, q.write, q.space);q.write = (q.write + q.space) % q.size;q.space = 0;} else {System.arraycopy(data, 0, q.data, q.write, rest);q.write = 0;System.arraycopy(data, rest, q.data, 0, q.space - rest);q.write = q.space -rest;q.space = 0;}} }return ret;}}/*** 從隊列中恢復長度len個字節的數據** @param q 目標隊列* * @param len 要恢復的長度** @return 成功恢復的字節數**/int RecoverReadQueue(Queue q, int len) {int ret = 0;int rest = q.read;synchronized (mSemaphore) {if (q.space >= len)ret = len;elseret = q.space;if (rest >= ret) {q.read -= ret;} else {q.read = q.size - (ret - rest);}q.space -= ret;return ret;}}/*** 從隊列中讀取len個字節數據到data數組中** @param q 目標隊列* * @param data 用于存放數據的目標數組* * @param start 拷貝至目標數組的起始位置* * @param len 讀取的長度* * @return 成功讀取的字節數**/int ReadQueue(Queue q, byte[] data, int start, int len) {int rest = q.size - q.read;int ret = 0;synchronized (mSemaphore) {if (!Queue_Empty(q)) {if (Avail(q) >= len) {ret = len;if (rest >= len) {System.arraycopy(q.data, q.read, data, start, len);q.read = (q.read + len) % q.size;q.space += len;} else {System.arraycopy(q.data, q.read, data, start, rest);q.read = 0;System.arraycopy(q.data, 0, data, start + rest, len - rest);q.read = len -rest;q.space += len;}return len;} else {ret = Avail(q);if (rest >= Avail(q)) {System.arraycopy(q.data, q.read, data, start, Avail(q));q.read = (q.read + Avail(q)) % q.size;q.space = q.size;} else {System.arraycopy(q.data, q.read, data, start, rest);q.read = 0;System.arraycopy(q.data, 0, data, start + rest, Avail(q) - rest);q.read = Avail(q) -rest;q.space = q.size;}}} return ret;}} }以上內容為使用該類及相關方法的定義,比較簡單,看注解即可。下面針對該類做一個使用與測試程序:

public void TestDataQueue() {DataQueue dataq = new DataQueue(100);byte[] a1 = {1, 2, 3, 4, 5, 6};byte[] a2 = {7, 8, 9, 10};byte[] b = new byte[10];int nread = 0;dataq.WriteQueue(dataq.q, a1, a1.length);nread = dataq.ReadQueue(dataq.q, b, 0, 3);System.out.println("length of queue: " + dataq.Avail(dataq.q));for (int i = 0; i < nread; i++) {System.out.printf("byte[%d]: %d\n", i, b[i]);}dataq.WriteQueue(dataq.q, a2, a2.length);System.out.println("length of queue: " + dataq.Avail(dataq.q));nread = dataq.ReadQueue(dataq.q, b, 0, dataq.Avail(dataq.q));System.out.println("length of queue: " + dataq.Avail(dataq.q));for (int i = 0; i < nread; i++) {System.out.printf("byte[%d]: %d\n", i, b[i]);}}public static void main(String args[]) {test t = new test();t.TestDataQueue();}運行結果如下所示:



有疑問或者問題就給我郵件或者評論吧,覺得有用就點贊吧~:-D



總結

以上是生活随笔為你收集整理的JAVA循环队列的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。