整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          統(tǒng)計(jì)列表(list)中每個(gè)元素出現(xiàn)的次數(shù)


          題描述:

          languages = ['python', 'java', 'python', 'c', 'c++', 'go', 'c#', 'c++', 'lisp', 'c', 'javascript', 'java', 'python', 'matlab', 'python', 'go', 'java']

          解決方案

          統(tǒng)計(jì)結(jié)果為element:count的形式,統(tǒng)計(jì)結(jié)果采用dict從左到右一次遍歷list中元素,判斷是否在dict中,如果不在則將element存入dict并設(shè)置count為1,否則將dict中element對(duì)應(yīng)的count加1后再存儲(chǔ)到dict中

          #encoding:utf-8
          languages = ['python', 'java', 'python', 'c', 'c++', 'go', 'c#', 'c++', 'lisp', 'c', 'javascript', 'java', 'python', 'matlab', 'python', 'go', 'java']
          
          stat={}
          
          for language in languages:
          	if language not in stat:
          		stat[language]=1
          	else:
          		stat[language]+=1
          print(stat)
          ————————————————
          版權(quán)聲明:本文為CSDN博主「lumangnote」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
          原文鏈接:https://blog.csdn.net/Filme/java/article/details/84882447

          運(yùn)行結(jié)果:

          這一篇文章將講述Redis中的list類型命令,同樣也是通過demo來講述,其他部分這里就不在贅述了。

          項(xiàng)目Github地址:https://github.com/rainbowda/learnWay/tree/master/learnRedis/case-list

          案例

          demo功能是隊(duì)列,整個(gè)demo的大致頁面如下。左邊是存儲(chǔ)到Redis中的數(shù)據(jù),右邊是從Redis中彈出的數(shù)據(jù)。

          準(zhǔn)備工作

          首先定義一個(gè)存儲(chǔ)list的key

          private static final String LIST_KEY = "list:1";
          

          隊(duì)列的key就用list:1

          redis操作對(duì)象

          private RedisTemplate redisTemplate;
          //string 命令操作對(duì)象
          private ValueOperations valueOperations;
          //list 命令操作對(duì)象
          private ListOperations listOperations;
          

          list在Redis中的結(jié)構(gòu)可以看下圖(圖片來源于Redis in Action)。

          插入數(shù)據(jù)

          頭部插入

          命令介紹

          命令用例描述LPUSHLPUSH key value [value ...]將所有指定的值插入到存于 key 的列表的頭部。 如果 key 不存在,那么在進(jìn)行 push 操作前會(huì)創(chuàng)建一個(gè)空列表。LPUSHXLPUSHX key value只有當(dāng) key 已經(jīng)存在并且存著一個(gè) list 的時(shí)候,在這個(gè) key 下面的 list 的頭部插入 value。

          接下來看看demo中頭部插入的功能,點(diǎn)擊下圖中頭部插入按鈕,然后在彈出框中填入數(shù)字0,點(diǎn)擊提交后整個(gè)頭部插入流程結(jié)束。可以看到左邊的隊(duì)列數(shù)據(jù)出現(xiàn)了一條{"data":"0"} 數(shù)據(jù),在數(shù)據(jù){"data":"1"} 上面。

          來看看后臺(tái)的方法

          @RequestMapping(value = "/leftPop",method = RequestMethod.GET)
          public Object leftPop(){
           return listOperations.leftPop(LIST_KEY);
          }
          

          如果需要在Redis中操作,可以敲下面的命令

          lpush list:1 "{\"data\":\"0\"}" 
          

          尾部插入

          命令介紹

          命令用例描述RPUSHRPUSH key value [value ...]向存于 key 的列表的尾部插入所有指定的值。如果 key 不存在,那么會(huì)創(chuàng)建一個(gè)空的列表然后再進(jìn)行 push 操作。RPUSHXRPUSHX key value將值 value 插入到列表 key 的表尾, 當(dāng)且僅當(dāng) key 存在并且是一個(gè)列表。

          接下來看看demo中尾部插入的功能,點(diǎn)擊下圖中尾部插入按鈕,然后在彈出框中填入數(shù)字11,點(diǎn)擊提交后整個(gè)新增流程結(jié)束。可以看到左邊的隊(duì)列數(shù)據(jù)出現(xiàn)了一條{"data":"11"} 數(shù)據(jù),在數(shù)據(jù){"data":"10"}下面。

          來看看后臺(tái)的方法

          @RequestMapping(value = "/rightPop",method = RequestMethod.GET)
          public Object rightPop(){
           return listOperations.rightPop(LIST_KEY);
          }
          

          如果需要在Redis中操作,可以敲下面的命令

          rpush list:1 "{\"data\":\"11\"}" 
          

          列表查詢

          命令介紹

          同樣先看看相關(guān)的獲取值命令

          命令用例描述LRANGELRANGE key start stop返回存儲(chǔ)在 key 的列表里指定范圍內(nèi)的元素。LINDEXLINDEX key index返回列表里的元素的索引 index 存儲(chǔ)在 key 里面。LLENLLEN key返回存儲(chǔ)在 key 里的list的長度。

          后臺(tái)查詢方法,將新增的內(nèi)容查詢出來

          @RequestMapping(value = "/getList",method = RequestMethod.GET)
          public List getList(){
           List list = listOperations.range(LIST_KEY, 0, -1);
           //可以用size獲取成員長度
           //listOperations.size(LIST_KEY);
           return list;
          }
          

          數(shù)據(jù)彈出

          頭部彈出

          命令用例描述LPOPLPOP key移除并且返回 key 對(duì)應(yīng)的 list 的第一個(gè)元素。BLPOPBLPOP key [key ...] timeout它是命令 LPOP 的阻塞版本,這是因?yàn)楫?dāng)給定列表內(nèi)沒有任何元素可供彈出的時(shí)候, 連接將被 BLPOP 命令阻塞。

          接下來看看頭部彈出的功能,點(diǎn)擊下圖中頭部彈出按鈕,可以看到左邊的隊(duì)列頂部數(shù)據(jù)減少了,在右邊彈出的數(shù)據(jù)出現(xiàn)了左邊隊(duì)列數(shù)據(jù)消失的數(shù)據(jù)。

          來看看后臺(tái)的方法

          @RequestMapping(value = "/leftPop",method = RequestMethod.GET)
          public Object leftPop(){
           return listOperations.leftPop(LIST_KEY);
          }
          

          如果需要在Redis中操作,可以敲下面的命令

          lpop list:1 
          

          尾部彈出

          命令用例描述RPOPRPOP key移除并返回存于 key 的 list 的最后一個(gè)元素。BRPOPBRPOP key [key ...] timeout它是 RPOP 的阻塞版本,因?yàn)檫@個(gè)命令會(huì)在給定list無法彈出任何元素的時(shí)候阻塞連接。

          接下來看看尾部彈出的功能,點(diǎn)擊下圖中尾部彈出按鈕,可以看到左邊的隊(duì)列尾部數(shù)據(jù)減少了,在右邊彈出的數(shù)據(jù)出現(xiàn)了左邊隊(duì)列數(shù)據(jù)消失的數(shù)據(jù)。

          來看看后臺(tái)的方法

          @RequestMapping(value = "/rightPop",method = RequestMethod.GET)
          public Object rightPop(){
           return listOperations.rightPop(LIST_KEY);
          }
          

          如果需要在Redis中操作,可以敲下面的命令

          rpop list:1 
          

          其他命令

          命令用例描述LINSERTLINSERT key BEFORE\AFTER pivot value把 value 插入存于 key 的列表中在基準(zhǔn)值 pivot 的前面或后面。LREMLREM key count value從存于 key 的列表里移除前 count 次出現(xiàn)的值為 value 的元素。LSETLSET key index value設(shè)置 index 位置的list元素的值為 value。LTRIMLTRIM key start stop修剪(trim)一個(gè)已存在的 list,這樣 list 就會(huì)只包含指定范圍的指定元素。RPOPLPUSHRPOPLPUSH source destination原子性地返回并移除存儲(chǔ)在 source 的列表的最后一個(gè)元素(列表尾部元素), 并把該元素放入存儲(chǔ)在 destination 的列表的第一個(gè)元素位置(列表頭部)。BRPOPLPUSHBRPOPLPUSH source destination timeoutBRPOPLPUSH 是 RPOPLPUSH 的阻塞版本。

          RPOPLPUSH和BRPOPLPUSH

          這兩個(gè)命令作用其實(shí)是相同的,只不過BRPOPLPUSH是阻塞的,當(dāng)沒有數(shù)據(jù)時(shí),會(huì)一直阻塞,直到有數(shù)據(jù)。

          在Redis官方文檔中,用RPOPLPUSH命令舉了兩個(gè)例子,一個(gè)是Reliable queue(安全的隊(duì)列 ),另一個(gè)是Circular list(循環(huán)列表)。

          Reliable queue(安全的隊(duì)列 )

          Redis通常都被用做一個(gè)處理各種后臺(tái)工作或消息任務(wù)的消息服務(wù)器。 一個(gè)簡單的隊(duì)列模式就是:生產(chǎn)者把消息放入一個(gè)列表中,等待消息的消費(fèi)者用 RPOP 命令(用輪詢方式), 或者用 BRPOP 命令(如果客戶端使用阻塞操作會(huì)更好)來得到這個(gè)消息。

          然而,因?yàn)橄⒂锌赡軙?huì)丟失,所以這種隊(duì)列并是不安全的。例如,當(dāng)接收到消息后,出現(xiàn)了網(wǎng)絡(luò)問題或者消費(fèi)者端崩潰了, 那么這個(gè)消息就丟失了。

          RPOPLPUSH (或者其阻塞版本的 BRPOPLPUSH) 提供了一種方法來避免這個(gè)問題:消費(fèi)者端取到消息的同時(shí)把該消息放入一個(gè)正在處理中的列表。 當(dāng)消息被處理了之后,該命令會(huì)使用 LREM 命令來移除正在處理中列表中的對(duì)應(yīng)消息。

          另外,可以添加一個(gè)客戶端來監(jiān)控這個(gè)正在處理中列表,如果有某些消息已經(jīng)在這個(gè)列表中存在很長時(shí)間了(即超過一定的處理時(shí)限), 那么這個(gè)客戶端會(huì)把這些超時(shí)消息重新加入到隊(duì)列中。

          翻譯來自 http://www.redis.cn/commands/rpoplpush.html

          Circular list(循環(huán)列表)

          RPOPLPUSH 命令的 source 和 destination 是相同的話, 那么客戶端在訪問一個(gè)擁有n個(gè)元素的列表時(shí),可以在 O(N) 時(shí)間里一個(gè)接一個(gè)獲取列表元素, 而不用像 LRANGE那樣需要把整個(gè)列表從服務(wù)器端傳送到客戶端。

          上面這種模式即使在以下兩種情況下照樣能很好地工作: 有多個(gè)客戶端同時(shí)對(duì)同一個(gè)列表進(jìn)行旋轉(zhuǎn)(rotating):它們會(huì)取得不同的元素,直到列表里所有元素都被訪問過,又從頭開始這個(gè)操作。 有其他客戶端在往列表末端加入新的元素。

          這個(gè)模式讓我們可以很容易地實(shí)現(xiàn)這樣一個(gè)系統(tǒng):有 N 個(gè)客戶端,需要連續(xù)不斷地對(duì)一批元素進(jìn)行處理,而且處理的過程必須盡可能地快。 一個(gè)典型的例子就是服務(wù)器上的監(jiān)控程序:它們需要在盡可能短的時(shí)間內(nèi),并行地檢查一批網(wǎng)站,確保它們的可訪問性。

          值得注意的是,使用這個(gè)模式的客戶端是易于擴(kuò)展(scalable)且安全的(reliable),因?yàn)榧词箍蛻舳税呀邮盏降南G失了, 這個(gè)消息依然存在于隊(duì)列中,等下次迭代到它的時(shí)候,由其他客戶端進(jìn)行處理。

          翻譯來自 http://www.redis.cn/commands/rpoplpush.html

          案例-約瑟夫問題

          約瑟夫問題(有時(shí)也稱為約瑟夫斯置換),是一個(gè)出現(xiàn)在計(jì)算機(jī)科學(xué)和數(shù)學(xué)中的問題。在計(jì)算機(jī)編程的算法中,類似問題又稱為約瑟夫環(huán)。

          人們站在一個(gè)等待被處決的圈子里。 計(jì)數(shù)從圓圈中的指定點(diǎn)開始,并沿指定方向圍繞圓圈進(jìn)行。 在跳過指定數(shù)量的人之后,執(zhí)行下一個(gè)人。 對(duì)剩下的人重復(fù)該過程,從下一個(gè)人開始,朝同一方向跳過相同數(shù)量的人,直到只剩下一個(gè)人,并被釋放。

          問題即,給定人數(shù)、起點(diǎn)、方向和要跳過的數(shù)字,選擇初始圓圈中的位置以避免被處決。

          來自維基百科 https://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%E6%96%AF%E9%97%AE%E9%A2%98

          思路

          定義一個(gè)list key為josephus,利用

          RPOPLPUSH josephus josephus
          

          命令來構(gòu)造循環(huán)鏈表,每當(dāng)數(shù)到3時(shí),使用rpop

          rpop josephus
          

          命令彈出

          代碼實(shí)現(xiàn)

          public class JosephusProblem extends RedisBaseConnection {
           @Test
           public void test() {
           //構(gòu)造數(shù)據(jù)
           for (int i = 1; i <= 41; i++) {
           listOperations.leftPush("josephus", String.valueOf(i));
           }
           int index = 1;
           while (listOperations.size("josephus") > 0) {
           //當(dāng)數(shù)到3時(shí),彈出
           if (index == 3) {
           System.out.println(listOperations.range("josephus", 0, -1));
           System.out.println("當(dāng)前被殺的人是:" + listOperations.rightPop("josephus"));
           index = 0;
           } else {
           listOperations.rightPopAndLeftPush("josephus", "josephus");
           }
           index++;
           }
           }
          }
          

          整個(gè)代碼步驟如下

          1. 先是模擬有41個(gè)人(向redis中key為josephus的list添加41個(gè)數(shù)據(jù))
          2. 定義索引index
          3. 循環(huán)判斷key為josephus的數(shù)據(jù)長度是否大于0
          4. 當(dāng)索引index為3時(shí),調(diào)用Redis的rpop命令彈出對(duì)應(yīng)的數(shù)據(jù)。索引index不為3時(shí),調(diào)用RPOPLPUSH命令,將對(duì)應(yīng)的數(shù)據(jù)放到隊(duì)列頭部
          5. 索引index加1

          運(yùn)行結(jié)果有點(diǎn)長,這里只截圖最后一部分的結(jié)果,如下

          約瑟夫問題代碼請(qǐng)點(diǎn)擊JosephusProblem.java


          建議學(xué)習(xí)的人最好每個(gè)命令都去敲下,加深印象。下面詩句送給你們。

          紙上得來終覺淺,絕知此事要躬行。————出自《冬夜讀書示子聿》

          作者:勿妄

          備工作:使用靜態(tài)塊初始化List數(shù)據(jù)

          private static List<Integer> list;	
          //靜態(tài)塊 ==> 初始化ArrayList
          static {
            list = new ArrayList<>(10);
            for(int index = 1; index <= 10; index++) {
              list.add(index);
            }
          }	

          1.普通while循環(huán)遍歷

          public static void test1() {
            System.out.println("第一種方式:普通while循環(huán)遍歷List集合");
            int index = 0;
            while(index < list.size()) {
              System.out.println(list.get(index));
              index++;
            }
          }

          2.普通do...while循環(huán)遍歷

          public static void test2() {
            System.out.println("第二種方式:普通do...while循環(huán)遍歷List集合");
            int index = 0;
            do{
              System.out.println(list.get(index));
              index++;
            }while(index < list.size());
          }

          3.普通for循環(huán)遍歷

          public static void test3() {
            System.out.println("第三種方式:普通for循環(huán)遍歷List集合");
            for (int index = 0; index < list.size(); index++) {
              System.out.println(list.get(index));
            }
          }

          4.增強(qiáng)for循環(huán)遍歷

          public static void test4() {
            System.out.println("第四種方式:增強(qiáng)for循環(huán)遍歷List集合");
            for (int element : list) {
              System.out.println(element);
            }
          }

          5.Iterator迭代器循環(huán)遍歷

          public static void test5() {
            System.out.println("第五種方式:Iterator迭代器循環(huán)遍歷List集合");
            Iterator<Integer> it = list.iterator();
            while(it.hasNext()) {
              System.out.println(it.next());
            }
          }

          6.ListIterator迭代器循環(huán)遍歷

          public static void test6() {
            System.out.println("第六種方式:ListIterator迭代器循環(huán)遍歷List集合");
            Iterator<Integer> it = list.listIterator();
            while(it.hasNext()) {
              System.out.println(it.next());
            }
          }

          7.Lambda表達(dá)式遍歷(jdk1.8+)

          public static void test7() {
            System.out.println("第七種方式:Lambda表達(dá)式遍歷List集合");
            list.forEach(element -> System.out.println(element));
            list.forEach(System.out::println);//方法參考引用
          }

          8.Stream流 + Lambda表達(dá)式(jdk1.8+)

          public static void test8() {
            System.out.println("第八種方式:Stream流 + Lambda表達(dá)式遍歷List集合");
            //單線程順序流 ==> 先過濾后遍歷
            list.stream().filter(element -> element % 2 == 0).forEach(System.out::println);
            //多線程并行流 ==> 先過濾后遍歷
            list.parallelStream().filter(element -> element % 2 == 0).forEach(System.out::println);
          }

          至此搞定,java循環(huán)遍歷List集合就這么簡單,小伙伴們不妨試試。


          主站蜘蛛池模板: 日韩一区二区三区免费体验| 国产午夜精品一区理论片飘花| 亚洲AV成人精品一区二区三区| 久久国产精品无码一区二区三区 | 激情内射亚洲一区二区三区爱妻 | 国产亚洲3p无码一区二区| 99国产精品一区二区| 日韩精品区一区二区三VR| 国产精品视频一区二区三区| 国产成人av一区二区三区在线观看| 日韩精品一区二区三区影院| 精品国产一区二区三区久久蜜臀 | 国产高清在线精品一区二区三区| 国产在线观看一区二区三区精品| 中文字幕一区二区三区久久网站| 精品国产一区二区三区AV | 精品国产不卡一区二区三区| 日本不卡一区二区三区| 亚洲一区二区三区高清在线观看 | 国产自产V一区二区三区C| 亚洲视频在线一区| 夜精品a一区二区三区| 亚洲老妈激情一区二区三区| 亚洲一区二区三区丝袜| 久久久人妻精品无码一区| 亚洲一区二区三区乱码在线欧洲| 国产av一区最新精品| 国产成人无码精品一区二区三区| 无码视频一区二区三区| 久久久久无码国产精品一区| 精品无码中出一区二区| 中文字幕一区二区三区久久网站| 一区二区三区国模大胆| 91精品乱码一区二区三区| 中文字幕一区二区视频| 国产嫖妓一区二区三区无码| 3d动漫精品啪啪一区二区中| 国产精品一区二区三区99| 国产精品无码一区二区三区毛片| 国产精品va无码一区二区| 福利片免费一区二区三区|