標籤: 如何寫文案

  • 稀有越南老鼠鹿 近30年首度現蹤

    摘錄自2019年11月12日中央通訊社綜合報導

    一種外觀似鹿、大小相當於兔子或貓的小型哺乳類動物銀背鼷鹿(越南老鼠鹿),在失去蹤跡近30年後,近日首度在越南被發現。專家多年來認為此物種已瀕臨絕種。

    根據今天發布在「自然生態學與進化」(Nature Ecology and Evolution)期刊的研究報告,紀錄顯示,越南老鼠鹿(Silver-backed Chevrotain,或Mouse deer)最後一次現蹤是在1990年。由於自1990年起即未有發現越南老鼠鹿的紀錄,專家推測此物種已因人類過度獵捕而瀕臨絕種。

    由於人口成長和經濟開發對東南亞的樹林構成巨大生存壓力,生物學家堤爾克指出,保育工作必須搶占先機。根據聯合國「政府間生物多樣性與生態系服務科學政策平台」(IPBES)5月發布的報告,人類活動對地球的衝擊,導致高達100萬個物種瀕臨絕種。

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

    【其他文章推薦】

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

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※別再煩惱如何寫文案,掌握八大原則!

  • 北京掀新能源車熱:指標申請首破三千 純電動車也需搖號

    受4月2日北京宣佈純電動小客車不尾號限行()的利好政策推動,據4月9日北京小客車指標調控管理辦公室公佈的資料顯示,本期搖號個人新能源車指標的申請者首次突破三千,達3874人,而此前申請指標的人數徘徊在2000多人左右。根據今年的指標配置方案,本期分配給個人的新能車指標為3333個,這意味著從這一期開始,在北京購買純電動車也要搖號分配了。   在北京剛剛結束的新能源汽車工作會議上,北京相關新能源小客車採取備案制的方案已經通過,知情人士稱,未來進口純電動汽車也有望通過備案進入免購置稅目錄,這無疑將大大增加北京純電動汽車的供應類型。   而針對充電樁安裝困難問題,北京市科委新能源與新材料處處長許心超透露,現在北京正著手做三件事:一是和百度合作,標識所有充電樁地圖並上線;二是印製北京充電樁地圖,發放給消費者和計程車司機;三是辦充電體驗周活動,聯合所有在京車企,做充電實際體驗。   北京市環保局機動車排放管理處處長李昆生在4月7日透露,未來北京將嚴格控制機動車總量,每年新增小客車指標由24萬輛削減到15萬輛,力爭在2017年底前,全市機動車保有量控制在600萬輛以內,而新能源和清潔能源汽車的應用規模將達到20萬輛。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

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

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

    ※別再煩惱如何寫文案,掌握八大原則!

  • 為取得專利,小米持股 Ninebot 收購電動代步車始祖 Segway

    為取得專利,小米持股 Ninebot 收購電動代步車始祖 Segway

      小米投資的電動代步車廠商 Ninebot 今天宣布與小米、順為資本、紅杉資本聯合出資收購電動代步車始祖 Segway,交易目前已全數完成。身為 Ninebot 的股東,這項收購除了意味著小米持續拓展海外市場外,對小米來說最大的收益,便是可取得 Segway 手中大量的專利。   總部位於美國的 Segway 成立於 2001 年,產品主要為雙輪的電動代步車,而 Ninebot 則是中國電動代步車品牌。Segway 在全球每年約只有 1 萬台左右的銷量,對增加 Ninebot 銷售量並沒有太大的直接幫助,據知情人士透露,先前 Segway 曾與包括法拉利、香奈兒等國際知名品牌合作,Ninebot 買下 Segway 主要是衝著其在海外的知名度,更重要的是可取得 Segway 手中握有的專利。   有趣的是,Segway 創辦人 Dean Kamen 曾在 2014 年控告 Ninebot 及其他中國廠商侵犯智慧財產權,美國國際貿易委員會於 11 月受理調查,而今調查結果尚未出爐,Segway 卻先被 Ninebot 收購,成為旗下全資子公司。   此外,Ninebot 執行長高祿峰同時也對外宣布已完成 8,000 萬美元的 A 輪融資,由小米、紅杉資本、順為資本共同出資,並表示未來將開發應用電動代步車、移動互聯網及人車互動技術的產品。     本文全文授權轉載自《科技新報》─〈〉

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※別再煩惱如何寫文案,掌握八大原則!

  • 聊聊算法–堆的構建和調整

    聊聊算法–堆的構建和調整

    先提個問題,完全二叉樹/滿二叉樹,區別?前者是指每一層都是緊湊靠左排列,最後一層可能未排滿,後者是一種特殊的完全二叉樹,

    每層都是滿的,即節點總數和深度滿足N=(2^n) -1。堆Heap,一堆蘋果,為了賣相好,越好看的越往上放,就是大頂堆;為了蘋果堆

    的穩定,質量越小越往上放,就是小頂堆;堆首先是完全二叉樹,但只確保父節點和子節點大小邏輯,不關心左右子節點的大小關係,

    通常是一個可以被看做一棵樹的數組對象,是個很常見的結構,比如BST對象,都與堆有關係,今天就說下這個重要的數據結構和應用。

     

    作者原創文章,謝絕一切轉載,違者必究!

    本文只發表在”公眾號”和”博客園”,其他均屬複製粘貼!如果覺得排版不清晰,請查看公眾號文章。 

     

    準備:

    Idea2019.03/Gradle6.0.1/Maven3.6.3/JDK11.0.4

    難度: 新手–戰士–老兵–大師

    目標:

    1.堆的構建和調整算法

    1 優先級隊列

    為理解堆的原理,先看優先級隊列,它是一種數據結構,插入或者刪除元素的時候,元素會自動排序,(優先級不是狹義的數值大小,

    但為了通俗理解,這裏以字母序為例),通常使用數組存儲,我們可以按照下圖進行轉換,序號 0 不用:

    優先級隊列的實現(Java版):

    public class PriorityQueue<Key extends Character> {
        /** 存儲元素的數組 */
        private Key[] keys;
        private int N = 0;
    
        public PriorityQueue(int capacity){
            // 下標0不用,多分配一個單位
            keys = (Key[]) new Character[capacity + 1];
        }
    
        public Key max(){
            return keys[1];
        }
    
        public void insert(Key e){
            N ++;
            keys[N] = e;
            swim(N);
        }
        public Key delMax(){
            Key max = keys[1];
            swap(1,N);
            keys[N] = null;
            N --;
            // 讓第一個元素下沉到合適的位置
            sink(1);
            return max;
        }
        /** 上浮第k個元素*/
        private void swim(int k){
            // 比父節點小,即進行交換,直到根
            while (k > 1 && less(parent(k),k)){
                swap(k,parent(k));
                k = parent(k);
            }
        }
        /** 下沉第 k 個元素*/
        private void sink(int k){
            while(k < N){
                int small = left(k);
                if (right(k) < N && less(right(k),left(k))){
                    small = right(k);
                }
                if (less(k,small)){
                    swap(k,small);
                    k = small;
                }
            }
        }
        private void swap(int i,int j){
            Key temp = keys[i];
            keys[i] = keys[j];
            keys[j] = temp;
        }
        /** 元素i和j大小比較*/
        private boolean less(int i,int j){
    //   'a' - 'b' = -1 ;
            return keys[i].compareTo(keys[j]) > 0;
        }
        /** 元素i的父節點*/
        private int parent(int i){
            return i/2;
        }
        /** 元素i的左子節點*/
        private int left(int i){
            return i * 2;
        }
        /** 元素i的右子節點*/
        private int right(int i){
            return i * 2 + 1;
        }
    }
     

    以上代碼解析:

    1 swim 上浮,對於元素k,是否需要上浮,僅需與其父節點比較,大於父節點則交換,迭代直到根節點;

    2 sink 下沉,對於元素k,是否需要下沉,需先比較其左右子節點,找出左右子節點中較小者,較小者若比父節點大,則交換,迭代直到末尾元素;

    3 insert 插入,先將元素放到數組末尾位置,再對其進行上浮操作,直到合適位置;

    4 delMax 刪除最大值,大根堆,故第一個元素最大,先將首末元素交換,再刪除末尾元素,再對首元素下沉操作,直到合適位置;

    總結:以上只是Java簡化版,java.util.PriorityQueue 是JDK原版,客官可自行研究。但設計還是非常有技巧的,值得思考一番,假設 insert 插入

    到首位,會導致數組大量元素移動。delMax 若直接刪除首位最大值,則需要進一步判斷左右子節點大小,並進行先子節點上浮再首元素下沉操作。

            有了這個堆結構,就可以進行堆排序了,將待排數全部加入此堆結構,然後依次取出,即成有序序列了!

    2 堆排序

    如要求不使用上述堆數據結構。思路(升序為例):將數組構建為一個大頂堆,首元素即為數組最大值,首尾元素交換;排除末尾元素后調整大頂堆,

    則新的首元素即為次最大值,交換首尾並再排除末尾元素;如此循環,最後的數組即為升序排列

    public class HeapSort02 {
        public static void main(String []args){
            int []arr = {2,1,8,6,4,7,3,0,9,5};
            sort(arr);
            System.out.println(Arrays.toString(arr));
        }
    
        public static void sort(int []arr){
            int len = arr.length;
            // 創建一個大頂堆
            for(int i = (int) Math.ceil(len/2 - 1); i >= 0; i--){
                //從第一個非恭弘=叶 恭弘子結點從下至上,從右至左調整結構
                adjustHeap(arr,i,len);
            }
            // 交換首尾元素,並重新調整大頂堆
            for(int j = len-1;j > 0;j--){
                swap(arr,0,j);
                adjustHeap(arr,0,j);
            }
        }
    
        /** 迭代寫法*/
        public static void adjustHeap(int []arr,int i,int length){
            int temp = arr[i];
            for (int k = 2*i + 1; k < length; k=k*2 + 1) {
            // 注意這裏的k + 1 < length
                // 如果右子節點大於左子節點,則比較對象為右子節點
                if (k + 1 < length && arr[k] < arr[k+1]){
                    k++;
                }
                if (arr[k] > temp){
                    // 不進行值交換
                    arr[i] = arr[k];
                    i = k;
                }
                else{
                    break;
                }
            }
            arr[i] = temp;
        }
    
        /** 遞歸寫法*/
        private static void adjustHeap2(int[] arr, int i, int len){
            int left = 2 * i + 1;
            int right = 2 * i + 2;
            int maxIndex = i;
            // 注意這裏的 left < len
            if (left < len && arr[left] > arr[maxIndex]){
                maxIndex = left;
            }
            if (right < len && arr[right] > arr[maxIndex]){
                maxIndex = right;
            }
            if (maxIndex != i){
                swap(arr,i,maxIndex);
                adjustHeap2(arr,maxIndex,len);
            }
        }
    
        /** 交換元素 */
        public static void swap(int []arr,int a ,int b){
            int temp=arr[a];
            arr[a] = arr[b];
            arr[b] = temp;
        }
    }
     

    以上代碼解析:

    1完全二叉樹結構中,如果根節點順序號為 0,總節點數為 N,則最末節點的父節點即為最後一個非恭弘=叶 恭弘子節點,順序號為 ceil(N/2 -1),

    2 adjustHeap2 為啥使用三個參數,不用中間的參數可以?使用三個參數,是為了進行遞歸調用,因為遞歸肯定是縮小計算規模,而這裏的形參arr和len是固定不變的;

    3 adjustHeap是非遞歸寫法,不用中間的參數可以?調用一在“構建大頂堆”處,可寫為函數體內初始化 i,並形成雙重 for 循環;調用二在“重新調整大頂堆”處,

        可見中間參數為 0,可直接去掉。故回答是可以!但需要調整寫法,且影響該方法復用,這裏直接寫為三個形參的函數更為優雅而已。

    4非遞歸寫法理解:類似插入排序思想(依次移動並找到合適的位置再插入),先將 arr[i] 取出,然後此節點和左右子樹進行比較,如子樹更大則子節點上升一層,使

        用for循環迭代到最終位置,並進行賦值;

     

    以 i=0 為例:

    5遞歸方式理解:定位目標元素的左右子樹,若子樹值更大,則進行值交換,且因為子樹發生了變化,故需要對子樹進行遞歸處理;

    3 前K個最大的數

    在N個數中找出前K個最大的數: 思路:從N個數中取出前K個數,形成一個數組[K],將該數組調整為一個小頂堆,則可知堆頂為K個數中最小值,

    然後依次將剩餘 N-K 個數與堆頂比較,若大於,則替換掉並調整堆,直到所有元素加入完畢,堆中元素即為目標集合。

    public class HeapSort {
        public static void main(String[] args) {
            int[] arr = new int[100];
            for (int i = 0; i < 100; i++) {
                arr[i] = i + 1;
            }
            // 前10個最大的數
            int k = 10;
            // 構造小頂堆
            for (int i = (int) Math.ceil(k/2 - 1); i >= 0; i--) {
                adjustHeap(arr,i,k);
            }
            // 依次比較剩餘元素
            for (int i = 10; i < arr.length; i++) {
                if (arr[i] > arr[0]){
                    swap(arr,0,i);
                    adjustHeap(arr,0,k);
                }
            }
            // 輸出結果
            for (int i = 0; i < 10; i++) {
                System.out.print(arr[i]+"-");
            }
        }
    
        /** 非迭代寫法 ,對arr[i]進行調整 */
        private static void adjustHeap(int[] arr,int i,int length){
            int temp = arr[i];
            for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {
                // 因第一次循環中可能越界,故需要 k+1 < length
                if (k + 1 < length && arr[k] > arr[k + 1]){
                    k++;
                }
                if (arr[k] < temp){
                    arr[i] = arr[k];
                    i = k;
                }
                else {
                    break;
                }
            }
            arr[i] = temp;
        }
        /** 遞歸寫法 */
        private static void adjustHeap2(int[] arr,int i,int length){
            int left = i * 2 + 1;
            int right = i * 2 + 2;
            int samller = i;
            if (left < length && arr[left] > arr[samller]){
                samller = right;
            }
            if (right < length && arr[right] > arr[samller]){
                samller = right;
            }
            if (samller != i){
                swap(arr,i,samller);
                adjustHeap2(arr,samller,length);
            }
        }
    
        /** 交換元素 */
        public static void swap(int []arr,int a ,int b){
            int temp=arr[a];
            arr[a] = arr[b];
            arr[b] = temp;
        }
    }
     

    以上代碼解析:按照”初始化—構建小頂堆—比較調整—輸出結果”執行。注意for循環中,因第一次循環中未使用for語句條件判斷,可能越界,故需要 k+1 < length

    輸出結果如下:

    請看官思考,如果需求變為找出N個數中找出前K個最小的數,該如何實現? 建議動腦且動手的寫一遍!因為魔鬼在細節!

    全文完!

    我近期其他文章:

    • 1 Dubbo學習系列之十九(Apollo配置中心)
    • 2 聊聊算法——二分查找算法深度分析
    • 3 DevOps系列——Jenkins/Gitlab自動打包部署
    • 4 DevOps系列——Jenkins私服
    • 5 DevOps系列——Gitlab私服

        只寫原創,敬請關注 

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

    【其他文章推薦】

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

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

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

    ※別再煩惱如何寫文案,掌握八大原則!

  • 為什麼建議你使用枚舉?

    為什麼建議你使用枚舉?

    枚舉是 JDK 1.5 新增的數據類型,使用枚舉我們可以很好的描述一些特定的業務場景,比如一年中的春、夏、秋、冬,還有每周的周一到周天,還有各種顏色,以及可以用它來描述一些狀態信息,比如錯誤碼等。

    枚舉類型不止存在在 Java 語言中,在其它語言中也都能找到它的身影,例如 C# 和 Python 等,但我發現在實際的項目中使用枚舉的人很少,所以本文就來聊一聊枚舉的相關內容,好讓朋友們對枚舉有一個大概的印象,這樣在編程時起碼還能想到有“枚舉”這樣一個類型。

    本文的結構目錄如下:

    枚舉的 7 種使用方法

    很多人不使用枚舉的一個重要的原因是對枚舉不夠熟悉,那麼我們就先從枚舉的 7 種使用方法說起。

    用法一:常量

    在 JDK 1.5 之前,我們定義常量都是 public static final... ,但有了枚舉,我們就可以把這些常量定義成一個枚舉類了,實現代碼如下:

    public enum ColorEnum {  
      RED, GREEN, BLANK, YELLOW  
    } 
    

    用法二:switch

    將枚舉用在 switch 判斷中,使得代碼可讀性更高了,實現代碼如下:

    enum ColorEnum {
        GREEN, YELLOW, RED
    }
    public class ColorTest {
        ColorEnum color = ColorEnum.RED;
    
        public void change() {
            switch (color) {
                case RED:
                    color = ColorEnum.GREEN;
                    break;
                case YELLOW:
                    color = ColorEnum.RED;
                    break;
                case GREEN:
                    color = ColorEnum.YELLOW;
                    break;
            }
        }
    }
    

    用法三:枚舉中增加方法

    我們可以在枚舉中增加一些方法,讓枚舉具備更多的特性,實現代碼如下:

    public class EnumTest {
        public static void main(String[] args) {
            ErrorCodeEnum errorCode = ErrorCodeEnum.SUCCESS;
            System.out.println("狀態碼:" + errorCode.code() + 
                               " 狀態信息:" + errorCode.msg());
        }
    }
    
    enum ErrorCodeEnum {
        SUCCESS(1000, "success"),
        PARAM_ERROR(1001, "parameter error"),
        SYS_ERROR(1003, "system error"),
        NAMESPACE_NOT_FOUND(2001, "namespace not found"),
        NODE_NOT_EXIST(3002, "node not exist"),
        NODE_ALREADY_EXIST(3003, "node already exist"),
        UNKNOWN_ERROR(9999, "unknown error");
    
        private int code;
        private String msg;
    
        ErrorCodeEnum(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    
        public int code() {
            return code;
        }
    
        public String msg() {
            return msg;
        }
    
        public static ErrorCodeEnum getErrorCode(int code) {
            for (ErrorCodeEnum it : ErrorCodeEnum.values()) {
                if (it.code() == code) {
                    return it;
                }
            }
            return UNKNOWN_ERROR;
        }
    }
    

    以上程序的執行結果為:

    狀態碼:1000 狀態信息:success

    用法四:覆蓋枚舉方法

    我們可以覆蓋一些枚舉中的方法用於實現自己的業務,比如我們可以覆蓋 toString() 方法,實現代碼如下:

    public class EnumTest {
        public static void main(String[] args) {
            ColorEnum colorEnum = ColorEnum.RED;
            System.out.println(colorEnum.toString());
        }
    }
    
    enum ColorEnum {
        RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLOW("黃色", 4);
        //  成員變量
        private String name;
        private int index;
    
        //  構造方法
        private ColorEnum(String name, int index) {
            this.name = name;
            this.index = index;
        }
    
        //覆蓋方法
        @Override
        public String toString() {
            return this.index + ":" + this.name;
        }
    }
    

    以上程序的執行結果為:

    1:紅色

    用法五:實現接口

    枚舉類可以用來實現接口,但不能用於繼承類,因為枚舉默認繼承了 java.lang.Enum 類,在 Java 語言中允許實現多接口,但不能繼承多個父類,實現代碼如下:

    public class EnumTest {
        public static void main(String[] args) {
            ColorEnum colorEnum = ColorEnum.RED;
            colorEnum.print();
            System.out.println("顏色:" + colorEnum.getInfo());
        }
    }
    
    interface Behaviour {
        void print();
    
        String getInfo();
    }
    
    enum ColorEnum implements Behaviour {
        RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLOW("黃色", 4);
        private String name;
        private int index;
    
        private ColorEnum(String name, int index) {
            this.name = name;
            this.index = index;
        }
    
        @Override
        public void print() {
            System.out.println(this.index + ":" + this.name);
        }
    
        @Override
        public String getInfo() {
            return this.name;
        }
    }
    

    以上程序的執行結果為:

    1:紅色

    顏色:紅色

    用法六:在接口中組織枚舉類

    我們可以在一個接口中創建多個枚舉類,用它可以很好的實現“多態”,也就是說我們可以將擁有相同特性,但又有細微實現差別的枚舉類聚集在一個接口中,實現代碼如下:

    public class EnumTest {
        public static void main(String[] args) {
            // 賦值第一個枚舉類
            ColorInterface colorEnum = ColorInterface.ColorEnum.RED;
            System.out.println(colorEnum);
            // 賦值第二個枚舉類
            colorEnum = ColorInterface.NewColorEnum.NEW_RED;
            System.out.println(colorEnum);
        }
    }
    
    interface ColorInterface {
        enum ColorEnum implements ColorInterface {
            GREEN, YELLOW, RED
        }
        enum NewColorEnum implements ColorInterface {
            NEW_GREEN, NEW_YELLOW, NEW_RED
        }
    }
    

    以上程序的執行結果為:

    RED

    NEW_RED

    用法七:使用枚舉集合

    在 Java 語言中和枚舉類相關的,還有兩個枚舉集合類 java.util.EnumSetjava.util.EnumMap,使用它們可以實現更多的功能。

    使用 EnumSet 可以保證元素不重複,並且能獲取指定範圍內的元素,示例代碼如下:

    import java.util.ArrayList;
    import java.util.EnumSet;
    import java.util.List;
    
    public class EnumTest {
        public static void main(String[] args) {
            List<ColorEnum> list = new ArrayList<ColorEnum>();
            list.add(ColorEnum.RED);
            list.add(ColorEnum.RED);  // 重複元素
            list.add(ColorEnum.YELLOW);
            list.add(ColorEnum.GREEN);
            // 去掉重複數據
            EnumSet<ColorEnum> enumSet = EnumSet.copyOf(list);
            System.out.println("去重:" + enumSet);
    
            // 獲取指定範圍的枚舉(獲取所有的失敗狀態)
            EnumSet<ErrorCodeEnum> errorCodeEnums = EnumSet.range(ErrorCodeEnum.ERROR, ErrorCodeEnum.UNKNOWN_ERROR);
            System.out.println("所有失敗狀態:" + errorCodeEnums);
        }
    }
    
    enum ColorEnum {
        RED("紅色", 1), GREEN("綠色", 2), BLANK("白色", 3), YELLOW("黃色", 4);
        private String name;
        private int index;
    
        private ColorEnum(String name, int index) {
            this.name = name;
            this.index = index;
        }
    }
    
    enum ErrorCodeEnum {
        SUCCESS(1000, "success"),
        ERROR(2001, "parameter error"),
        SYS_ERROR(2002, "system error"),
        NAMESPACE_NOT_FOUND(2003, "namespace not found"),
        NODE_NOT_EXIST(3002, "node not exist"),
        NODE_ALREADY_EXIST(3003, "node already exist"),
        UNKNOWN_ERROR(9999, "unknown error");
    
        private int code;
        private String msg;
    
        ErrorCodeEnum(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    
        public int code() {
            return code;
        }
    
        public String msg() {
            return msg;
        }
    }
    

    以上程序的執行結果為:

    去重:[RED, GREEN, YELLOW]

    所有失敗狀態:[ERROR, SYS_ERROR, NAMESPACE_NOT_FOUND, NODE_NOT_EXIST, NODE_ALREADY_EXIST, UNKNOWN_ERROR]

    EnumMapHashMap 類似,不過它是一個專門為枚舉設計的 Map 集合,相比 HashMap 來說它的性能更高,因為它內部放棄使用鏈表和紅黑樹的結構,採用數組作為數據存儲的結構。

    EnumMap 基本使用示例如下:

    import java.util.EnumMap;
    
    public class EnumTest {
        public static void main(String[] args) {
            EnumMap<ColorEnum, String> enumMap = new EnumMap<>(ColorEnum.class);
            enumMap.put(ColorEnum.RED, "紅色");
            enumMap.put(ColorEnum.GREEN, "綠色");
            enumMap.put(ColorEnum.BLANK, "白色");
            enumMap.put(ColorEnum.YELLOW, "黃色");
            System.out.println(ColorEnum.RED + ":" + enumMap.get(ColorEnum.RED));
        }
    }
    
    enum ColorEnum {
        RED, GREEN, BLANK, YELLOW;
    }
    

    以上程序的執行結果為:

    RED:紅色

    使用注意事項

    阿里《Java開發手冊》對枚舉的相關規定如下,我們在使用時需要稍微注意一下。

    【強制】所有的枚舉類型字段必須要有註釋,說明每個數據項的用途。

    【參考】枚舉類名帶上 Enum 後綴,枚舉成員名稱需要全大寫,單詞間用下劃線隔開。說明:枚舉其實就是特殊的常量類,且構造方法被默認強制是私有。正例:枚舉名字為 ProcessStatusEnum 的成員名稱:SUCCESS / UNKNOWN_REASON。

    假如不使用枚舉

    在枚舉沒有誕生之前,也就是 JDK 1.5 版本之前,我們通常會使用 int 常量來表示枚舉,實現代碼如下:

    public static final int COLOR_RED = 1;
    public static final int COLOR_BLUE = 2;
    public static final int COLOR_GREEN = 3;
    

    但是使用 int 類型可能存在兩個問題:

    第一, int 類型本身並不具備安全性,假如某個程序員在定義 int 時少些了一個 final 關鍵字,那麼就會存在被其他人修改的風險,而反觀枚舉類,它“天然”就是一個常量類,不存在被修改的風險(原因詳見下半部分);

    第二,使用 int 類型的語義不夠明確,比如我們在控制台打印時如果只輸出 1…2…3 這樣的数字,我們肯定不知道它代表的是什麼含義。

    那有人就說了,那就使用常量字符唄,這總不會還不知道語義吧?實現示例代碼如下:

    public static final String COLOR_RED = "RED";
    public static final String COLOR_BLUE = "BLUE";
    public static final String COLOR_GREEN = "GREEN";
    

    但是這樣同樣存在一個問題,有些初級程序員會不按套路出牌,他們可能會直接使用字符串的值進行比較,而不是直接使用枚舉的字段,實現示例代碼如下:

    public class EnumTest {
        public static final String COLOR_RED = "RED";
        public static final String COLOR_BLUE = "BLUE";
        public static final String COLOR_GREEN = "GREEN";
        public static void main(String[] args) {
            String color = "BLUE";
            if ("BLUE".equals(color)) {
                System.out.println("藍色");
            }
        }
    }
    

    這樣當我們修改了枚舉中的值,那程序就涼涼了。

    枚舉使用場景

    枚舉的常見使用場景是單例,它的完整實現代碼如下:

    public class Singleton {
        // 枚舉類型是線程安全的,並且只會裝載一次
        private enum SingletonEnum {
            INSTANCE;
            // 聲明單例對象
            private final Singleton instance;
            // 實例化
            SingletonEnum() {
                instance = new Singleton();
            }
            private Singleton getInstance() {
                return instance;
            }
        }
        // 獲取實例(單例對象)
        public static Singleton getInstance() {
            return SingletonEnum.INSTANCE.getInstance();
        }
        private Singleton() {
        }
        // 類方法
        public void sayHi() {
            System.out.println("Hi,Java.");
        }
    }
    class SingletonTest {
        public static void main(String[] args) {
            Singleton singleton = Singleton.getInstance();
            singleton.sayHi();
        }
    }
    

    因為枚舉只會在類加載時裝載一次,所以它是線程安全的,這也是《Effective Java》作者極力推薦使用枚舉來實現單例的主要原因。

    知識擴展

    枚舉為什麼是線程安全的?

    這一點要從枚舉最終生成的字節碼說起,首先我們先來定義一個簡單的枚舉類:

    public enum ColorEnumTest {
        RED, GREEN, BLANK, YELLOW;
    }
    

    然後我們再將上面的那段代碼編譯為字節碼,具體內容如下:

    public final class ColorEnumTest extends java.lang.Enum<ColorEnumTest> {
      public static final ColorEnumTest RED;
      public static final ColorEnumTest GREEN;
      public static final ColorEnumTest BLANK;
      public static final ColorEnumTest YELLOW;
      public static ColorEnumTest[] values();
      public static ColorEnumTest valueOf(java.lang.String);
      static {};
    }
    

    從上述結果可以看出枚舉類最終會被編譯為被 final 修飾的普通類,它的所有屬性也都會被 staticfinal 關鍵字修飾,所以枚舉類在項目啟動時就會被 JVM 加載並初始化,而這個執行過程是線程安全的,所以枚舉類也是線程安全的類。

    小貼士:代碼反編譯的過程是先用 javac 命令將 java 代碼編譯字節碼(.class),再使用 javap 命令查看編譯的字節碼。

    枚舉比較小技巧

    我們在枚舉比較時使用 == 就夠了,因為枚舉類是在程序加載時就創建了(它並不是 new 出來的),並且枚舉類不允許在外部直接使用 new 關鍵字來創建枚舉實例,所以我們在使用枚舉類時本質上只有一個對象,因此在枚舉比較時使用 == 就夠了。

    並且我們在查看枚舉的 equlas() 源碼會發現,它的內部其實還是直接調用了 == 方法,源碼如下:

    public final boolean equals(Object other) {
        return this==other;
    }
    

    總結

    本文我們介紹了枚舉類的 7 種使用方法:常量、switch、枚舉中添加方法、覆蓋枚舉方法、實現接口、在接口中組織枚舉類和使用枚舉集合等,然後講了如果不使用枚舉類使用 int 類型和 String 類型存在的一些弊端:語義不夠清晰、容易被修改、存在被誤用的風險,所以我們在適合的環境下應該盡量使用枚舉類。並且我們還講了枚舉類的使用場景——單例,以及枚舉類為什麼是安全的,最後我們講了枚舉比較的小技巧,希望本文對你有幫助。

    查看 & 鳴謝

    https://www.iteye.com/blog/softbeta-1185573

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

    【其他文章推薦】

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

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※別再煩惱如何寫文案,掌握八大原則!

  • 可拖拽圓形進度條組件(支持移動端)

    可拖拽圓形進度條組件(支持移動端)

    好久之前寫過一個可拖拽圓形進度條的dome,中間有網友反饋過一些問題,最近比較閑有時間修改了一些問題也做了一些優化,並封裝成組件,基於canvas實現,只需傳入放置組件dom容器,任何框架均可直接使用;

    codepen 示例如下:https://codepen.io/pangyongsheng/pen/XRmNRK

     

    一、如何使用

    npm下載

    執行 npm i drag-arc -S 或 cnpm i drag-arc -S

     
    import DragArc from 'drag-arc';
     new DragArc({
        el: dom,
        value: 10,
        change: (v) => {
            console.log(v)
        },
        ...
    })
    或者 也可從項目下載dist/dist/drag-arc.min.js,直接通過srcipt標籤引入

    其中dom為放置組件HTML容器,可通過ref獲取;

    主要屬性方法(詳見github/npm)

    項目地址:https://github.com/pangyongsheng/canvas-arc-draw
    npm地址:https://www.npmjs.com/package/drag-arc

    Name Description Type Default Required
    el 放置組件的DOM元素 Element none Y
    change 當前值變化時觸發的事件,回調參數為當前進度值Number(0-100) Function ()=>{} N
    startDeg 滑動圓弧的起始弧度 Number  0 N
    endDeg 滑動圓弧的結束弧度 Number 1 N
    value 默認值 Number (0-100) 0 N
    textShow 显示文字 Boolean true N
    color 外側圓弧顏色 String,Array [“#06dabc”, “#33aaff”] N
    slider 滑塊半徑 Number #FFF N
    innerColor 內側弧度的顏色 String #ccc N
    outColor 外側圓弧背景顏色 String,Array #ccc N
    innerLineWidth 內側弧線寬 Number 1 N
    outLineWidth 外側弧線寬 Number 20 N
    counterclockwise 逆時針方向 Boolean true N
    sliderColor 滑塊顏色 String #CCC N
    sliderBorderColor 滑塊邊框顏色 String #fff N

    二、實現方法簡介

    1、繪製位置幾何關係

    如圖所示,以canvas畫布中心點建立坐標系,則有:

    滑塊位置與弧度關係:

    由圓的參數方程得出
    x=rcosφ
    y=rsinφ

    鼠標移動位置與弧度關係:

    通過事件回調參數 我們可以獲得 鼠標mousemove事件或者移動端touchmove事件的x,y坐標,可計算tan值為
    tanφ = y/x;
    再通過反三角函數有可得:
    φ=arctan(tanφ)

    以上基本的位置關係已經得出;

    2、js實現中的幾個問題

    (1)坐標的轉化方法

    由於上述位置關係是基於中心坐標實現的,而canvas繪製坐標是以左上角為原點實現的,故需要實現兩種坐標的轉化關係;

    (2)canvas弧度位置與正常弧度位置的轉化

    下圖是canvas的弧度位置恰好與我們正常計算的方向是相反的,同樣需考慮弧度的轉換;

    (3)Math.atan方法返回值與實際弧度的關係

    由於Math.atan() 函數返回一個數值的反正切[- π/2 , π/2 ],
    而實際中我們需要獲得到[0-2π]直接的值,所以在通過鼠標位置獲取弧度值時需要通過Math.atan(y/x)和xy在中心坐標的正負綜合判斷其所在象限從何獲取實際的獲取弧度值;

    (4)弧度與進度條值得關係

    由於鼠標移動觸發繪圖方法是較為連續的動畫效果,而進度是間隔的,
    這裏我們需要實現個類似d3js中domain和range的比例關係。
    這裏我們將值[0,100]對應弧度比例為[startDeg, endDeg]

    (5)終點的判斷

    由於鼠標移動的位置是任意的,可能導致滑塊到達終點後由於鼠標移動到了起點時,滑塊也直接從終點移動到起點,故需對起點終點做判斷,到達起點后不可再向後滑動,到達終點后不可再向前滑動;

    3、詳細實現方法可以參考這篇文章

     https://www.cnblogs.com/pangys/p/6837344.html

     

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

    【其他文章推薦】

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

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

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

    ※別再煩惱如何寫文案,掌握八大原則!

  • 多圖解釋Redis的整數集合intset升級過程

    多圖解釋Redis的整數集合intset升級過程

    redis源碼分析系列文章

    [Redis源碼系列]在Liunx安裝和常見API 

    為什麼要從Redis源碼分析 

    String底層實現——動態字符串SDS 

    雙向鏈表都不懂,還說懂Redis?

    面試官:說說Redis的Hash底層 我:……(來自閱文的面試題)

    Redis的跳躍表確定不了解下

     

    前言

    大噶好,今天仍然是元氣滿滿的一天,拋開永遠寫不完的需求,拒絕要求賊變態的客戶,單純的學習技術,感受技術的魅力。(哈哈哈,皮一下很開森)

    前面幾周我們一起看了Redis底層數據結構,如動態字符串SDS雙向鏈表Adlist字典Dict跳躍表,如果有對Redis常見的類型或底層數據結構不明白的請看上面傳送門。

    今天來說下set的底層實現整數集合,如果有對set不明白的,常見的API使用這篇就不講了,看上面的傳送門哈。

    整數集合概念

    整數集合是Redis設計的一種底層結構,是set的底層實現,當集合中只包含整數值元素,並且這個集合元素數據不多時,會使用這種結構。但是如果不滿足剛才的條件,會使用其他結構,這邊暫時不講哈。

    下圖為整數集合的實際組成,包括三個部分,分別是編碼格式encoding,包含元素數量length,保存元素的數組contents。(這邊只需要簡單看下,下面針對每個模塊詳細說明哈)

    整數集合的實現

    我們看下intset.h裏面關於整數集合的定義,上代碼哈:

    //整數集合結構體
    typedef struct intset {
        uint32_t encoding;  //編碼格式,有如下三種格式,初始值默認為INTSET_ENC_INT16
        uint32_t length;    //集合元素數量
        int8_t contents[];  //保存元素的數組,元素類型並不一定是ini8_t類型,柔性數組不佔intset結構體大小,並且數組中的元素從小到大排列。
    } intset;               
    
    #define INTSET_ENC_INT16 (sizeof(int16_t))   //16位,2個字節,表示範圍-32,768~32,767
    #define INTSET_ENC_INT32 (sizeof(int32_t))   //32位,4個字節,表示範圍-2,147,483,648~2,147,483,647
    #define INTSET_ENC_INT64 (sizeof(int64_t))   //64位,8個字節,表示範圍-9,223,372,036,854,775,808~9,223,372,036,854,775,807

     

     

    編碼格式encoding

    包括INTSET_ENC_INT16,INTSET_ENC_INT32,INTSET_ENC_INT64三種類型,其分別對應着不同的範圍,具體看上面代碼的註釋信息。

    因為插入的數據的大小是不一樣的,為了盡可能的節約內存(畢竟都是錢,平時要省着點用),所以我們需要使用不同的類型來存儲數據。

    集合元素數量length

    記錄了保存數據contents的長度,即有多少個元素。

    保存元素的數組contents

    真正存儲數據的地方,數組是按照從小到大有序排序的,並且不包含任何重複項(因為set是不含重複項,所以其底層實現也是不含包含項的)。

    整數集合升級過程(重點,手動標星)

    上面的圖我們重新看下,編碼格式encoding為INTSET_ENC_INT16,即每個數據佔16位。長度length為4,即數組content裏面有四個元素,分別是1,2,3,4。如果我們要添加一個数字位40000,很明顯超過編碼格式為INTSET_ENC_INT16的範圍-32,768~32,767,應該是編碼格式為INTSET_ENC_INT32。那麼他是如何升級的呢,從INTSET_ENC_INT16升級到INTSET_ENC_INT32的呢?

    1.了解舊的存儲格式

    首先我們看下1,2,3,4這四個元素是如何存儲的。首先要知道一共有多少位,計算規則為length*編碼格式的位數,即4*16=64。所以每個元素佔用了16位。

    2.確定新的編碼格式

    新的元素為40000,已經超過了INTSET_ENC_INT16的範圍-32,768~32,767,所以新的編碼格式為INTSET_ENC_INT32。

    3.根據新的編碼格式新增內存

    上面已經說明了編碼格式為INTSET_ENC_INT32,計算規則為length*編碼格式的位數,即5*32=160。所以新增的位數為64-159。

    4.根據編碼格式設置對應的值

    從上面知道按照新的編碼格式,每個數據應該佔用32位,但是舊的編碼格式,每個數據佔用16位。所以我們從後面開始,每次獲取32位用來存儲數據。

    這樣說太難懂了,看下圖。

    首先,那最後32位,即128-159存儲40000。那麼第49-127是空着的。

    接着,取空着的49-127最後的32位,即96到127這32位,用來存儲4。那麼之前4存儲的位置48-6349-127剩下的64-95這兩部分組成了一個大部分,即48-95,現在空着啦。

    在接着在48-95這個大部分,再取后32位,即64-95,用來存儲3。那麼之前3存儲位置32-4748-95剩下的48-63這兩部分組成了一個大部分,即32-63,現在空着啦。

    再接着,將32-63這個大部分,再取后32位,即還是32-63,用來存儲2。那麼之前2存儲位置16-31空着啦。

    最後,將16-31和原來0-31合起來,存儲1。

    至此,整個升級過程結束。整體來說,分為3步,確定新的編碼格式,新增需要的內存空間,從后往前調整數據。

    這邊有個小問題,為啥要從后往前調整數據呢?

    原因是如果從前往後,數據可能會覆蓋。也拿上面個例子來說,數據1在0-15位,數據2在16-31位,如果從前往後,我們知道新的編碼格式INTSET_ENC_INT32要求每個元素佔用32位,那麼數據1應該佔用0-31,這個時候數據2就被覆蓋了,以後就不知道數據2啦。

    但是從后往前,因為後面新增了一些內存,所以不會發生覆蓋現象。

    升級的優點

     節約內存

    整數集合既可以讓集合保存三種不同類型的值,又可以確保升級操作只在有需要的時候進行,這樣就節省了內存。 

    不支持降級

    一旦對數組進行升級,編碼就會一直保存升級后的狀態。即使後面把40000刪掉了,編碼格式還是不會將會INTSET_ENC_INT16。

    整數集合的源碼分析

    創建一個空集合 intsetnew

    這個方法比較簡單,是初始化整數集合的步驟,即下圖部分。

    主要的步驟是分配內存空間,設置默認編碼格式,以及初始化數組長度length。

    intset *intsetNew(void) {
        intset *is = zmalloc(sizeof(intset));//分配內存空間 
        is->encoding = intrev32ifbe(INTSET_ENC_INT16);//設置默認編碼格式INTSET_ENC_INT16 
        is->length = 0;//初始化length 
        return is;
    }

    添加元素並升級insetAdd流程圖(重點)

    添加元素並升級insetAdd源碼分析

    可以根據上面的流程圖,對照着下面的源碼分析,這邊就不寫啦哈。

    //添加元素
    //輸入參數*is為原整數集合
    //value為要添加的元素
    //*success為是否添加成功的標誌量 ,1表示成功,0表示失敗 
    intset *intsetAdd(intset *is, int64_t value, uint8_t *success) {
        //確定要添加的元素的編碼格式 
        uint8_t valenc = _intsetValueEncoding(value);
        
        uint32_t pos;
        //如果success沒有初始值,則初始化為1 
        if (success) *success = 1;
    
       //如果新的編碼格式大於現在的編碼格式,則升級並添加元素 
        if (valenc > intrev32ifbe(is->encoding)) {
            //調用另一個方法 
            return intsetUpgradeAndAdd(is,value);
        } else {
            //如果編碼格式不變,則調用查詢方法 
            //輸入參數is為原整數集合 
            //value為要添加的數據
            //pos為位置 
            if (intsetSearch(is,value,&pos)) {//如果找到了,則直接返回,因為數據是不可重複的。 
                if (success) *success = 0;
                return is;
            }
    
            //設置length 
            is = intsetResize(is,intrev32ifbe(is->length)+1);
            if (pos < intrev32ifbe(is->length)) intsetMoveTail(is,pos,pos+1);
        }
        //設置數據 
        _intsetSet(is,pos,value);
        is->length = intrev32ifbe(intrev32ifbe(is->length)+1);
        return is;
    }
    
    
    //#define INT8_MAX 127
    //#define INT16_MAX 32767
    //#define INT32_MAX 2147483647
    //#define INT64_MAX 9223372036854775807LL 
    static uint8_t _intsetValueEncoding(int64_t v) {
        if (v < INT32_MIN || v > INT32_MAX)
            return INTSET_ENC_INT64;
        else if (v < INT16_MIN || v > INT16_MAX)
            return INTSET_ENC_INT32;
        else
            return INTSET_ENC_INT16;
    }
    
    
    //根據輸入參數value的編碼格式,對整數集合is的編碼格式升級 
    static intset *intsetUpgradeAndAdd(intset *is, int64_t value) {
        //當前集合的編碼格式 
        uint8_t curenc = intrev32ifbe(is->encoding);
        //根據對value解析獲取新的編碼格式 
        uint8_t newenc = _intsetValueEncoding(value);
        //獲取集合元素數量 
        int length = intrev32ifbe(is->length);
        //如果要添加的數據小於0,則prepend為1,否則為0 
        int prepend = value < 0 ? 1 : 0;
    
       //設置集合為新的編碼格式,並根據編碼格式重新設置內存 
        is->encoding = intrev32ifbe(newenc);
        is = intsetResize(is,intrev32ifbe(is->length)+1);
    
        //逐步循環,直到length小於0,挨個重新設置每個值,從后往前 
        while(length--)
            _intsetSet(is,length+prepend,_intsetGetEncoded(is,length,curenc));
    
        //如果value為負數,則放在最前面 
        if (prepend)
            _intsetSet(is,0,value);
        else//如果value為整數,設置最末尾的元素為value 
            _intsetSet(is,intrev32ifbe(is->length),value);
        //重新設置length 
        is->length = intrev32ifbe(intrev32ifbe(is->length)+1);
        return is;
    }
    
    
    //找到is集合中值為value的下標,返回1,並保存在pos中,沒有找到返回0,並將pos設置為value可以插入到數組的位置
    static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *pos) {
        int min = 0, max = intrev32ifbe(is->length)-1, mid = -1;
        int64_t cur = -1;
    
        //如果集合為空,那麼位置pos為0 
        if (intrev32ifbe(is->length) == 0) { 
            if (pos) *pos = 0;
            return 0;
        } else {
            //因為數據是有序集合,如果要添加的數據大於最後一個数字,那麼直接把要添加的值放在最後即可,返回最大值下標 
            if (value > _intsetGet(is,intrev32ifbe(is->length)-1)) {
                if (pos) *pos = intrev32ifbe(is->length);
                return 0;
            } else if (value < _intsetGet(is,0)) { //如果這個數據小於數組下標為0的數據,即為最小值 ,返回0 
                if (pos) *pos = 0;
                return 0;
            }
        }
        //有序集合採用二分法 
        while(max >= min) {
            mid = ((unsigned int)min + (unsigned int)max) >> 1;
            cur = _intsetGet(is,mid);
            if (value > cur) {
                min = mid+1;
            } else if (value < cur) {
                max = mid-1;
            } else {
                break;
            }
        }
    
        //確定找到 
        if (value == cur) {
            if (pos) *pos = mid;//設置參數pos,返回1,即找到位置 
            return 1;
        } else {//如果沒找到,則min和max相鄰,隨便設置都行,並返回0 
            if (pos) *pos = min; 
            return 0;
        }
    }

     

    結語

    該篇主要講了Redis的SET數據類型的底層實現整數集合,先從整數集合是什麼,,剖析了其主要組成部分,進而通過多幅過程圖解釋了intset是如何升級的,最後結合源碼對整數集合進行描述,如創建過程,升級過程,中間穿插例子和過程圖。

    如果覺得寫得還行,麻煩給個贊,您的認可才是我寫作的動力!

    如果覺得有說的不對的地方,歡迎評論指出。

    好了,拜拜咯。

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

    【其他文章推薦】

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

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※別再煩惱如何寫文案,掌握八大原則!

  • 大自然工程師河狸將修築堤壩 助英格蘭抗水患

    摘錄自2019年11月20日中央通訊社倫敦報導

    業務涵蓋歷史古蹟與鄉村管理的英國保育組織「國家信託」(National Trust)今天(20日)宣布,預定明年初在英格蘭南部兩地施放天生會修築堤壩的歐亞河狸,協助對抗水患。其中一地的計畫經理伊爾德利(Ben Eardley)指出:「河狸修築的堤壩在乾季可儲水,此外還有助降低下游暴洪、減少河岸侵蝕,攔截淤泥也可改善水質。」

    河狸素有「大自然工程師」美譽,牠創造的濕地環境可供小至昆蟲、大至野禽等許多物種棲息。這些河狸將生活在有柵欄隔離林地,專家將監測棲地變化。

    「國家信託」計畫於2025年前讓2萬5000公頃土地重新成為大量野生動植物的棲地。英國氣象局(Met Office)資料顯示,英格蘭北部近幾週遭逢嚴重水患,部分地區創下有紀錄以來最潮濕秋季。英格蘭光是今天早上就有18起水患警報,另有58起可能淹水警告。

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

    【其他文章推薦】

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

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

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

    ※別再煩惱如何寫文案,掌握八大原則!

  • 韓媒:台灣值得被納入全球氣候變遷體系

    摘錄自2019年11月19日中央社報導

    韓國「韓民族新聞」和英文報The Korea Times今(19日)同步刊載中華民國行政院環保署長張子敬署名的投書專文,呼籲國際社會接納台灣成為全球氣候變遷體系的一員。張子敬在分別以Taiwan: valuable partner in fighting climate change和「台灣也應當參與全球氣候變遷協約」為標題,向韓國報紙投書闡述台灣欲加入全球氣候變遷體系的立場。

    專文指出,台灣整合中央相關部會工作,制訂「國家氣候變遷調適行動方案」,從災害、維生基礎設施、水資源、國土安全、海岸、能源及產業、農業、健康等8個面向,建構因應氣候變遷的韌性體制;在醫療領域上特別著重強化醫療衛生及防疫系統預防、減災、應變及復原能力,維護全民健康並優先保障弱勢住民。

    另外在生態保育領域上,將維護農業生產資源及生物多樣性,加強監測與預警機制、強化天然災害救助及保險體系、整合科技提升農林漁牧產業抗逆境能力,並完善自然保護區經營管理、建構長期生態監測體系、強化物種及基因的多樣性保存與合理利用,以確保糧食安全並建構適應氣候風險的永續農業。

    專文認為,台灣因政治成見被排除在國際組織之外,是相當不公平的,非但不符合氣候公約籲請所有國家對全球氣候變遷進行廣泛合作的精神,忽視巴黎協定強調「氣候正義」及呼籲各國採取氣候行動的重要性,更違背聯合國憲章宗旨,也弱化國際架構而對世界造成傷害。

    專文強調,面對國際社會,台灣是負責任、肯貢獻的真誠朋友,樂於分享在環境治理制度、防災預警系統、能源效率提升技術、科技創新運用等相關領域的經驗,台灣努力希望能讓世界更美好,而台灣也真的值得被納入全球氣候變遷體系的一員。

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

    【其他文章推薦】

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

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※幫你省時又省力,新北清潔一流服務好口碑

    ※別再煩惱如何寫文案,掌握八大原則!

  • 韓國入冬後空氣污染物八成來自中國

    摘錄自2019年11月21日大紀元報導

    韓、日、中三國對大氣污染物流動的共同研究顯示,韓國境內有高達三成的細懸浮污染物(PM2.5)來自中國,入冬後這個數字更飆高至八成。

    據韓聯社報導,韓國環境部下屬國立環境科學院20日發布報告概要指,韓日主要城市由國內因素導致污染的比例分別為51%和55%,而中國是91%。

    從國外成因來看,韓國的空氣污染物中,來自中日兩國的各占32%和2%,其餘來自朝鮮、蒙古、東南亞等地區。從韓日兩國流入中國的空氣污染物比重分別僅占2%和1%,從韓中兩國流入日本的比重分別為8%和25%。

    然而,如果將時間範圍限定在12月至3月,中國的空氣污染物對韓國的影響更為嚴重。據韓國國立環境科學院的調查,今年1月11日至15日韓國空氣污染物中只有18%至31%來自國內因素,其餘69%至82%來自國外,其中中國占絕大多數。

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

    【其他文章推薦】

    網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

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

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

    ※別再煩惱如何寫文案,掌握八大原則!