【JVM】如何理解強引用、軟引用、弱引用、虛引用?_潭子電動車

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污

整體架構

強引用

強引用是默認支持,當內存不足的時候,JVM開始垃圾回收,對於強引用的對象,就算是出現了OOM也不會回收對象。

強引用是最常見的普通對象引用,只要還有強引用指向對象,對象就存活,垃圾回收器不會處理存活對象。一般把一個對象賦給一個引用變量,這個引用變量就是強引用。當一個對象被強引用變量所引用,它就處於可達狀態,是不會被垃圾回收的,即使之後都不會再用到了,也不會回收。因此強引用是造成Java內存泄漏的主要原因之一

關於Java內存泄漏的詳細內容,可以參考這篇博客:https://blog.csdn.net/m0_38110132/article/details/81986334。

對於一個普通對象,如果沒有其他引用關係,只要超過了引用的作用域或者顯式地將相應的強引用賦值為null,一般認為就是可以被垃圾回收了。(具體的回收時機看垃圾回收策略)

下例中,b就是強引用。

1     public static void main(String[] args) {
2         Object a = new Object();
3         Object b = a;
4         a = null;
5         System.out.println(b);//java.lang.Object@4554617c
6     }

軟引用

軟引用是一種相對強引用弱化了一些的引用,用java.lang.ref.SoftReference實現,可以讓對象豁免一些垃圾收集。當系統內存充足的時候,不會被回收;當系統內存不足的時候,會被回收。

軟引用一般用於對內存敏感的程序中,比如高速緩存。

 1 import java.lang.ref.SoftReference;
 2 
 3 public class SoftReferenceDemo {
 4     public static void main(String[] args) {
 5         Object a = new Object();
 6         SoftReference<Object> softReference = new SoftReference<>(a);//軟引用
 7         //a和軟引用指向同一個對象
 8         System.out.println(a);//java.lang.Object@4554617c
 9         System.out.println(softReference.get());//java.lang.Object@4554617c
10 
11         //內存夠用,軟引用不會被回收
12         a = null;
13         System.gc();//內存夠用不會自動gc,手動喚醒gc
14         System.out.println(a);//null
15         System.out.println(softReference.get());//java.lang.Object@4554617c
16 
17         //內存不夠用時
18         try{
19             //配置Xms和Xmx為5MB
20             byte[] bytes = new byte[1024*1024*30];//設置30MB超內存
21         }catch (Throwable e){
22             e.printStackTrace();
23         }finally {
24             System.out.println(a);//null
25             System.out.println(softReference.get());//null
26         }
27     }
28 }

使用場景

一個應用需要讀取大量的本地圖片,如果每次讀取都從硬盤讀取會嚴重影響性能,如果一次性全部加載到內存,內存可能會溢出。

可以使用軟引用解決這個問題,使用一個HashMap來保存圖片路徑和圖片對象管理的軟引用之間的映射關係,內存不足時,JVM會自動回收緩存圖片對象的佔用空間,有效地避免了OOM(Out Of Memory)問題。

Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>

弱引用

弱引用需要用java.lang.ref.WeakReference實現,它比軟引用的生存期更短,對於弱引用的對象來說,只要垃圾回收機制一運行,不管JVM的內存空間是否夠,都會回收該對象的佔用內存。

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

 1 import java.lang.ref.WeakReference;
 2 
 3 public class SoftReferenceDemo {
 4     public static void main(String[] args) {
 5         Object a = new Object();
 6         WeakReference<Object> softReference = new WeakReference<>(a);//軟引用
 7         //a和弱引用指向同一個對象
 8         System.out.println(a);//java.lang.Object@4554617c
 9         System.out.println(softReference.get());//java.lang.Object@4554617c
10 
11         //內存夠用,弱引用也會被回收
12         a = null;
13         System.gc();//內存夠用不會自動gc,手動喚醒gc
14         System.out.println(a);//null
15         System.out.println(softReference.get());//null
16     }
17 }

關於WeakHashMap

 1     public static void weakHashMapTest() {
 2         Integer key = new Integer(1);
 3         String value = "李四";
 4         Map<Integer,String> weakHashMap = new WeakHashMap();
 5         weakHashMap.put(key, value);
 6         System.out.println(weakHashMap);//{1=李四}
 7         key = null;
 8         System.gc();
 9         System.out.println(weakHashMap);//{}
10     }
11 
12     public static void hashMapTest() {
13         HashMap<Integer,String> map = new HashMap<>();
14         Integer key = 1;
15         String value = "張三";
16         map.put(key,value);
17         System.out.println(map);//{1=張三}
18         key = null;
19         System.gc();
20         System.out.println(map);//{1=張三}
21     }

在HashMap中,鍵被置為null,喚醒gc后,不會垃圾回收鍵為null的鍵值對。但是在WeakHashMap中,鍵被置為null,喚醒gc后,鍵為null的鍵值對會被回收。

虛引用

虛引用要通過java.lang.ref.PhantomReference類來實現,虛引用不會決定對象的生命周期,如果一個對象只有虛引用,就相當於沒有引用,在任何時候都可能會被垃圾回收器回收。它不能單獨使用也不能訪問對象,虛引用必須和引用隊列聯合使用

虛引用的主要作用是跟蹤對象被垃圾回收的狀態,僅僅是提供一種確保對象被finalize以後,做某些事情的機制。

PhantomReference的get方法總是返回null,因此無法訪問對應的引用對象,設置虛引用關聯唯一的目的是在對象被收集器回收的時候收到一個系統通知,或者後續添加進一步的處理。Java允許使用finalize()方法在垃圾回收器將對象從內存中清理出去之前做一些必要的清理工作。【例如實現一個監控對象的通知機制】

引用隊列

WeakReference和ReferenceQueue的聯合使用效果:

 1     public static void weakReferenceTest() {
 2         Object a = new Object();
 3         ReferenceQueue<Object> queue = new ReferenceQueue<>();
 4         WeakReference<Object> weakReference = new WeakReference<>(a,queue);
 5         System.out.println(a);//java.lang.Object@4554617c
 6         System.out.println(weakReference.get());//java.lang.Object@4554617c
 7         System.out.println(queue.poll());//null
 8         System.out.println("-------------------");
 9         a = null;
10         System.gc();
11         System.out.println(a);//null
12         System.out.println(weakReference.get());//null
13         //虛引用在回收之前被加入到了引用隊列中
14         System.out.println(queue.poll());//java.lang.ref.WeakReference@74a14482
15     }

PhantomReference和ReferenceQueue的聯合使用效果:

 1     public static void phantomReferenceTest() {
 2         Object a = new Object();
 3         ReferenceQueue<Object> queue = new ReferenceQueue<>();
 4         PhantomReference<Object> phantomReference = new PhantomReference<>(a,queue);
 5         System.out.println(a);//java.lang.Object@4554617c
 6         System.out.println(phantomReference.get());//null
 7         System.out.println(queue.poll());//null
 8         System.out.println("-------------------");
 9         a = null;
10         System.gc();
11         System.out.println(a);//null
12         System.out.println(phantomReference.get());//null
13         //引用在回收之前被加入到了引用隊列中
14         System.out.println(queue.poll());//java.lang.ref.WeakReference@74a14482
15     }

總結

強引用:不回收。

軟引用:內存不夠就回收。

弱引用:一定回收。

虛引用:一定回收,get出來就是null,引用形同虛設,主要和引用隊列聯合使用,在finalize之前會被放到引用隊列中。

與根對象沒有引用關係的:引用不可達,一定回收。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。

生態環境部環評司有關負責人就《經濟、技術政策生態環境影響分析技術指南(試行)》有關問題答記者問_租車

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。

2020-11-10 來源:生態環境部

2020-11-10
來源:生態環境部 分享到:
[打印]
字號:[大] [中] [小]   生態環境部近日印發了《 經濟、技術政策生態環境影響分析技術指南》(試行)(以下簡稱《指南》)。針對《指南》的出台背景、主要內容、實施重點等問題,生態環境部環評司有關負責人回答了記者的提問。
  問:《指南》發布的背景和意義是什麼?   答:《指南》是貫徹落實《中華人民共和國環境保護法》的重要舉措。《環境保護法》第十四條規定“國務院有關部門和省、自治區、直轄市人民政府組織制定經濟、技術政策,應當充分考慮對環境的影響,聽取有關方面和專家的意見”。為貫徹落實上述規定,“十三五”以來,我部組織環境工程評估中心、環境與經濟政策研究中心、清華大學、北京師範大學等單位,針對區域、產業和城鎮化等領域的典型政策開展了環境評價研究,同時借鑒美國、加拿大、英國、歐盟、世界銀行和相關國際組織制定的政策(戰略)環境評價技術指南等,探索形成了適用於政策生態環境影響分析的技術方法、內容框架和成果要求,在此基礎上編製形成《指南》,可以為經濟、技術政策的制定者在分析政策的生態環境影響方面提供參考。
  問:《指南》的定位是什麼?   答:《指南》是推動政策制定過程中充分考慮生態環境影響的技術指引文件。《指南》列舉了適用的政策類型,提出了一般性分析程序和技術路線,提供了推薦性指標體系和技術方法,政策制定部門在開展環境影響分析工作過程中可根據實際情況增補或調整指標體系,選擇或創新技術方法。
  問:政策生態環境影響分析的作用是什麼?   答:經濟、技術政策關係到一個國家、地區或部門長期發展前景,影響涉及時間跨度大,空間範圍廣,影響類型多樣,政策執行過程中不確定性因素多,可能會對生態環境造成潛在的重大影響。《指南》從環境質量、生態保護、資源消耗、應對氣候變化等四個方面構建了較為全面的指標體系,政策制定部門可通過全面梳理重點識別,判斷政策是否存在重大不利生態環境影響。針對具有潛在重大不利生態環境影響的政策內容,分析其影響範圍和程度,預警可能引發的生態環境風險,通過優化政策內容、完善保障措施和制度,從源頭降低生態環境影響,防控生態環境風險。針對促進生態環境保護、改善環境質量的政策內容,通過提高保障措施和制度的有效性,推動政策落地實施。
  問:政策生態環境影響分析是否涉及新增行政程序?   答:根據《環境保護法》第十四條“國務院有關部門和省、自治區、直轄市人民政府組織制定經濟、技術政策,應當充分考慮對環境的影響”的規定,《重大行政決策程序暫行條例》縣級以上地方人民政府在制(修)定相關政策時應在決策啟動階段開展環境影響和環境效益等分析預測的要求,

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污

政策制定主體應將生態環境影響分析工作融入政策制定過程。本《指南》僅提供技術指引,不增加行政程序。
  問:《指南》包括哪些主要內容?   答:《指南》包括七部分內容。一是確定經濟、技術政策生態環境影響分析的適用範圍;二是確定政策生態環境影響分析的工作流程;三是提出政策分析內容及步驟,即政策要素解析,相關政策回顧性分析,政策與黨中央、國務院相關決策部署的符合性分析等;四是提出“初步識別”的內容及推薦方法,建議從環境質量、生態保護、資源消耗、應對氣候變化四個方面梳理政策生態環境影響,推薦採用快速、定性分析方法識別政策是否存在重大生態環境影響;五是提出“影響分析”的內容及推薦方法。推薦採用列表法分析政策直接、間接及累積性生態環境影響的範圍和程度,結合不確定性分析預測存在的生態環境風險;六是提出保障措施及制度分析的內容和步驟;七是明確結論與建議。
  問:《指南》推薦採用哪些技術方法?   答:經濟、技術政策生態環境影響範圍廣,影響產生的邏輯鏈條長,執行過程中不確定性因素多,難以定量分析。同時,一些政策出台的周期短、時效性強,需儘快判斷其可能造成的生態環境影響或風險,為政策制定和實施提供支撐和保障,因此《指南》推薦採用快速、定性方法開展生態環境影響分析。在生態環境影響初步識別階段,結合推薦性指標體系採用矩陣分析、檢查表、專家分析等方法,判斷政策是否存在重大不利生態環境影響。在環境影響分析階段,結合政策產生生態環境影響的作用方式和受影響區域特點,採用列表法分析政策對各受影響區域的直接、間接、累積性影響及生態環境風險。鑒於政策生態環境影響分析尚無普遍實踐,開展工作過程中可根據政策類型、政策內容和管理需求合理選擇或創新政策生態環境影響分析技術方法。
  問:《指南》發布后將重點推動哪些後續工作?   答:一是組織開展試點研究,形成案例庫。目前政策生態環境影響分析處於初步推廣階段,下一步將選取典型省份、典型政策領域作為試點推動開展政策生態環境影響分析工作,在試點基礎上逐步完善技術方法體系,建立政策生態環境影響分析案例庫。二是持續開展專題研究,提供更為完善的技術支撐。根據政策類型及政策內容不同,產生生態環境影響的作用機制不同,影響類型和程度也存在很大差異。基於本《指南》提出的一般性程序、技術路線和推薦方法,後續將進一步組織開展專題研究,分析政策生態環境影響機制,研究制定針對不同領域和政策類型的技術路線,提出適用於各分析環節的技術方法,為推動決策機構在政策制定過程中更好考慮對生態環境影響提供技術保障。

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

POCO M3 即將在台發表:6000mAh 超大電量,規格重點搶先看!_租車

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污

幾天前,我們曾報導過 POCO 台灣的官方 Facebook 粉絲專頁和官網上線的消息,這幾天 POCO 官方也開始在預告新機即將推出的消息,種種跡象也正暗示著 POCO 品牌獨立後的首款在台發表的新機,就是內建 6000mAh 超大電量的 POCO M3 。定位為中階入門的大電量手機, POCO M3 也早已在上個月就通過台灣 NCC 認證。

▲圖片來源:小米香港官網

POCO M3 即將在台發表:6000mAh 超大電量,規格重點搶先看!

隨著 POCO Taiwan 粉專和官網曝光後,最近在 POCO Taiwan 的 Facebook 粉絲專頁也開始推出問答抽獎活動,截至目前的兩題的答案都是「6000」,這數字正是 POCO M3 的電池容量。另外,這項活動只到 1 月 10 日,也代表在不久後 POCO M3 就會正式在台亮相。(更新:POCO M3 將於 1 月 21 日在台發表)

▲圖片來源:POCO Taiwan(Facebook)

其實早在去年 12 月初, POCO M3 就以型號 M2010J19CG 通過台灣 NCC 認證, POC M3 預計銷售模式將比照目前小米10T、小米10T Pro 方式,由官方授權通路進行販售。

▲圖片來源:NCC

在 NCC 認證通過的資料附件也能見到產品外觀照,確認它就是 POCO M3 :

▲圖片來源:NCC

雖然 POCO M3 只支援 18W 快速充電,不過充電器仍將標配 22.5W 快速充電器:

▲圖片來源:NCC

至於 POCO M3 的規格重點有哪些呢?目前 POCO M3 已在印度、香港等地開賣,這裡也提前為大家簡單介紹 POCO M3 的規格特色:

▲圖片來源:小米香港官網

POCO M3 產品定位為中階入門的 4G 智慧型手機,採用 6.53 吋 FHD+ 解析度的水滴全螢幕:

▲圖片來源:小米香港官網

相機方面, POCO M3 配備 4800 萬像素 AI 三鏡頭主相機,擁有 4800 萬像素 f/1.79 光圈主鏡頭、200 萬像素微距鏡頭以及 200 萬像素景深鏡頭的搭配。前相機則為 800 萬像素自拍鏡頭。

▲圖片來源:小米香港官網

硬體規格方面, POCO M3 搭載 Qualcomm Snapdragon 662 八核心處理器、配備 4GB RAM 和最高 128GB ROM :

▲圖片來源:小米香港官網

POCO M3 超大電量則是 POCO M3 的特色之一, POCO M3 內建 6000mAh 大電量電池並支持 18W 快速充電。 POCO M3 的續航換算日常使用情境,待機可達到 583 小時、通話 40 小時、音樂 196 小時、影片 17 小時。

▲圖片來源:小米香港官網

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。

音效方面, POCO M3 內建雙揚聲器,並通過 Hi-Res Audio 高解析度音效認證。另外, POCO M3 仍保留 3.5mm 耳機插孔,對有線耳機需求的用戶來說更為方便:

▲圖片來源:小米香港官網

POCO M3 採用獨立三卡槽設計,可同時支持 4G+4G 雙卡雙待和 microSD 記憶卡擴充容量(最高可擴充至 512GB):

▲圖片來源:小米香港官網

POCO M3 採用側邊指紋辨識,結合於電源鍵更方便於快速解鎖:

▲圖片來源:小米香港官網

即便 POCO M3 內建 6000mAh 大電量電池,仍將重量控制在 200 克以內,機身重量為 198 克:

▲圖片來源:小米香港官網

延伸閱讀:
小米有品推出 Lydsto 手持吸塵打氣機,眾籌價約 860 元

小米11 Lite 通過 FCC 認證,相關規格提前曝光!

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

啪啪,打臉了!領導說:try-catch必須放在循環體外!_租車

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

哈嘍,親愛的小夥伴們,技術學磊哥,進步沒得說!歡迎來到新一期的性能解讀系列,我是磊哥。

今天給大家帶來的是關於 try-catch 應該放在循環體外,還是放在循環體內的文章,我們將從性能業務場景分析這兩個方面來回答此問題。

很多人對 try-catch 有一定的誤解,比如我們經常會把它(try-catch)和“低性能”直接畫上等號,但對 try-catch 的本質(是什麼)卻缺少着最基礎的了解,因此我們也會在本篇中對 try-catch 的本質進行相關的探索

小貼士:我會盡量用代碼和評測結果來證明問題,但由於本身認知的局限,如有不當之處,請讀者朋友們在評論區指出。

性能評測

話不多說,我們直接來開始今天的測試,本文我們依舊使用 Oracle 官方提供的 JMH(Java Microbenchmark Harness,JAVA 微基準測試套件)來進行測試。

首先在 pom.xml 文件中添加 JMH 框架,配置如下:

<!-- https://mvnrepository.com/artifact/org.openjdk.jmh/jmh-core -->
<dependency>
   <groupId>org.openjdk.jmh</groupId>
   <artifactId>jmh-core</artifactId>
   <version>{version}</version>
</dependency>

完整測試代碼如下:

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;

/**
 * try - catch 性能測試
 */
@BenchmarkMode(Mode.AverageTime) // 測試完成時間
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS) // 預熱 1 輪,每次 1s
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) // 測試 5 輪,每次 3s
@Fork(1) // fork 1 個線程
@State(Scope.Benchmark)
@Threads(100)
public class TryCatchPerformanceTest {
    private static final int forSize = 1000; // 循環次數
    public static void main(String[] args) throws RunnerException {
        // 啟動基準測試
        Options opt = new OptionsBuilder()
                .include(TryCatchPerformanceTest.class.getSimpleName()) // 要導入的測試類
                .build();
        new Runner(opt).run(); // 執行測試
    }

    @Benchmark
    public int innerForeach() {
        int count = 0;
        for (int i = 0; i < forSize; i++) {
            try {
                if (i == forSize) {
                    throw new Exception("new Exception");
                }
                count++;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return count;
    }

    @Benchmark
    public int outerForeach() {
        int count = 0;
        try {
            for (int i = 0; i < forSize; i++) {
                if (i == forSize) {
                    throw new Exception("new Exception");
                }
                count++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return count;
    }
}

以上代碼的測試結果為:

從以上結果可以看出,程序在循環 1000 次的情況下,單次平均執行時間為:

  • 循環內包含 try-catch 的平均執行時間是 635 納秒 ±75 納秒,也就是 635 納秒上下誤差是 75 納秒;
  • 循環外包含 try-catch 的平均執行時間是 630 納秒,上下誤差 38 納秒。

也就是說,在沒有發生異常的情況下,除去誤差值,我們得到的結論是:try-catch 無論是在 for 循環內還是 for 循環外,它們的性能相同,幾乎沒有任何差別

try-catch的本質

要理解 try-catch 的性能問題,必須從它的字節碼開始分析,只有這樣我能才能知道 try-catch 的本質到底是什麼,以及它是如何執行的。

此時我們寫一個最簡單的 try-catch 代碼:

public class AppTest {
    public static void main(String[] args) {
        try {
            int count = 0;
            throw new Exception("new Exception");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

然後使用 javac 生成字節碼之後,再使用 javap -c AppTest 的命令來查看字節碼文件:

 javap -c AppTest 
警告: 二進制文件AppTest包含com.example.AppTest
Compiled from "AppTest.java"
public class com.example.AppTest {
  public com.example.AppTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: new           #2                  // class java/lang/Exception
       5: dup
       6: ldc           #3                  // String new Exception
       8: invokespecial #4                  // Method java/lang/Exception."<init>":(Ljava/lang/String;)V
      11: athrow
      12: astore_1
      13: aload_1
      14: invokevirtual #5                  // Method java/lang/Exception.printStackTrace:()V
      17: return
    Exception table:
       from    to  target type
           0    12    12   Class java/lang/Exception
}

從以上字節碼中可以看到有一個異常表:

Exception table:
       from    to  target type
          0    12    12   Class java/lang/Exception

參數說明:

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污

  • from:表示 try-catch 的開始地址;
  • to:表示 try-catch 的結束地址;
  • target:表示異常的處理起始位;
  • type:表示異常類名稱。

從字節碼指令可以看出,當代碼運行時出錯時,會先判斷出錯數據是否在 fromto 的範圍內,如果是則從 target 標誌位往下執行,如果沒有出錯,直接 gotoreturn。也就是說,如果代碼不出錯的話,性能幾乎是不受影響的,和正常的代碼的執行邏輯是一樣的。

業務情況分析

雖然 try-catch 在循環體內還是循環體外的性能是類似的,但是它們所代碼的業務含義卻完全不同,例如以下代碼:

public class AppTest {
    public static void main(String[] args) {
        System.out.println("循環內的執行結果:" + innerForeach());
        System.out.println("循環外的執行結果:" + outerForeach());
    }
    
    // 方法一
    public static int innerForeach() {
        int count = 0;
        for (int i = 0; i < 6; i++) {
            try {
                if (i == 3) {
                    throw new Exception("new Exception");
                }
                count++;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return count;
    }

    // 方法二
    public static int outerForeach() {
        int count = 0;
        try {
            for (int i = 0; i < 6; i++) {
                if (i == 3) {
                    throw new Exception("new Exception");
                }
                count++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return count;
    }
}

以上程序的執行結果為:

java.lang.Exception: new Exception

at com.example.AppTest.innerForeach(AppTest.java:15)

at com.example.AppTest.main(AppTest.java:5)

java.lang.Exception: new Exception

at com.example.AppTest.outerForeach(AppTest.java:31)

at com.example.AppTest.main(AppTest.java:6)

循環內的執行結果:5

循環外的執行結果:3

可以看出在循環體內的 try-catch 在發生異常之後,可以繼續執行循環;而循環外的 try-catch 在發生異常之後會終止循環。

因此我們在決定 try-catch 究竟是應該放在循環內還是循環外,不取決於性能(因為性能幾乎相同),而是應該取決於具體的業務場景

例如我們需要處理一批數據,而無論這組數據中有哪一個數據有問題,都不能影響其他組的正常執行,此時我們可以把 try-catch 放置在循環體內;而當我們需要計算一組數據的合計值時,只要有一組數據有誤,我們就需要終止執行,並拋出異常,此時我們需要將 try-catch 放置在循環體外來執行。

總結

本文我們測試了 try-catch 放在循環體內和循環體外的性能,發現二者在循環很多次的情況下性能幾乎是一致的。然後我們通過字節碼分析,發現只有當發生異常時,才會對比異常表進行異常處理,而正常情況下則可以忽略 try-catch 的執行。但在循環體內還是循環體外使用 try-catch,對於程序的執行結果來說是完全不同的,因此我們應該從實際的業務出發,來決定到 try-catch 應該存放的位置,而非性能考慮

關注公眾號「Java中文社群」回復“乾貨”,獲取 50 篇原創乾貨 Top 榜

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。

助美成天然氣出口大國的崔石比克能源 聲請破產保護_租車

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。

摘錄自2020年6月29日聯合報報導

紐約時報報導,美國頁岩油業先行者崔石比克能源公司(Chesapeake Energy)周日(28日)聲請破產保護,十年來的低油價使其再也無法承擔堆積如山的債務。

崔石比克在共同創辦人和前任執行長Aubrey McClendon的領導下,讓美國由天然氣進口國轉變為出口大國。但Aubrey McClendon在2013年被迫離職之前過度擴張公司,累積下超過2000萬美元的債務。

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

該公司今年第一季度虧損83億美元,截至3月底止,僅剩8200萬美元現金。去年底的債務總額為95億美元,8月即將有1.92億美元債券到期。崔石比克發表聲明說,該公司已通過循環信貸機制取得了9.25億美元融資,取消約70億美元的債務。另獲得了增資6億美元的承諾。

能源議題
能源轉型
國際新聞
美國
破產
天然氣

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污

Razer 展示 Project Hazel 概念,號稱全球最智慧口罩_租車

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

今天(1/13) Razer 在官網上發表了一款號稱全球最智慧的口罩「Project Hazel 」,雖然只是概念品,但對於疫情期間又不甘跟別人一樣的人們來說的確具有相當大的吸引力,對筆者這個悶騷個性的人來說更是有種躍躍欲試的感覺,你以為它只是口罩?不,它還會發光跟濾淨空氣呢!

Razer 展示 Project Hazel 概念,號稱全球最智慧口罩

外型上,Project Hazel 效法 N95 口罩,具備光滑、防水、耐磨的再生塑膠透明外殼搭配矽膠護照,與臉部緊密貼合,可重複使用,當你與他人對話時,還能讓對方看到你的嘴型與完整面部表情。在 Project Hazel 上還內建有麥克風與喇叭,可以確保對話時的聲音能夠讓對方清晰聽見;在口罩上還配有光感應器,當處於較暗環境中時,內部的燈光會自動點亮,以便讓別人看見你的臉孔,當然這個色光也能透過 Razer Chroma RGB 軟體來自定顏色。

在口罩外的兩側配置了兩個圓形區塊,它們主要的功能是用來使空氣流通,利用主動式圓形通風裝置,將呼出的二氧化碳排出,並且對吸入的空氣加以過濾,根據 Razer 說法,內部可替換的過濾裝置預計可過濾至少 95% 的微粒,且具備有高度細菌過濾效果,因為具防水性,自然也能防止液體、口水噴濺。在圓形區塊上還配有 RGB 色光,光是這點就足夠讓你與眾不同了。

隨著口罩本體,還附有一個內部配置紫外光燈的充電收納盒,當你將口罩放入其中時,可自動消滅附著在口罩上的細菌與病毒。這款概念產品目前還沒有上市相關資訊,對於必要的送審與核准當然也還沒有進行,但如果順利量產的話,似乎很值得入手啊!

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。

數據分析 | 數據可視化圖表,BI工具構建邏輯_潭子電動車

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

本文源碼:GitHub·點這裏 || GitEE·點這裏

一、數據可視化

1、基礎概念

數據可視化,是關於數據視覺表現形式的科學技術研究。其中,這種數據的視覺表現形式被定義為,一種以某種概要形式抽取出來的信息,包括相應信息單位的各種屬性和變量。

如果說的實際貼切的話:系統開發中常見的數據報表統計,將數據用圖表或表格的形式呈現出來,幫助運營或者決策人員了解這些數據的規律或者價值,就是簡單的可視化應用。

從開發角度來看,把系統中的核心數據,用一定的手段進行統計,在藉助一些精美的圖表樣式,展示出來,或者把一系列圖表組裝成一個數據大屏,格調十足。

但是從運營人員的角度看,更多的是藉助可視化數據分析業務場景,得到有價值的參考數據,為後續的決策或者開展活動提供指導。所以隨着業務線的不斷髮展,對數據分析的要求越來越高,也就誕生現在比較常見的BI分析工具和BI分析師。

2、數據可視化價值

  • 準確高效直觀的傳遞傳遞數據中的規律和信息;
  • 實時監控系統各項數據指標,實現數據的自解釋;
  • 基於可視化洞察數據規律,指定精準的運營策略;

3、基礎構建原則

簡單的步驟如下:基於業務需求,完成可視化數據處理(收集,規則,定時任務等)。藉助常用的圖表進行組合展示,但是也有一些注意事項如下:

  • 可視化的數據要關聯核心的有業務價值的數據;
  • 圖表的展現注意簡單,明了,圖表的本質就是讓數據更直觀;
  • 不要為了追求系統花哨,可以大批量添加圖表;

二、常用圖表設計

1、常見基礎圖表

柱狀圖

特點:一般展現分組數據,直觀展示各組數據差異,例如常見以每周,每月,或者不同客戶端劃分為軸的數據。

折線圖

特點:重點展現數據的變化趨勢,常見以時間為軸,展示時間下的數據趨勢。

餅狀圖

特點:不注重數據明細,強調數據中各項佔總體的百分比,或者分佈情況,注重模塊模塊之間的對比。

漏斗圖

特點:強調數據之間的轉化關係和遞進規律,經典常見就是用戶瀏覽量,點擊量,到訂單支付數量。

組合圖

特點:多種基礎圖表組合,某些特殊業務數據,需要結合兩種圖或者更多種圖表,強調裝載該業務報表的關鍵組合信息。

2、數據大屏

顧名思義,放在大屏幕的報表,一般有多種豐富的業務數據,自然需要多種報表展現形式,比較有立體感和視覺上的衝擊力。

絮叨一句:數據大屏在更多時候所追求的是讓人印象深刻,這才是最關鍵的,懂的都懂。

三、常用統計方式

1、SQL分析語句

在報表類業務中,經常使用SQL分析語句,常用的幾個方法:

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。

  • count:數據求和,求總數,例如多少用戶;
  • sum:求和函數,例如總銷量,總成本等;
  • group-by:分組統計,分組結果就是軸標識;
  • average:平均值計算,例如平均每天銷量;

業務類的報表雖然複雜,但是報表相關的數據接口相對而言簡單,基於一些基礎的統計SQL,生成報表數據。

2、基礎案例

產品和緯度表

CREATE TABLE `vc_product_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
  `product_sort` varchar(20) DEFAULT '' COMMENT '產品分類',
  `product_name` varchar(50) DEFAULT '' COMMENT '產品名稱',
  `inventory` int(11) DEFAULT '0' COMMENT '庫存剩餘',
  `price` decimal(10,2) DEFAULT '0.00' COMMENT '單價',
  `total_sales` int(11) DEFAULT '0' COMMENT '銷售總量',
  `sales_amount` decimal(10,2) DEFAULT '0.00' COMMENT '銷售總額',
  `create_time` datetime DEFAULT NULL COMMENT '創建時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='產品信息表';

CREATE TABLE `vc_product_detail` (
	`id` INT (11) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
	`product_id` INT (11) NOT NULL COMMENT '產品ID',
	`place_origin` VARCHAR (50) DEFAULT '' COMMENT '產品產地',
	`weight` DECIMAL (10, 2) DEFAULT '0.00' COMMENT '重量',
	`color` VARCHAR (50) DEFAULT '' COMMENT '顏色',
	`high_praise` INT (11) DEFAULT '0' COMMENT '好評數量',
	`low_praise` INT (11) DEFAULT '0' COMMENT '差評數量',
	`create_time` datetime DEFAULT NULL COMMENT '創建時間',
	PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '產品維度表';

基礎查詢語句

<mapper namespace="com.visual.chart.mapper.ProductInfoMapper">

    <!-- 商品種類 -->
    <select id="countNum" resultType="java.lang.Integer">
        SELECT COUNT(product_name) FROM vc_product_info
    </select>

    <!-- 銷售總額度 -->
    <select id="sumAll" resultType="java.lang.Double">
        SELECT SUM(sales_amount) FROM vc_product_info
    </select>

    <!-- 分組求和 -->
    <select id="groupSum" resultType="java.util.Map">
        SELECT product_sort,SUM(sales_amount) FROM vc_product_info GROUP BY product_sort
    </select>

    <!-- 平均單價 -->
    <select id="average" resultType="java.lang.Double">
        SELECT AVG(price) FROM vc_product_info
    </select>
</mapper>

四、自定義工具

1、數據集

數據集概念

DataSet是一個數據的集合,通常以列表形式出現。每一列代表一個特定變量。每一行都對應於某一成員的數據集的問題。在統計分析的業務中,通常稱為大寬表,方便業務分析。

數據集生成

視圖方式

基於視圖的方式,生成一個單表的數據集,方便簡化操作。該方式不提倡,視圖在大部分公司里是禁止使用的,這裏只是單純演示。

基於上述產品信息表和維度表,通過視圖手段生成數據集,單純為了簡化業務分析的操作難度,因為多表聯合簡化成感覺上的單表。

CREATE OR REPLACE 
VIEW data_set_view AS SELECT
	t1.*, t2.place_origin,
	t2.weight,
	t2.color,
	t2.high_praise,
	t2.low_praise
FROM vc_product_info t1
LEFT JOIN vc_product_detail t2 ON t1.id = t2.product_id

任務方式

通過定時任務,獲取要分析的數據結構,不斷注入到分析表中,這是業務開發中最常見的報表數據集生成方式,有的甚至通過定時任務直接統計出報表需要的數據,不適應於大數據場景。

離線或實時計算

通過大數據分析手段,離線計算或者實時計算,獲取業務報表數據,注入OLAP實時分析計算庫,使用大數據分析場景。

2、定製化BI工具

BI工具可以快速對業務數據進行有效的整合,快速準確的提供報表並提出決策依據,幫助企業做出明智的業務經營決策。商業智能的概念最早在1996年提出。當時將商業智能定義為一類由數據倉庫(或數據集市)、查詢報表、數據分析、數據挖掘、數據備份和恢復等部分組成的、以幫助企業決策為目的技術及其應用。

基本搭建思路:

  • 管理數據源,建立數據表之間關係,維護特定數據集;
  • 創建可拖拉拽的報告面板,用來承載單個圖表組合;
  • 封裝不同的圖表的處理邏輯,規則展示,關聯數據集字段;
  • 封裝圖表樣式,例如大小、顏色、背景、交互等可配置;
  • 圖表關聯分析數據集,報告面板組合多個圖表生成報告;

實際的開發過程是非常複雜的,管理各個業務線的數據源,聯合分析,適配各種圖表規範和樣式,都是一個十分漫長的過程。

3、基礎案例

接口入參

承接上述業務場景,這裏參數都需要動態傳入,例如操作的:數據集、圖表、參數歸屬軸、或者業務產品參數等。

@RestController
public class DefineController {

    @Resource
    private DataSetService dataSetService ;
    /**
     * 自定義可視化報告入參
     */
    @GetMapping("/getDefChart")
    public Map<Integer, List<ChartParam>> getDefChart (){
        List<ChartParam> chartParamList = new ArrayList<>() ;
        chartParamList.add(new ChartParam("X",1,"data_set_view","product_sort")) ;
        chartParamList.add(new ChartParam("X",1,"data_set_view","product_name")) ;
        chartParamList.add(new ChartParam("Y",2,"data_set_view","high_praise")) ;
        chartParamList.add(new ChartParam("Y",2,"data_set_view","low_praise")) ;
        chartParamList.add(new ChartParam("Z",3,"data_set_view","inventory",1)) ;
        chartParamList.add(new ChartParam("Z",3,"data_set_view","total_sales",1)) ;
        return dataSetService.analyData(chartParamList);
    }
}

參數解析

根據各種動態參數,解析查詢條件,獲取查詢結果。

@Service
public class DataSetServiceImpl implements DataSetService {

    @Resource
    private DataSetMapper dataSetMapper ;
    // 分析任務劃分
    @Override
    public Map<Integer, List<ChartParam>> analyData(List<ChartParam> chartParamList) {
        Map<Integer, List<ChartParam>> dataMap = chartParamList.stream()
                                                 .collect(Collectors
                                                 .groupingBy(ChartParam::getDataType));
        for (Integer dataType:dataMap.keySet()){
            switch (dataType){
                case 1: // Count 風格數據
                    taskCount(dataMap.get(dataType));
                    break;
                case 2: // Sum 風格數據
                    taskSum(dataMap.get(dataType));
                    break;
                case 3: // Percent 風格數據
                    taskPercent(dataMap.get(dataType));
                    break;
                default:
                    break;
            }
        }
        return dataMap ;
    }
    // Count 數據執行
    private void taskCount (List<ChartParam> chartParamList){
        for (ChartParam chartParam:chartParamList){
            chartParam.setResultNum(dataSetMapper.taskCount(chartParam.getColumnName(),
                                                            chartParam.getTableName()));
        }
    }
    // Sum 數據執行
    private void taskSum (List<ChartParam> chartParamList){
        for (ChartParam chartParam:chartParamList){
            chartParam.setResultNum(dataSetMapper.taskSum(chartParam.getColumnName(),
                                                          chartParam.getTableName()));
        }
    }
    // Percent 數據執行
    private void taskPercent (List<ChartParam> chartParamList){
        for (ChartParam chartParam:chartParamList){
            chartParam.setResultNum(dataSetMapper.taskPercent(chartParam.getColumnName(),
                                                              chartParam.getTableName(),
                                                              chartParam.getProductId()));
        }
    }
}

總結一句:數據可視化工具建設是個漫長過程,不僅僅可以分析自己公司的業務,也可以作為開放BI工具產生價值。

五、源代碼地址

GitHub·地址
https://github.com/cicadasmile/data-manage-parent
GitEE·地址
https://gitee.com/cicadasmile/data-manage-parent

推薦閱讀:《架構設計系列》,蘿蔔青菜,各有所需

序號 標題
01 架構設計:單服務.集群.分佈式,基本區別和聯繫
02 架構設計:分佈式業務系統中,全局ID生成策略
03 架構設計:分佈式系統調度,Zookeeper集群化管理
04 架構設計:接口冪等性原則,防重複提交Token管理
05 架構設計:緩存管理模式,監控和內存回收策略

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污

Python編程思想(3):数字及其相關運算_包裝設計

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

Python 提供了三種數值類型:int(整型),float(浮點型)和complex(複數)。

  • int:通常被稱為整型或者整數,如200、299、10都屬於整型;
  • float:浮點數包含整數和小數部分,如3.1415926,2.71828都屬於浮點數;
  • complex:複數包含實數部分和虛數部分,形如 a+bj,其實部和虛部都是浮點類型;

需要注意的是,Python3 已經廢棄了 Python2 的 Long(長整型),在 Python3 中,int 的大小沒有限制,可以作為 Long 使用。這也是為什麼Python非常適合科學計算的原因,因為Python可以處理無限大的整數。在Python中進行數值運算,並不需要考慮溢出問題,因為Python的數值永遠不會溢出。  
1. 數值類型之間的轉換   Python 的三種數值類型可以進行相互轉換,轉換方式為:数字類型+圓括號,如下實例:

a = 456
b = 2.71828
print("int(b)=",int(b))
print("float(a)=",float(a))
print("complex(a)=",complex(a))
print("complex(a,b)=",complex(a,b))

執行結果如下圖所示:    
2. 常用的數學函數   Python 提供了豐富的數學函數以降低編程實現的難度,本問將介紹一些常用的函數。

import math
#求絕對值:abs(x)
print("abs(-200)=",abs(-200))

#向上取整:ceil(x)
print("ceil(3.1415)=",math.ceil(3.1415))

#向下取整:floor(x)
print("floor(3.678)=",math.floor(3.678))

#四舍五入:round(x)
print("round(3.678)=",round(3.678))

#乘方運算:pow(x,y),x的y次方
print("pow(3,4)=",pow(3,4))

#求平方根:sqrt(x)
print("sqrt(144)=",math.sqrt(144))

執行結果如下圖所示:

 
3. 運算符   計算機的最基本用途之一就是執行數學運算,作為一門計算機編程語言,Python 也提供了一套豐富的運算符來滿足各種運算需求。 Python 運算符主要可以分為6種:算術運算符、比較運算符、賦值運算符、邏輯運算符、位運算符和成員運算符。  
(1)算術運算符 對於算術運算,大家並不陌生,常用的加減乘除就是算術運算。不過,在編程語言里,算術運算符特殊一些,Python 中的算術運算有7種:加(+)、減(-)、乘( * )、除(/)、取模(%)、冪運算( ** )和取整預算(//)。以下通過實例演示算術運算符的用法。

#初始化測試數據
x = 30
y = 24
z = 12
#分別進行7種算術運算
z = x + y
print("x + y =", z)
z = x - y
print("x - y =", z)
z = x * y
print("x * y =", z)
z = x / y
print("x / y =", z)
z = x % y
print("x % y =", z)
z = x ** y
print("x ** y =", z)
z = x // y
print("x // y =", z)

執行結果如下圖所示:

 

  (2)比較運算符

比較無處不在,大於、小於、等於、不等於……和 C/C++、Java 等編程語言一樣,Python 也提供了6種比較運算符:>(大於),<(小於),==(等於),!=(不等於),>=(大於等於),<=(小於等於)。比較運算的結果是一個布爾值,True 或者 False,看下面的案例代碼:

# 初始化變量
x = 12
y = 7
#分別進行6種比較運算
print("x == y:", x == y)
print("x != y:", x != y)
print("x > y:", x > y)
print("x < y:", x < y)
print("x >= y:", x >= y)
print("x <= y:", x <= y)

執行結果如下圖所示:  
(3)賦值運算符 其實在前面的代碼中已經用到賦值運算,如 x = 12,就是一個最簡單的賦值運算,“=”就是最簡單的賦值運算符。將簡單的賦值運算與算術運算結合,Python 形成了更豐富的賦值運算符:+=、-=、=、/=、%=、*=、//=。看下面的案例代碼:

#初始化變量
x = 12
y = 21
#分別進行7種賦值運算
y = x
print("y = x, y =", y)
y += x
print("y += x, y =", y)
y -= x
print("y -= x, y =", y)
y *= x
print("y *= x, y =", y)
y /= x
print("y /= x, y =", y)
y **= x
print("y **= x, y =", y)
y //= x
print("y //= x, y =", y)

執行結果:

 

 

(4)邏輯運算符 所謂邏輯運算,就是:與、或、非。Python 中的3種邏輯運算符分別為:and(與),or(或),not(非),邏輯運算的結果是布爾值:True 或者 False。

  1. A and B:當A和B有一個為False時,結果就為False,只有A和B都為True時,結果才為True;
  2. A or B:只有當A和B都是False時,結果才為False,只要有一個為True,結果就為True;
  3. not A:當 A 為 True 時,返回 False,否則返回 True。

看下面的案例:

#初始化變量
a = 2
b = 3
c = 5
#分別執行3種邏輯運算
print("a>b and a<c :", a>b and a<c)
print("a<b and c :", a<b and c)
print("a>b or c :", a>b or a<c)
print("a<b or c :", a<b or c)
print("a or a<c :", a or a<c)
print("not a :", not a)
print("not a<b :", not a<b)

執行結果如下圖所示:

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

 
(5)位運算符 程序中的所有數值在計算機內存中都是以二進制的形式儲存的。位運算就是直接對整數在內存中的二進制位進行操作。Python 中有6種位運算符:

  • &:按位與,參与運算的兩個值,如果兩個相應位都為1,則該位的結果為1,否則為0;
  • |:按位或,只要對應的2個二進位有一個為1時,結果位就為1;
  • ^:按位異或,當兩對應的二進位相異時,結果為1;
  • ~:按位取反,對數據的每個二進制位取反,即把1變為0,把0變為1;
  • >>:按位右移,將>>左側的數按位向右移動>>右邊的數指定的位;
  • <<:按位左移,將<<左側的數按位向左移動<<右邊的數指定的位;

看下面的案例代碼:

a = 21
b = 6
print('a & b = ',a & b)
print('a | b = ',a | b)
print('a ^ b = ',a ^ b)
print('~a = ',~a)
print('a << 2 = ',a << 2)
print('a >> 2 = ',a >> 2)

執行結果如下圖所示:

 

 

 這裏講a=21,b=6,轉換為二進制如下:

a = 0001 0101
b = 0000 0110

a&b = 0000 0100
a|b = 0001 0111
a^b = 0001 0011
~a = 1110 1010
a<<2 = 01010100
a>>2 = 0000 0101

(6)成員運算符 除了前面介紹的5種運算符,Python 還支持成員運算符。介紹成員運算符之前,我們需要提前了解一個概念:數據結構,如字符串、列表、元組、字典。在接下來的文章中我們將詳細介紹這些基礎的數據結構。字符串、列表、字典,它們就像一個集合,其中包含若干元素,這些元素就是集合的成員;對於一個給定的元素,它有可能在一個給定的集合中,也可能不在,Python 中採用成員運算符來判斷元素是否屬於成員,成員運算的結果為布爾值,True 或者 False。 看下面的代碼:

#初始化字符串和列表
temp1 = "abcdefg"
temp2 = [4,2,3,5,8,9]
a = "cdf"
b = 5
c = "cde"
print("a in temp1?", a in temp1)
print("b in temp2?", b in temp2)
print("c in temp1?", c in temp1)

  執行結果如下圖所示:    

 

 

 

 

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

支援 M1 Mac 的 Microsoft Edge Beta 預覽版來囉_網頁設計公司

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

換了 Apple M1 Mac 後還暫時找不到可以代替 Chrome 的瀏覽器?還是你還不知道為什麼大家最近都考慮把 Chrome 斷個乾淨(傳送門低家啦)?總而言之,隨著 Google 將對三方 Chromium 瀏覽器祭出的私有 Chrome API 限制政策後,眼看之後比較能接近 Chrome 的瀏覽器就剩下微軟的 Edge 了。但剛買 M1 MacBook Air / M1 MacBook Pro / M1 Mac mini 的你,卻不太想安裝 Canary / Dev 版本的 Edge?現在,更接近正式版的預覽版本也許真的可以成為屬於你的及時雨。繼續閱讀支援 M1 Mac 的 Microsoft Edge Beta 預覽版來囉報導內文。

▲圖片來源:Microsoft

M1 Mac 版 Microsoft Edge Beta 預覽版來囉,不趁 Keystone 換個瀏覽器?

▲圖片來源:Microsoft

眼看 Google 還沒打算將「壞壞」的 Keystone 從 Chrome 中排除,早已經習慣使用以 Chromium 為基礎所打造的瀏覽器的你,更因為剛換到 M1 Mac 而苦尋不找可以長久使用下去的替代瀏覽器(如果不是 Keystone 相信大家也不會想要一直換)。

雖說直接切換到了原本工作專用的 Firefox 的小編自己是用的很開心啦,但顯然許多人應該都把希望放在了先前已經宣佈,將會推出 Apple Silicon 版本 Edge 瀏覽器的微軟身上。

▲圖片來源:Microsoft

現在雖說正式版本還沒推出,但也真的只差一步之遙的 Microsoft Edge Beta 預覽版,倒是已經開放在 Insider 頻道提供下載了(點我前往頁面)。雖然名為 Beta,但它相對每日 / 每週更新的 Canary / Dev 版本,是以 2 個月為更新週期,雖說穩定度仍然有疑慮,但相對來講已經是最接近正式版本的了。

所以如果你已經等不及想跳槽或想試試微軟的 Edge 瀏覽器,在 M1 Mac 上是否有更強悍的表現的話(應該會吧,畢竟少了 Keystone ~ 嗯… 好地獄的梗),那可以考慮安裝 Beta 版本試試囉。

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

本篇圖片 / 引用來源

延伸閱讀:

好用的 Chrome 為何炎上被抵制?神人直指「它壞壞」還做了個懶人包網頁

借鑑食品、飲料等產業 Tesla 電池生產影片大公開,看了覺得莫名療癒…

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單

一文帶你了解js數據儲存及深複製(深拷貝)與淺複製(淺拷貝)_租車

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

背景

在日常開發中,偶爾會遇到需要複製對象的情況,需要進行對象的複製。

由於現在流行標題黨,所以,一文帶你了解js數據儲存及深複製(深拷貝)與淺複製(淺拷貝)

理解

首先就需要理解 js 中的數據類型了
js 數據類型包含

  1. 基礎類型:StringNumbernullundefinedBoolean以及ES6引入的Symboles10中的BigInt
  2. 引用類型:Object

由於 js 對變量的儲存是棧內存堆內存完成的。

  • 基礎類型將數據保存在棧內存
  • 引用類型將數據保存在堆內存

由於 js 在數據讀取和寫入的時候,對基礎類型是直接讀寫棧內存中的數據,引用類型是將一個內存地址保存在棧內存中,讀寫都是修改棧內存中指向堆內存的地址

以如下代碼為例

let obj = {
  a:1,
  arr:[1,3,5,7,9],
  b:2,
  c:{
    num:100
  }
}
let num = 10

在內存中的表現為

我們聲明個obj1

let obj1 = obj;
console.log(obj1 == obj);//true

因為這個賦值,把內存變成了這樣

然後,內存中只是給js棧內存新增了一個指向堆內存的地址而已,這種就叫做淺複製。因為如圖可以看到,如果我們修改obj.a的話,實際修改的是堆內存0x88888888中的變量a,由於obj1也指向這個地址,所以obj1.a也被修改了

深複製是指,不單單複製引用地址,連堆內存都複製一遍,使objobj1不指向同一個地址。

代碼

分開來看深複製淺複製

淺複製

由上述圖可知,淺複製只是複製了堆內存的引用地址,通常在業務需求中出現的淺複製是指複製引用對象的第一層,也就是,基本類型複製新值,引用類型複製引用地址

淺複製可以使用的方案有循環賦值擴展運算符object.assign(),

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。

let obj = {
  a:1,
  arr:[1,3,5,7,9],
  b:2,
  c:{
    num:100
  }
}
function clone1(obj){ // 使用循環賦值
  let b = {};
  for(let key in obj){
    b[key] = obj[key]
  }
  return b
}
function clone2(obj){ // 使用擴展運算符
  let b = {
    ...obj
  };
  return b
}
function clone3(obj){ // 使用object.assign()
  let b = {};
  Object.assign(b,obj)
  return b
}
let obj1 = clone1(obj);
let obj2 = clone2(obj);
let obj3 = clone3(obj);

console.log(obj1 === obj); //false 代表複製成功了
console.log(obj2 === obj); //false 代表複製成功了
console.log(obj3 === obj); //false 代表複製成功了
console.log('obj0.c.num修改前',obj.c.num); //100
console.log('obj1.c.num修改前',obj1.c.num); //100
console.log('obj2.c.num修改前',obj2.c.num); //100
console.log('obj3.c.num修改前',obj3.c.num); //100
obj0.c.num = 555;
console.log('obj0.c.num修改后',obj.c.num); //555
console.log('obj1.c.num修改后',obj1.c.num); //555
console.log('obj2.c.num修改后',obj2.c.num); //555
console.log('obj3.c.num修改后',obj3.c.num); //555

由於是淺複製,所以引用類型只是複製了內存地址,修改其中一個對象的子屬性后,引用這個地址的值都會被修改。

淺克隆圖解如下

深複製

由於淺複製只是複製第一層,為了解決引用類型的複製,需要使用深複製來完成對象的複製,基本類型複製新值,引用類型開闢新的堆內存

深複製可以使用的方案有JSON.parse(JSON.stringify(obj))循環賦值

JSON.parse(JSON.stringify(obj))

let obj = {
  a:1,
  arr:[1,3,5,7,9],
  c:{
    num:100
  },
  fn:function(){
     console.log(1)
  },
  date:new Date(),
  reg:/\.*/g
}
function clone1(obj){ // 使用JSON.parse(JSON.stringify(obj))
  return JSON.parse(JSON.stringify(obj))
}
let obj1 = clone1(obj);
console.log(obj === obj1); //false 代表複製成功了
obj.c.num = 555;

console.log(obj.c.num,obj1.c.num) // 555,100

看起來是複製成功了!!~地址也變了,修改obj,obj1的引用地址不會跟着變化。

但是我們來console一下obj以及obj1

console.log(obj)
console.log(obj1)

似乎發現了離奇的事情,只有obj.a以及obj.c正確的複製了,日期類型方法正則表達式均沒有複製成功,發生了一些奇怪的事情

循環賦值 deepClone

那麼為了解決這種事情,就需要寫一個deepClone方法來完成深複製了,參考了許多開源庫的寫法,將所有的複製項單獨拆出,方便未來對特殊類型進行擴展,也防止不同功能間的變量互相干擾

 //既然是深複製,一定要傳入一個object,再return 一個新的 Object
function deepClone(obj){
    let newObj;
    if(obj instanceof Array){ // 數組的話,要new一個數組
      newObj = []
    }else if(obj instanceof Object){  // 對象的話,要new一個對象
      newObj = {}
    }
    if(obj === null) {
      return cloneNull(obj)
    }
    if(typeof obj=='function'){
        return cloneFunction(obj)
    }
    if(typeof obj!='object') {
        return cloneOther(obj)
    }
    if(obj instanceof RegExp) {
        return cloneRegExp(obj)
    }
    if(obj instanceof Date){
        return cloneDate(obj)
    }
    if(obj instanceof Array){
        for(let index in obj){
            newObj[index] = deepClone(obj[index]); // 對數組子項進行複製
        }
    }
    if(obj instanceof Object){
        for(let key in obj){
            newObj[key] = deepClone(obj[key]); // 對對象子項進行複製
        }
    }
    return newObj;
}
function cloneNull(obj){ // 複製NULL
  return obj
}
function cloneFunction(obj){ // 複製方法,
  // 複製一個新方法,將原方法轉成字符串,並new一個新的function
  return new Function('return '+obj.toString())()
}
function cloneOther(obj){ // 複製非對象的數據
  return obj
}
function cloneRegExp(obj){ // 複製正則對象
  return new RegExp(obj)
}
function cloneDate(obj){ // 複製日期對象
  return new Date(obj)
}

這樣一個基本上滿足功能的深複製就完成了。先測試一下

let obj = {
  a:1,
  arr:[1,3,5,7,9],
  c:{
    num:100
  },
  fn:function(){
     console.log(1)
  },
  date:new Date(),
  reg:/\.*/g
}

let obj1 = deepClone(obj);
console.log(obj.c === obj1.c); // false  代表複製成功
console.log(obj.fn === obj1.fn);// false  代表複製成功 
console.log(obj.date === obj1.date);// false  代表複製成功
console.log(obj.reg === obj1.reg);// false  代表複製成功

console一下

console.log(obj)
console.log(obj1)

這樣,就完成了deepClone深複製方法

經過深複製后,圖解如下

優化 deepClone

上述代碼還有優化空間,參考了lodash庫,在進行 new 對象時,可以使用 constructor構造函數 來進行創建新的實例,這樣

  1. 可以不用判斷遞歸中,是數組還是對象
  2. 如果深複製的某一項是某個原型的實例,深複製完成后,依然是該原型的實例
function deepClone(obj){
    let newObj = new obj.constructor;
    if(obj === null) {
      return cloneNull(obj)
    }
    if(typeof obj=='function'){
        return cloneFunction(obj)
    }
    if(typeof obj!='object') {
        return cloneOther(obj)
    }
    if(obj instanceof RegExp) {
        return cloneRegExp(obj)
    }
    if(obj instanceof Date){
        return cloneDate(obj)
    }
    if(obj instanceof Array){
        for(let index in obj){
            newObj[index] = deepClone(obj[index]); // 對數組子項進行複製
        }
    }
    if(obj instanceof Object){
        for(let key in obj){
            newObj[key] = deepClone(obj[key]); // 對對象子項進行複製
        }
    }
    return newObj;
}
function cloneNull(obj){ // 複製NULL
  return obj
}
function cloneFunction(obj){ // 複製方法,
  // 複製一個新方法,將原方法轉成字符串,並new一個新的function
  return new Function('return '+obj.toString())()
}
function cloneOther(obj){ // 複製非對象的數據
  return obj
}
function cloneRegExp(obj){ // 複製正則對象
  return new RegExp(obj)
}
function cloneDate(obj){ // 複製日期對象
  return new Date(obj)
}

最終版本 deepClone

然後可以有一個合併版本的,比較節省代碼,將下方區分開的複製方法,合併到deepClone中,可以極大地減少代碼體積

function deepClone(obj){ //
    let newObj = new obj.constructor;
    if(obj === null) return obj
    if(typeof obj=='function') return new Function('return '+obj.toString())()
    if(typeof obj!='object') return obj
    if(obj instanceof RegExp) return new RegExp(obj)
    if(obj instanceof Date) return new Date(obj)
    // 運行到這裏,基本上只存在數組和對象兩種類型了
    for(let index in obj){
        newObj[index] = deepClone(obj[index]); // 對子項進行遞歸複製
    }
    return newObj;
}

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污