技術境界的二三四

兩種能力境界

1.解決問題

在工程師中有一種人被稱為”救火隊長“。哪裡出了問題,哪裡就有他的身影,他的出現,燃眉之急就有救了。他們是解決問題的高人。但是“救火隊長”在晉陞上往往會遇到瓶頸。

對標人物:漫威-美國隊長

每天嚴陣以待,隨時準備拯救世界。無法接受鋼鐵俠防患於未然用機器來解決問題解放自己的方式。

 

2.發現問題

更高的高人會問一個問題:“為什麼每天會任務追着你跑?你為什麼沒從根源上解決所有的問題?”一個在辦公室里和下面人一起研究茶道的領導要比和大家一起加班到半夜的領導受歡迎。因為他們從更大的層面上杜絕了對救火隊長的需要。

對標人物:《罪惡黑名單》雷丁頓

雷丁頓總是運籌帷幄游刃有餘。所以在形勢危急的情況下,他總是評價哪家的什麼東西好吃,或者任何別人沒有注意到的生活瑣事,觀眾並不恨他。因為知道他早就搞定了一切。

 

 

三種需求對應境界

1.對應需求

一個兢兢業業的工程師或團隊,對產品有求必應。項目初期這樣沒有錯,時間一長,就會遇到維護和擴展性問題。

對標:下圖的狀態有木有很熟悉的趕腳?

 

2.快速對應需求

通過系統性的設計和不斷的迭代重構,一個需求來了,通過少量開發或者不開發就可以完成。每周上班五天,三天用來團建。很好,直到公司創始人完成了最初的宏圖偉業,連高層也不知道要干什麼,公司開始走下坡了。

對標:請參考《浪潮之巔》

 

3.引領需求

在線上跑着的服務就會產生數據,通過數據的分析,自己的觀察思考,推演出新的商機和需求,開拓更大的市場。

對標:請參考google的7-2-1原則。

 

 

四種技術運用境界

1.會用

很多面試者在面試中被淘汰時很不服氣,這些我會用,給我分配的活我都干出來了。為什麼不要我?答案很簡單,你這個工作別人也能幹。所以聰明的老闆寧願花4個人的錢招聘3個人干5個人的活。所以怎麼才能獲得一份收入不錯的工作?

2.知道各種優劣勢,知道怎麼用更好

公司絕對不會鼓勵重複造輪子,他們更鼓勵用好輪子。所以深入透徹的技術調研分析,根據場景選擇了合適的技術是個不錯的開始。但是現有的技術並不是為自己定製的。當自己用的足夠深,就發現很多方面,現有技術確實不能滿足自己的業務需要。

3.理解原理及技術血緣,深入運用

特別是一些新技術,由於場景覆蓋還不是很全面,需要在此基礎上做一些二次開發或者內部改造,甚至重寫。重寫重寫着,突然覺得自己有更好的想法?

4.創造技術

技術創造價值,技術引領一個時代。

 

總結

持續有聲音 

 

近期文章

代碼榮辱觀-以運用風格為榮,以隨意編碼為恥

你看不懂的spring原理是因為不知道這幾個概念

應屆生offer指南

【精選推薦文章】

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

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

高級Java工程師必備 —– 深入分析 Java IO (三)

概述

Java IO即Java 輸入輸出系統。不管我們編寫何種應用,都難免和各種輸入輸出相關的媒介打交道,其實和媒介進行IO的過程是十分複雜的,這要考慮的因素特別多,比如我們要考慮和哪種媒介進行IO(文件、控制台、網絡),我們還要考慮具體和它們的通信方式(順序、隨機、二進制、按字符、按字、按行等等)。Java類庫的設計者通過設計大量的類來攻克這些難題,這些類就位於java.io包中。

在JDK1.4之後,為了提高Java IO的效率,Java又提供了一套新的IO,Java New IO簡稱Java NIO。它在標準java代碼中提供了高速的面向塊的IO操作。本篇文章重點介紹Java IO,關於Java NIO請參考我的另兩篇文章: 

高級Java工程師必備 —– 深入分析 Java IO (一)BIO

高級Java工程師必備 —– 深入分析 Java IO (二)NIO

Java IO類庫的框架

首先看個圖:

 Java IO的類型

雖然java IO類庫龐大,但總體來說其框架還是很清楚的。從是讀媒介還是寫媒介的維度看,Java IO可以分為:

  1. 輸入流:InputStream和Reader
  2. 輸出流:OutputStream和Writer

而從其處理流的類型的維度上看,Java IO又可以分為:

  1. 字節流:InputStream和OutputStream
  2. 字符流:Reader和Writer

下面這幅圖就清晰的描述了JavaIO的分類:

字節流 字符流
輸入流 InputStream Reader
輸出流 OutputStream Writer

我們的程序需要通過InputStream或Reader從數據源讀取數據,然後用OutputStream或者Writer將數據寫入到目標媒介中。其中,InputStream和Reader與數據源相關聯,OutputStream和writer與目標媒介相關聯。

Java IO的基本用法

Java IO :字節流

通過上面的介紹我們已經知道,字節流對應的類應該是InputStream和OutputStream,而在我們實際開發中,我們應該根據不同的媒介類型選用相應的子類來處理。下面我們就用字節流來操作文件媒介:

例1,用字節流寫文件

public static void writeByteToFile() throws IOException{
    String hello= new String( "hello word!");
     byte[] byteArray= hello.getBytes();
    File file= new File( "d:/test.txt");
     //因為是用字節流來寫媒介,所以對應的是OutputStream 
     //又因為媒介對象是文件,所以用到子類是FileOutputStream
    OutputStream os= new FileOutputStream( file);
     os.write( byteArray);
     os.close();
}

例2,用字節流讀文件

public static void readByteFromFile() throws IOException{
    File file= new File( "d:/test.txt");
     byte[] byteArray= new byte[( int) file.length()];
     //因為是用字節流來讀媒介,所以對應的是InputStream
     //又因為媒介對象是文件,所以用到子類是FileInputStream
    InputStream is= new FileInputStream( file);
     int size= is.read( byteArray);
    System. out.println( "大小:"+size +";內容:" +new String(byteArray));
     is.close();
}

CopyFileDemo

package com.chenhao.io.byteIO;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * @author ChenHao
 *
 */
public class CopyFileDemo {

    /**
     * @param args
     * @throws FileNotFoundException 
     */
    public static void main(String[] args) {
        String src ="E:/xp/test";
        String dest="e:/xp/test/4.jpg";
        try {
            copyFile(src,dest);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("文件不存在");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("拷貝文件失敗|關閉流失敗");
        }
    }
    /**
     * 文件的拷貝
     * @param  源文件路徑
     * @param  目錄文件路徑
     * @throws FileNotFoundException,IOException
     * @return 
     */
    public static void copyFile(String srcPath,String destPath) throws FileNotFoundException,IOException {
        //1、建立聯繫 源(存在且為文件) +目的地(文件可以不存在)  
        File src =new File(srcPath);
        File dest =new File(destPath);
        if(! src.isFile()){ //不是文件或者為null
            System.out.println("只能拷貝文件");
            throw new IOException("只能拷貝文件");
        }
        //2、選擇流
        InputStream is =new FileInputStream(src);
        OutputStream os =new FileOutputStream(dest);
        //3、文件拷貝   循環+讀取+寫出
        byte[] flush =new byte[1024];
        int len =0;
        //讀取
        while(-1!=(len=is.read(flush))){
            //寫出
            os.write(flush, 0, len);
        }
        os.flush(); //強制刷出
        
        //關閉流
        os.close();
        is.close();
    }

}

Java IO :字符流

同樣,字符流對應的類應該是Reader和Writer。下面我們就用字符流來操作文件媒介:

例3,用字符流讀文件

public static void writeCharToFile() throws IOException{
    String hello= new String( "hello word!");
    File file= new File( "d:/test.txt");
    //因為是用字符流來讀媒介,所以對應的是Writer,又因為媒介對象是文件,所以用到子類是FileWriter
    Writer os= new FileWriter( file);
    os.write( hello);
    os.close();
}

例4,用字符流寫文件

public static void readCharFromFile() throws IOException{
    File file= new File( "d:/test.txt");
    //因為是用字符流來讀媒介,所以對應的是Reader
    //又因為媒介對象是文件,所以用到子類是FileReader
    Reader reader= new FileReader( file);
    char [] byteArray= new char[( int) file.length()];
    int size= reader.read( byteArray);
    System. out.println( "大小:"+size +";內容:" +new String(byteArray));
    reader.close();
}

Java IO :字節流轉換為字符流

字節流可以轉換成字符流,java.io包中提供的InputStreamReader類就可以實現,當然從其命名上就可以看出它的作用。其實這涉及到另一個概念,IO流的組合,後面我們詳細介紹。下面看一個簡單的例子:

例5 ,字節流轉換為字符流

public static void convertByteToChar() throws IOException{
    File file= new File( "d:/test.txt");
    //獲得一個字節流
    InputStream is= new FileInputStream( file);
    //把字節流轉換為字符流,其實就是把字符流和字節流組合的結果。
    Reader reader= new InputStreamReader( is);
    char [] byteArray= new char[( int) file.length()];
    int size= reader.read( byteArray);
    System. out.println( "大小:"+size +";內容:" +new String(byteArray));
    is.close();
    reader.close();
}

Java IO:文件媒介操作

例6 ,File操作

public class FileDemo {
  public static void main(String[] args) {
         //檢查文件是否存在
        File file = new File( "d:/test.txt");
         boolean fileExists = file.exists();
        System. out.println( fileExists);
         //創建文件目錄,若父目錄不存在則返回false
        File file2 = new File( "d:/fatherDir/subDir");
         boolean dirCreated = file2.mkdir();
        System. out.println( dirCreated);
         //創建文件目錄,若父目錄不存則連同父目錄一起創建
        File file3 = new File( "d:/fatherDir/subDir2");
         boolean dirCreated2 = file3.mkdirs();
        System. out.println( dirCreated2);
        File file4= new File( "d:/test.txt");
         //判斷長度
         long length = file4.length();
         //重命名文件
         boolean isRenamed = file4.renameTo( new File("d:/test2.txt"));
         //刪除文件
         boolean isDeleted = file4.delete();
        File file5= new File( "d:/fatherDir/subDir");
         //是否是目錄
         boolean isDirectory = file5.isDirectory();
         //列出文件名
        String[] fileNames = file5.list();
         //列出目錄
        File[]   files = file4.listFiles();
  }
}

隨機讀取File文件

通過上面的例子我們已經知道,我們可以用FileInputStream(文件字符流)或FileReader(文件字節流)來讀文件,這兩個類可以讓我們分別以字符和字節的方式來讀取文件內容,但是它們都有一個不足之處,就是只能從文件頭開始讀,然後讀到文件結束。

但是有時候我們只希望讀取文件的一部分,或者是說隨機的讀取文件,那麼我們就可以利用RandomAccessFile。RandomAccessFile提供了seek()方法,用來定位將要讀寫文件的指針位置,我們也可以通過調用getFilePointer()方法來獲取當前指針的位置,具體看下面的例子:

例7,隨機讀取文件

public static void randomAccessFileRead() throws IOException {
     // 創建一個RandomAccessFile對象
    RandomAccessFile file = new RandomAccessFile( "d:/test.txt", "rw");
     // 通過seek方法來移動讀寫位置的指針
     file.seek(10);
     // 獲取當前指針
     long pointerBegin = file.getFilePointer();
     // 從當前指針開始讀
     byte[] contents = new byte[1024];
     file.read( contents);
     long pointerEnd = file.getFilePointer();
    System. out.println( "pointerBegin:" + pointerBegin + "\n" + "pointerEnd:" + pointerEnd + "\n" + new String(contents));
     file.close();
}

例8,隨機寫入文件

public static void randomAccessFileWrite() throws IOException {
     // 創建一個RandomAccessFile對象
     RandomAccessFile file = new RandomAccessFile( "d:/test.txt", "rw");
     // 通過seek方法來移動讀寫位置的指針
     file.seek(10);
     // 獲取當前指針
     long pointerBegin = file.getFilePointer();
     // 從當前指針位置開始寫
     file.write( "HELLO WORD".getBytes());
     long pointerEnd = file.getFilePointer();
     System. out.println( "pointerBegin:" + pointerBegin + "\n" + "pointerEnd:" + pointerEnd + "\n" );
     file.close();
}

Java IO:BufferedInputStream和BufferedOutputStream

BufferedInputStream顧名思義,就是在對流進行寫入時提供一個buffer來提高IO效率。在進行磁盤或網絡IO時,原始的InputStream對數據讀取的過程都是一個字節一個字節操作的,而BufferedInputStream在其內部提供了一個buffer,在讀數據時,會一次讀取一大塊數據到buffer中,這樣比單字節的操作效率要高的多,特別是進程磁盤IO和對大量數據進行讀寫的時候,能提升IO性能。

使用BufferedInputStream十分簡單,只要把普通的輸入流和BufferedInputStream組合到一起即可。我們把上面的例2改造成用BufferedInputStream進行讀文件,請看下面例子:

例10 ,用緩衝流讀文件

public static void readByBufferedInputStream() throws IOException {
     File file = new File( "d:/test.txt");
     byte[] byteArray = new byte[( int) file.length()];
     //可以在構造參數中傳入buffer大小
     InputStream is = new BufferedInputStream( new FileInputStream(file),2*1024);
     int size = is.read( byteArray);
     System. out.println( "大小:" + size + ";內容:" + new String(byteArray));
     is.close();
}

BufferedOutputStream的情況和BufferedInputStream一致,在這裏就不多做描述了。

copyFile

package com.chenhao.io.buffered;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
 * 字節流文件拷貝+緩衝流 ,提高性能
 * 緩衝流(節點流)
 * @author ChenHao
 *
 */
public class BufferedByteDemo {

    public static void main(String[] args) {
        String src ="E:/xp/test";
        String dest="e:/xp/test/4.jpg";
        try {
            copyFile(src,dest);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("文件不存在");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("拷貝文件失敗|關閉流失敗");
        }
    }
    /**
     * 文件的拷貝
     * @param  源文件路徑
     * @param  目錄文件路徑
     * @throws FileNotFoundException,IOException
     * @return 
     */
    public static void copyFile(String srcPath,String destPath) throws FileNotFoundException,IOException {
        //1、建立聯繫 源(存在且為文件) +目的地(文件可以不存在)  
        File src =new File(srcPath);
        File dest =new File(destPath);
        if(! src.isFile()){ //不是文件或者為null
            System.out.println("只能拷貝文件");
            throw new IOException("只能拷貝文件");
        }
        //2、選擇流
        InputStream is =new BufferedInputStream(new FileInputStream(src));
        OutputStream os =new BufferedOutputStream( new FileOutputStream(dest));
        //3、文件拷貝   循環+讀取+寫出
        byte[] flush =new byte[1024];
        int len =0;
        //讀取
        while(-1!=(len=is.read(flush))){
            //寫出
            os.write(flush, 0, len);
        }
        os.flush(); //強制刷出
        
        //關閉流
        os.close();
        is.close();
    }

}

Java IO:BufferedReader和BufferedWriter

BufferedReader、BufferedWriter 的作用基本和BufferedInputStream、BufferedOutputStream一致,具體用法和原理都差不多 ,只不過一個是面向字符流一個是面向字節流。同樣,我們將改造字符流中的例4,給其加上buffer功能,看例子:

public static void readByBufferedReader() throws IOException {
     File file = new File( "d:/test.txt");
     // 在字符流基礎上用buffer流包裝,也可以指定buffer的大小
     Reader reader = new BufferedReader( new FileReader(file),2*1024);
     char[] byteArray = new char[( int) file.length()];
     int size = reader.read( byteArray);
     System. out.println( "大小:" + size + ";內容:" + new String(byteArray));
     reader.close();
}

另外,BufferedReader提供一個readLine()可以方便地讀取一行,而FileInputStream和FileReader只能讀取一個字節或者一個字符,因此BufferedReader也被稱為行讀取器.

public static void keyIn() throws IOException {
 try (//InputStreamReader是從byte轉成char的橋樑
      InputStreamReader reader = new InputStreamReader(System.in);
      //BufferedReader(Reader in)是char類型輸入的包裝類
      BufferedReader br = new BufferedReader(reader);) {
         
         String line = null;
         while ((line = br.readLine()) != null) {
             if (line.equals("exit")) {
                 //System.exit(1);
                 break;
             }
             System.out.println(line);
         }
     } catch (IOException e) {
         e.printStackTrace();
     }
}

Java IO: 序列化與ObjectInputStream、ObjectOutputStream

推薦博客

  程序員寫代碼之外,如何再賺一份工資?

Serializable

如果你希望類能夠序列化和反序列化,必須實現Serializable接口,就像所展示的ObjectInputStream和ObjectOutputStream例子一樣。

ObjectInputStream

ObjectInputStream能夠讓你從輸入流中讀取Java對象,而不需要每次讀取一個字節。你可以把InputStream包裝到ObjectInputStream中,然後就可以從中讀取對象了。代碼如下:

ObjectInputStream input = new ObjectInputStream(new FileInputStream("object.data"));
MyClass object = (MyClass) input.readObject(); //etc.
input.close();

在這個例子中,你讀取的對象必須是MyClass的一個實例,並且必須事先通過ObjectOutputStream序列化到“object.data”文件中。

在你序列化和反序列化一個對象之前,該對象的類必須實現了java.io.Serializable接口。

ObjectOutputStream

ObjectOutputStream能夠讓你把對象寫入到輸出流中,而不需要每次寫入一個字節。你可以把OutputStream包裝到ObjectOutputStream中,然後就可以把對象寫入到該輸出流中了。代碼如下:

ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("object.data"));
MyClass object = new MyClass();  output.writeObject(object); //etc.
output.close();

例子中序列化的對象object現在可以從ObjectInputStream中讀取了。

同樣,在你序列化和反序列化一個對象之前,該對象的類必須實現了java.io.Serializable接口。

 

【精選推薦文章】

智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

帶您來看台北網站建置台北網頁設計,各種案例分享

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

我的產品/競品分析鍛煉記錄(分析產品核心)

  一來,以前剛入行的時候也想學習下競品分析/產品分析,然後好提高自身的分析能力,當時看了很多文章,然後看到大多都是學生寫的,分析的思路都是從用戶、核心流程,然後一直說到交互,但是整片文章偏重的是說某個小交互怎麼設計得不好,怎麼改進怎麼。

  二來,最近面試了一次,面試我的人應該也是挺教條主義的,面試過程我說了下競品分析,了解過市場行情,當時她追問,我就說下我的分析思路,我的分析思路很特別,只是分析產品核心、整體設計的優缺、預判產品的未來發展方向等,對於細節、業務流程等,一概不分析。

  三來想起來幾年前,那時候我還非常空閑,做了個100個APP分析挑戰,結果沒做完,尷尬。

  所以想整理下這篇,關於我對產品/競品分析的一些思路及想法,以供其他人參考。

 

1、產品經理究竟是負責什麼?

  必須要理清這個點,如果沒對產品經理的職責有清晰定位,很難做出比較適合的分析。為什麼這麼說呢?因為很多剛入行的人,要不從運營/業務入行,要不就技術/畫圖入行,只是了解業務或者功能設計,而不是真正、完整的產品管理。

  產品經理是要對一個產品的從頭到尾的管理,包括用戶了解、分析、業務設計、功能設計實施、運營推廣,從產品冷啟動到產品發展到產品退出市場,產品經理都需要負起帶頭的責任。這個是我理解的產品經理該需要承擔起來的責任。(這裏不展開說,不然這文章沒完沒了)

  基於這個概念,所以我作為一個產品經理,應該關注產品核心價值,因為核心價值才是讓這個產品獨立生存在市場上面,關注市場用戶的情況,而不是將關注點局限在一個小功能、小交互。所以才會有文章一開始說的,分析思路跟那些教科書的,有差異。

2、產品分析與競品分析的差異?

  在我的概念裏面,產品分析是偏重某個產品的的分析,偏重產品的核心價值、核心業務、核心設計。而競品分析偏重是在某個市場環境裏面,同類產品的核心價值差異。

  一個相對深入點,一個相對注重分析面,並且注重市場環境。

3、我的產品分析思路,要分析什麼?

  競品分析就不怎麼寫了,以前我也沒怎麼做過真正的競品分析,產品分析我也是只是分析核心的而已。

  我的方法很原始,就是作為一個用戶、作為一個產品設計者,兩種角色交替去對一個產品進行觀察、感受,寫出它的優缺而已。

  

下面截圖一下當時做的一些內容:

 

 

 

  從上面截圖可以看到當時我做這個鍛煉的目的及原始的一些思路,這個挑戰持續一年的,所以當時在自我學習過程裏面,開始逐漸完善我自身的分析。

  當然,這個是幾年前的分析,分析重點是一個產品的核心,沒有分析細節怎麼設計是好的,怎麼不好,只是純粹從小白的角度去嘗試,從如果我是這個產品的負責人的話,市場環境大概是那樣,我該如何去突破尋求發展?

 

如果說專業一點的競品分析文章,這裏介紹一篇超級詳細的競品分析文章,分析非常深入透徹,但是個人覺得價值不大!為什麼會這麼說呢?

  1、請問要分析一個行業的競品,單靠一個人,要像這位哥們分析到這麼深入,需要多少時間?一個月?一個季度?

  2、以前做產品分析的時候就發現一個問題,當你做完產品分析,產品已經發生改變,你所做的,都是歷史記錄的(當然有很重要的參考意義,這點無可厚非),花費那麼大的時間精力,是否值得?(跟隨是無法超越對方的,因為對方的創新永遠比你快,除非你的創新比它快,這樣要求你的團隊比對方要牛逼,要更清楚用戶需要)

 

  文章鏈接:https://www.zhihu.com/question/23601989/answer/91519343

  作者:大禹

 

       在後來的工作上面,針對這種專門競品/產品分析幾乎是沒有,可能我孤陋寡聞,但是貌似,沒見過有什麼企業,會做比較專門的競品/產品分析,因為做這些實在是耗費時間精力,但是做出來的時候,市場環境可能已經發生了改變了。

       而且當分析深度不夠深的話,還不如外包給專業的市場調研機構,他們會更專業,更有效率產出相對來說更準確的報告。而產品人員通過這些分析,可以拓寬自身眼界,鍛煉思考產品的核心。如果是這樣~~~好像也沒必要畫流程圖啊、寫交互優缺~~

       以上是我個人對產品經理、產品/競品分析的一些見解,純屬個人看法,如有更好的歡迎下面評論一起討論,研究下。

【精選推薦文章】

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

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

細談unity資源管理的設計

一、概要

本文主要說說Unity是如何管理的,基於何種方式,基於這種管理方式,又該如何規劃資源管理,以及構建bundle,是後面需要詳細討論的。

二、Unity的資源管理方式

2.1 資源分類

unity項目中的資源,大體上可以分為外部導入資源和內部生成資源兩種類型。
外部導入資源: 美術生成的大部分資源,都是外部帶入資源,模型,貼圖,UI用圖,基本是美術工具生成后,導入到工程中的。
內部生成資源: 部分美術生成資源,例如材質,shader,特效,場景等,屬於基於Unity引擎來製作生成的,此外各種prefab(UI/角色等),以及代碼腳本(c#為主),也屬於Unity的內部生成資源。

2.2 資源的存儲方式

在資源導入到unity工程后,會以各種方式進行轉換存儲,主要有以下幾種:

2.2.1 腳本類資源

對於工程中的腳本類資源,主要分為plugin和非plugin兩類。

  • plugin類:在plugin中引用的dll, 屬於自己生成相關的dll,在最終構建遊戲包的時候,被打入到相關遊戲包中:      
  • 非plugin類:unity會構建成4個基本的dll, 構建的順序為:
    • Assembly-CSharp-firstpass: standard assets/Pro standard assets/plugins 中的腳本
    • Assembly-CSharp-Editor-firstpass: editor scripts in standard assets/Pro standard assets/plugins 這個dll不會被打入到遊戲包中,屬於編輯器下特有的dll
    • Assembly-CSharp: all other scripts that not inside editor 主體遊戲邏輯的dll
    • Assembly-CSharp-Editor: all remaing scripts inside editor 這個dll也不會被打入到遊戲包中,編輯器中特有的dll

所有最終構建到遊戲包中的dll,主要分為:

  • Assembly-CSharp.dll/Assembly-CSharp-firstpass.dll 這2個主要遊戲邏輯dll
  • 引擎dll和插件引用的dll

2.2.2 美術類資源

美術類資源,分為外部導入和內部生成兩個大類

  • 外部導入類: 場景/模型/貼圖 都可以外部導入
    • 繼承自AssetPostprocesser后,可以對導入的貼圖,材質,模型,場景,均執行相關的修改
  • 內部生成類: shader/材質/prefab/場景 均可以內部生成美術資源的貼圖資源和特效資源,屬於重點關注對象,後面會細談這幾個資源的管理
    • 修改操作同上

2.2.3 meta文件

工程資源劃分好后,如何對這些資源進行管理? 不同的引擎有不同的管理方式,那麼unity中是如何管理的?
這兒管理分為2個步驟:序列化和meta文件的生成

2.2.3.1 unity的序列化

工程中的資源,要存儲到本地磁盤,那麼就會通過引擎進行一步序列化的操作,序列化的實質,就是將資源對象按照一定的順序轉換成二進制文件。

2.2.3.2 meta文件的生成

在完成序列化后,unity會對應的為該文件生成一份meta文件,這份meta文件會跟隨該文件一直存在,如果刪除該資源文件,其對應的meta文件也會被引擎自動刪除。
meta文件的主要構成:

  • 文件的guid: 這個文件的全工程中的唯一索引id,基於該id,可以對應的查找到該文件。guid的生成本質,就是基於文件的路徑來進行轉換生成的,同理,如果多個工程合併的時候出現guid衝突,可以自己重新生成一份guid,相關鏈接: https://gist.github.com/ZimM-LostPolygon/7e2f8a3e5a1be183ac19

  • 文件的導入設置:

    • 對於一般的文件,導入設置都比較簡單腳本類叫MonoImporter, 資源類叫NativeFormatImporter
    • 貼圖屬於需要重點關注的類型,其導入類型叫TextureImporter,裏面詳細的列出對該貼圖的各種壓縮格式,mipmaps, 類型,uv,貼圖大小等等詳細的設置信息

2.2.4 基於meta文件和序列化的資源管理

除了meta文件的guid,unity還會為每個資源生成一份文件id,也就是fileID, 不過現在fileID已經不再保留在meta文件中了,保留到文件的序列化文件中了,對於該資源,還會有一份localID, 這個localID, 對應的就是在一個資源中包含多個子資源的時候,定位每個子資源所用:  

那麼序列化是如何與guid/fileID關聯的?
在unity工程內部,如果給資源添加其他資源的引用,例如加一個腳本,拖拽一個外部引用,那麼就會觸發一次序列化操作,序列化操作的時候,就會將引用的資源的fileID和guid都序列化下來,這樣在反序列化的時候,就會基於fileID和guid來反向找到依賴的資源,從而加載進來。   

這個過程,在Unity中,就是一個裝載的過程,多說一句,如果一個資源依賴的其他資源越多,那麼這個裝載過程就會越耗時,所以在打開一個很大的UI的時候,有一部分的時間是消耗在裝載UI上各個組件上的。

三、總結

基於前文,可以對整個unity的資源管理有一個初步的認識,基於meta文件和序列化操作,可以管理工程中的資源,同時也能管理好各個資源的互相引用,那麼基於這樣的設計,在構建bundle的時候,是可以進行相關的設計和實現的。

【精選推薦文章】

智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

帶您來看台北網站建置台北網頁設計,各種案例分享

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

Spring 核心技術(1)

接上篇:Spring 框架概述

version 5.1.8.RELEASE

這部分參考文檔涵蓋了 Spring Framework 所有絕對不可或缺的技術。

其中最重要的是 Spring Framework 的控制反轉(IoC)容器。在介紹完 Spring 框架的 IoC 容器之後,緊接着全面介紹 Spring 的面向切面編程(AOP)技術。Spring Framework 有自己的 AOP 框架,它在概念上易於理解,並且成功地定位了 Java 企業編程中 AOP 需求的 80% 最佳擊球點。

Spring 提供與 AspectJ (目前功能最豐富,也是Java企業領域中最成熟的 AOP 實現)的集成。

1. IoC容器

本章介紹 Spring 的控制反轉(IoC)容器。

1.1 Spring IoC 容器和 Bean 簡介

本章介紹了 Spring Framework 控制反轉(IoC)的實現原理。IoC 也稱為依賴注入(DI)。通過這個機制,對象可以通過構造方法參數、工廠方法參數以及通過工廠方法構建或返回的實例上設置的屬性來定義它們的依賴關係(即它們使用的其他對象)。然後容器在創建 bean 時注入這些依賴項。這個過程從根本上反轉了 Bean 自身通過直接調用構造方法或服務定位模式等機制來控制實例化或定位其依賴的模式,因此叫做控制反轉。

org.springframework.beansorg.springframework.context 包是 Spring 框架的 IoC 容器的基礎。BeanFactory 接口提供了一種能夠管理任何類型對象的高級配置機制。ApplicationContext 是 BeanFactory 的子類。它補充的內容有:

  • 更容易與 Spring 的 AOP 功能集成
  • 消息資源處理(用於國際化)
  • 事件發布
  • 應用層特定的上下文,例如在 Web 應用程序中使用的 WebApplicationContext

簡而言之,BeanFactory 提供了配置框架和基本功能,ApplicationContext 添加了更多針對企業級的功能。ApplicationContextBeanFactory 完整的超集,在本章中僅用它描述 Spring IoC 容器。有關使用 BeanFactory 而不是 ApplicationContext的更多信息 請參考 BeanFactory。

在 Spring 中,構成應用程序架構並由 Spring IoC 容器管理的對象稱為 beans。bean 是一個由 Spring IoC 容器實例化、組裝或管理的對象。除此之外,bean 只是應用程序中眾多對象之一。Bean 及其之間的依賴關係反映在容器使用的配置元數據中。

1.2 容器概覽

org.springframework.context.ApplicationContext 接口代表 Spring IoC 容器,負責實例化、配置和組裝 bean。容器通過讀取配置元數據獲取有關需要實例化、配置和組裝對象的指令。配置元數據以 XML、Java 註解或 Java 代碼錶示,通過它可以表示構成應用的對象以及對象之間豐富的依賴關係。

Spring 提供了多種 ApplicationContext 接口實現。在傳統單機應用中,通常會創建一個 ClassPathXmlApplicationContextFileSystemXmlApplicationContext 的實例。雖然 XML 是定義配置元數據的傳統格式,但你也可以通過提供少量 XML 配置聲明容器啟用對其他元數據格式的支持后使用 Java 註解或代碼作為元數據格式。

在大多數應用程序方案中,不需要顯式使用代碼來實例化 Spring IoC 容器實例。例如,在 Web 應用程序場景中,應用程序文件 web.xml 中一個 8 行左右的 web 描述模板 XML 就足夠了(請參閱 Web 應用程序快速實例化 ApplicationContext)。如果你使用 Spring Tool Suite(一個基於 Eclipse 的開發環境),只需點擊幾下鼠標或按幾下鍵盤即可輕鬆創建此模板配置。

下圖是 Spring 工作原理的高級視圖。應用程序類與配置元數據相結合,在 ApplicationContext 創建並初始化之後,即可擁有完全配置且可執行的系統或應用程序。

1.2.1 配置元數據

如上圖所示,Spring IoC 容器使用一系列配置元數據。這些配置元數據描述了Spring 容器在應用程序中如何實例化,配置和組裝對象。

傳統配置元數據使用簡單直觀的 XML 格式,本章大部分內容也是用 XML 來表達 Spring IoC 容器的關鍵概念和功能。

XML 不是唯一的配置元數據格式。Spring IoC 容器與實際編寫配置元數據的格式完全解耦。目前,許多開發人員為其 Spring 應用程序選擇基於 Java 的配置。

有關在 Spring 容器中使用其他形式的元數據的信息,請參閱:

  • 基於註解的配置:Spring 2.5 引入了對基於註解的配置元數據的支持。
  • 基於Java的配置:從 Spring 3.0 開始,Spring JavaConfig 項目提供的許多功能成為 Spring Framework 核心的一部分。因此,你可以使用 Java 而不是 XML 文件來定義應用程序類外部的 bean。要使用這些新功能,請參閱 @Configuration@Bean@Import,和 @DependsOn 註解。

Spring 配置信息由至少一個(通常不止一個) 必須由容器進行管理的 bean 定義組成。基於 XML 的配置元數據將這些 bean 配置為頂級元素 <beans/> 內的 <bean/> 元素。基於 Java 的配置通常在使用 @Configuration 註解的類中使用帶有 @Bean 註解的方法。

這些 bean 定義對應構成應用程序的實際對象。我們一般會定義服務層對象,數據訪問對象(DAO),展示層對象(例如 Struts Action 實例),基礎結構對象(例如 Hibernate SessionFactories、JMS Queues 等)。一般不會在容器中配置細粒度的域對象,因為通常由 DAO 和業務邏輯負責創建和加載域對象。然而,你可以使用 Spring 集成 AspectJ 來配置非 IoC 容器創建的對象。請參閱使用 Spring 和 AspectJ 進行域對象的依賴注入。

以下示例显示了基於 XML 的配置元數據的基本結構:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="...">①②
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>

① id 屬性是一個標識單個 bean 定義的字符串

② class 屬性使用完整的類名定義 bean 的類型

id 屬性的值表示協作對象。在此示例中未包含用於引用協作的對象的 XML。有關更多信息,請參閱依賴。

1.2.2 實例化容器

提供給 ApplicationContext 構造函數的位置路徑是一個資源字符串,它允許容器從各種外部資源加載配置元數據,例如本地文件系統、Java 環境變量等。

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

在了解了 Spring 的 IoC 容器之後,你可能想要了解有關 Spring 資源抽象化(參考資源描述)的更多信息,特別是 Resource 路徑用於構建應用程序上下文(請參考應用程序上下文和資源路徑),它提供了一種便捷的機制從 URI 語句中定義的位置讀取 InputStream。。

以下示例展示了服務層對象配置文件(services.xml):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- services -->

    <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <property name="itemDao" ref="itemDao"/>
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for services go here -->

</beans>

以下示例展示了數據訪問對象文件(daos.xml):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="accountDao"
        class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for data access objects go here -->

</beans>

在前面的示例中,服務層由 PetStoreServiceImpl 類和兩個數據訪問對象 JpaAccountDaoJpaItemDao(基於 JPA 對象關係映射標準)組成。property 元素的 name 屬性指的是 JavaBean 屬性的名稱,ref 屬性指向另一個 bean 定義的名稱。元素 idref 之間的這種聯繫表達了協作對象之間的依賴關係。有關配置對象的依賴關係的詳細信息,請參閱依賴關係。

編寫基於XML的配置元數據

通常,每個單獨的 XML 配置文件都對應着架構中的邏輯層或模塊,讓 bean 定義在多個 XML 文件中生效會非常有用。

如上一節中所示,應用程序上下文構造函數可以使用多個 Resource 位置,它可以從這些 XML 片段中加載 bean 定義。另外也可以使用一個或多個 <import/> 元素從其他文件加載 bean 定義。以下示例展示了如何執行此操作:

<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

在前面的例子中,從三個文件中加載外部 Bean 定義,分別是 services.xml、messageSource.xml 和 themeSource.xml。對於執行導入的定義文件來說,所有路徑都是相對路徑,因此 services.xml 必須與執行導入的文件位於相同的目錄或環境變量, messageSource.xml 和 themeSource.xml 必須位於導入文件路徑下方的 resources 目錄中。正如你所見,前邊的斜杠會被忽略掉。鑒於提供的都是相對路徑,所以最好不要使用斜杠。這些文件中包括根據 Spring Schema 定義的正確的 XML Bean 在內的內容都會被導入,包括頂級元素 <beans/>

雖然可以使用相對路徑“../”引用父目錄中的文件,但不建議這樣使用,因為這樣做會使得當前應用依賴程序之外的文件。非常不建議使用 classpath:URL(例如,classpath:../services.xml)引用文件,因為運行時解析過程會選擇“最近”的環境變量根目錄,然後查找其父目錄。環境變量配置的更改可能導致目錄選擇不正確。

可以使用完整的資源位置替代相對路徑,例如,file:C:/config/services.xml 或 classpath:/config/services.xml。然而需要注意應用程序的配置將會與特定的絕對路徑耦合。通常最好為這些絕對路徑保持間接聯繫,例如通過在運行時通過“$ {…}”佔位符替代 JVM 系統屬性。

命名空間本身提供了導入指令的功能。Spring 提供的一系列 XML 命名空間中提供了除普通 bean 定義之外的其他配置功能,例如 context 和 util 命名空間。

Groovy Bean 定義 DSL

作為外化配置元數據的另一個示例,bean 定義也可以在 Spring 的 Groovy Bean 定義 DSL 中表示,就像 Grails 框架。通常此類配置位於“.groovy”文件中,其結構如下例所示:

beans {
    dataSource(BasicDataSource) {
        driverClassName = "org.hsqldb.jdbcDriver"
        url = "jdbc:hsqldb:mem:grailsDB"
        username = "sa"
        password = ""
        settings = [mynew:"setting"]
    }
    sessionFactory(SessionFactory) {
        dataSource = dataSource
    }
    myService(MyService) {
        nestedBean = { AnotherBean bean ->
            dataSource = dataSource
        }
    }
}

此配置樣式在很大程度上等同於 XML bean 定義,同樣支持 Spring 的 XML 配置命名空間。它還允許通過 importBeans 指令直接導入 XML bean 定義文件。

1.2.3 使用容器

ApplicationContext 是一個高級工廠接口,主要負責維護不同 bean 及其依賴項的註冊。通過使用 T getBean(String name, Class<T> requiredType) 方法可以獲得 Bean 的實例。

通過 ApplicationContext 可以讀取 bean 定義並訪問它們,如下例所示:

// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// use configured instance
List<String> userList = service.getUsernameList();

使用 Groovy 配置時,初始化程序看起來非常相似。不同的是使用了支持 Groovy 的上下文實現類(也支持 XML bean 定義)。以下示例展示了 Groovy 配置:

ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");

最靈活的使用方式是 GenericApplicationContext 與讀取器委派結合使用,例如針對 XML 文件使用 XmlBeanDefinitionReader,如以下示例所示:

GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml");
context.refresh();

還可以使用針對 Groovy 文件使用 GroovyBeanDefinitionReader ,如以下示例所示:

GenericApplicationContext context = new GenericApplicationContext();
new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy");
context.refresh();

你可以在相同的 ApplicationContext 中混合使用此類讀取器委託, 從不同的配置源讀取 bean 定義。

你可以使用 getBean 方法來獲取 Bean 實例。ApplicationContext 接口還有一些其他方法可以獲取 bean,但理想情況下你的應用程序不應該使用它們。實際上,你的應用程序代碼根本不應該調用 getBean()方法,也應該不依賴於 Spring API。例如,Spring 集成的 Web 框架為各種 Web 框架組件(如控制器和 JSF 託管的 bean)提供依賴注入,以便通過元數據聲明對特定 bean 的依賴關係,例如自動裝配註解。

  • 我的CSDN:https://blog.csdn.net/liweitao7610
  • 我的博客園:https://www.cnblogs.com/aotian/
  • 我的簡書:https://www.jianshu.com/u/6b6e162f1fdc

【精選推薦文章】

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

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

List集合去重方式及效率對比

List集合相信大家在開發過程中幾乎都會用到。有時候難免會遇到集合里的數據是重複的,需要進行去除。然而,去重方式有好幾種方式,你用的是哪種方式呢?去重方式效率是否是最高效、最優的呢?今天就給大家講解一下List集合去重的常見及常用的四種方式。

01

實現思路:使用兩個for循環遍歷集合所有元素,然後進行判斷是否有相同元素,如果有,則去除。這種方式是大部分最先想到的,也是最簡單的實現方式。其中,這種方式可以保證List集合原來的順序不變。

代碼實現:

/**
* notes:使用兩個for循環實現List去重
@param list
@return
*/
public static List repeatListWayOne(List<String> list){
   for(int i = 0;i < list.size();i++){
       for(int j = i+1;j < list.size();j++){
           if(list.get(i).equals(list.get(j))){
               list.remove(j);
           }
       }
   }
   return list;
}

 

02

實現思路:我們知道HashSet實現了Set接口,不允許出現重複元素。可以基於這個想法,把List集合所有元素存入HashSet對象,接着把List集合元素全部清空,最後把HashSet對象元素全部添加至List集合中,這樣就可以保證不出現重複元素。而HashSet有一個構造函數,在初始化時可以直接添加元素。其中,HashSet不能保證順序不變,所以此方式不能保證List集合原來的順序不變。

代碼實現:

/**
* notes:使用HashSet實現List去重
@param list
@return
*/
public static List repeatListWayTwo(List<String> list){
  //初始化HashSet對象,並把list對象元素賦值給HashSet對象
  HashSet set = new HashSet(list);
  //把List集合所有元素清空
  list.clear();
  //把HashSet對象添加至List集合
  list.addAll(set);
  return list;
}

 

03

實現思路:TreeSet集合也是實現Set接口,是一個有序的,並且無重複元素集合。同理,我們可以根據上面方式二的思想進行去重。其中,去重后的List集合可以保證和原來的順序一致。

代碼實現:

/**
* notes:使用TreeSet實現List去重
@param list
@return
*/
public static List repeatListWayThird(List<String> list){
   //初始化TreeSet對象,並把list對象元素賦值給TreeSet對象
   TreeSet set = new TreeSet(list);
   //把List集合所有元素清空
   list.clear();
   //把TreeSet對象添加至List集合
   list.addAll(set);
   return list;
}

 

04

實現思路:利用List集合contains方法循環遍歷,先創建新的List集合,接着循環遍歷原來的List集合,判斷新集合是否包含有舊集合,如果有,則不添加至新集合,否則添加。最後,把舊集合清空,把新集合元素賦值給舊集合。

代碼實現:

/**
* notes:利用List集合contains方法循環遍歷去重
@param list
@return
*/
public static List repeatListWayFourth(List<String> list){
   //新建新List集合,用於存放去重后的元素
   List<String> newList = new ArrayList<String>();
   //循環遍歷舊集合元素
   for(int i = 0; i < list.size(); i++ ){
       //判斷新集合是否包含有,如果不包含有,則存入新集合中
       boolean isContains = newList.contains(list.get(i));
       if(!isContains){
           newList.add(list.get(i));
       }
   }
   //把List集合所有元素清空
   list.clear();
   //把新集合元素添加至List集合
   list.addAll(newList);
   return list;
}

上面給大家介紹了四種List集合去重方式。那麼,哪種方式效率是最好的呢?下面就演示一下進行對比。

為了演示方式,隨機生成0-500之間的20000個整数字符串,並存入List集合,並在相應代碼打印相關時間進行對比。其中,隨機生成List集合代碼如下:

/**
* 隨機生成0-500之間的20000個整数字符串,並存入List集合
@return
*/
public static List<String> getRandomList(){
   List<String> list = new ArrayList<String>();
   //隨機生成20000個整数字符串
   for(int i = 1; i <= 20000; i++){
       //任意取[0,500)之間整數,其中0可以取到,500取不到
       int number = new Random().nextInt(500);
       String number_str = "geshan"+number;
       list.add(number_str);
   }
   return list;
}

為了保證List集合元素一致,創建四個List集合,分別對應List去重方式。效率對比代碼如下:

public static void main(String[] args){
   //隨機生成0-500之間的1000個整数字符串List集合
   List<String> list = getRandomList();

   //為了演示四種方式效率,創建四個List集合,保證List集合元素一致
   //方式一List集合
   List<String> oneList = new ArrayList<>();
   oneList.addAll(list);
   //方式二List集合
   List<String> twoList = new ArrayList<>();
   twoList.addAll(list);
   //方式三List集合
   List<String> thirdList = new ArrayList<>();
   thirdList.addAll(list);
   //方式四List集合
   List<String> fourthList = new ArrayList<>();
   fourthList.addAll(list);

   System.out.println("方式一:使用兩個for循環實現List去重");
   System.out.println("原來集合大小:"+oneList.size()+",集合元素>>"+oneList);
   Date oneDateBegin = new Date();
   repeatListWayOne(oneList);
   System.out.println("集合去重大小:"+oneList.size()+",集合元素>>"+oneList);
   Date oneDateEnd = new Date();
   System.out.println("去重所需時間:"+(oneDateEnd.getTime()-oneDateBegin.getTime())+"毫秒");

   System.out.println("方式二:使用HashSet實現List去重");
   System.out.println("原來集合大小:"+twoList.size()+",集合元素>>"+twoList);
   Date twoDateBegin = new Date();
   repeatListWayTwo(twoList);
   System.out.println("集合去重大小:"+twoList.size()+",集合元素>>"+twoList);
   Date twoDateEnd = new Date();
   System.out.println("去重所需時間:"+(twoDateEnd.getTime()-twoDateBegin.getTime())+"毫秒");

   System.out.println("方式三:使用TreeSet實現List去重");
   System.out.println("原來集合大小:"+thirdList.size()+",集合元素>>"+thirdList);
   Date thirdDateBegin = new Date();
   repeatListWayThird(thirdList);
   System.out.println("集合去重大小:"+thirdList.size()+",集合元素>>"+thirdList);
   Date thirdDateEnd = new Date();
   System.out.println("去重所需時間:"+(thirdDateEnd.getTime()-thirdDateBegin.getTime())+"毫秒");

   System.out.println("方式四:利用List集合contains方法循環遍歷去重");
   System.out.println("原來集合大小:"+fourthList.size()+",集合元素>>"+fourthList);
   Date fourthDateBegin = new Date();
   repeatListWayFourth(fourthList);
   System.out.println("集合去重大小:"+fourthList.size()+",集合元素>>"+fourthList);
   Date fourthDateEnd = new Date();
   System.out.println("去重所需時間:"+(fourthDateEnd.getTime()-fourthDateBegin.getTime())+"毫秒");
}

多次運行結果如下:

第一次四種方式運行時間如下:223、10、16、30;

第二次四種方式運行時間如下:164、10、17、43;

第三次四種方式運行時間如下:164、9、16、37;

綜合代碼及運行時間對比,方式二是最好的去重方式,代碼最簡潔、耗時最短。你平時List集合去重,方式用對了嗎?

【精選推薦文章】

智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

帶您來看台北網站建置台北網頁設計,各種案例分享

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

ASC19最新戰況:北航打破HPL基準測試賽會紀錄!

ASC19最新戰況:北航打破HPL基準測試賽會紀錄!

2019-04-23 23:32    原創  作者: 謝濤 編輯:
0購買

  【IT168現場報道】今天(4月23日)是全球矚目的ASC19全球總決賽第三天,經過前两天的系統搭建與調試工作后,20支隊伍進入了正式競賽階段,向總冠軍寶座發起最後衝刺。

  根據賽程,今天所有參賽隊伍需要完成的項目包括超級計算機性能基準測試HPL&HPCG、超級團隊對抗賽賽題Fluidity以及全球氣候變化模式CESM——其中,CESM是今年“e Prize計算挑戰獎”的指定賽題。

  上午十二時左右,組委會公布了第一項賽題HPL的成績,在3000瓦功耗約束下,北京航空航天大學代表隊以每秒50.21萬億次浮點運算的成績打破了賽會紀錄,在HPL賽題單項成績上排名第一。

  HPL是國際通用的超級計算機浮點性能基準測試程序,是全球超算TOP500榜單評比的重要依據,主要考察參賽隊伍對硬件平台的浮點計算性能優化能力。ASC競賽的HPL計算性能測試有嚴格的規定,各參賽隊伍需要在功耗不高於3000W的約束下,採用組委會統一提供的超算節點、高速網絡和自行配置加速卡等設備,完成超算系統搭建。

  HPL測試側重於系統的整體運行能力和峰值性能,這個項目考察參賽隊伍在搭建系統、性能優化和配置選擇上的綜合能力。為了取得更好的成績,參賽隊伍需要從超算系統體繫結構、多級存儲一致性、高速網絡、算法優化等不同角度,進行全方位的深入研究,在不同方案之間進行抉擇,通過反覆優化和測試獲得更高的運算性能。

  在這一項目上,歷屆ASC大賽總能給我們帶來驚喜,充分體現了“百尺竿頭,更進一步”的積極進取精神。ASC15,來自新加坡的南洋理工大學以11.92萬億次浮點運算/秒的成績打破上一年的紀錄;ASC16,該紀錄被浙江大學以12.03萬億次浮點運算/秒的成績刷新;ASC17,濰坊學院代表隊創下31.7萬億次浮點運算/秒的新紀錄;ASC18,也就是去年,台灣清華大學獲得42.99萬億次浮點運算/秒的成績,再次刷新紀錄。

  今年,北京航空航天大學則以50.21萬億次/秒的驚人成績又一次打破賽會紀錄,在現場引起一片呼聲。該代表隊設計了“3機12卡”的異構超算系統,共採用3台浪潮AI超算服務器NF5280M5配置12塊NVIDIA Tesla系列V100加速卡。值得一提的是,北京航空航天大學在預賽期間就曾獲得了第一名的好成績。

  根據ASC19競賽組委會的介紹,明天(4月24日)將公布正式競賽第一天其餘賽題的成績,包括HPCG、Fluidity、CESM。此外,參賽隊伍還將完成人工智能賽題人臉圖像超分辨率(Face SR)、中國科學家研發的第三代基因測序組裝軟件wtdbg以及一個神秘應用賽題。

  在這些賽題上,各位參賽隊伍又將給我們帶來哪些驚喜呢?大家一起期待明天的結果吧!

  4月24日下午,第21屆國際超算高峰論壇將在大連理工大學隆重舉行。全球超級計算機排行榜TOP500提出人、ASC競賽專家委員會主席、田納西大學傑出教授Jack Dongarra,憶阻器提出人加州大學伯克利分校教授Leon Chua(蔡少棠)等多位知名國際國內專家將出席並進行主題報告與分享,與參會嘉賓就超算話題展開思想碰撞。

  IT168將對本次大賽進行全程報道,了解大賽更多信息,請持續關注:http://zt.itpub.net/topic/ASC19/

, ,

網站內容來源http://server.it168.com/本站聲明:網站內容來源http://www.it168.com/,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

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

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

采埃孚coPILOT助力提升安全性與駕駛舒適性

采埃孚coPILOT助力提升安全性與駕駛舒適性

2019-04-24 11:46    原創  作者: 陶然 編輯:
0購買

  近日,采埃孚宣布推出采埃孚coPILOT智能高級駕駛輔助系統(ADAS),助力提升安全性和駕駛舒適性。藉助AI的強大功能同時配備全面的傳感器組,車輛能夠執行各類自動駕駛功能。在高速公路行駛時,該輔助系統的功能尤為突出。此外,采埃孚coPILOT可通過語音指令進行操作,識別交通狀況,感知車輛操控並監控駕駛員,並且能夠通過主動控制干預來幫助預防危險情況發生。采埃孚coPILOT基於采埃孚ProAI中央計算機和NVIDIA DRIVE平台,專為量產而設計,預計將於2021年開始供貨。

  距離采埃孚和NVIDIA宣布“采埃孚ProAI成為首個運行NVIDIA DRIVE軟件的系統”僅三個月後,采埃孚coPILOT就在上海國際汽車工業展覽會上首次亮相。兩家高科技公司共同推出這一極具吸引力的 “L2+級”自動駕駛輔助系統,可提高乘用車的安全性和駕駛舒適性。

  采埃孚先期開發工程部門負責人兼采埃孚風險投資公司(Zukunft Ventures GmbH)總經理TorstenGollewski表示:“采埃孚coPILOT配備了人工智能、360度全方位傳感器組、功能強大的采埃孚ProAI中央計算機以及NVIDIA DRIVE平台,可實現高於常規L2級系統的駕駛和安全功能。這使我們能夠實現更高性能的半自動駕駛。”

  采埃孚coPILOT演示車將在上海車展首次亮相,詳細展示其功能範圍以及其為駕駛員所提供的舒適性與安全性:車輛可自主執行特定的駕駛操作,例如在適當情況下進出高速公路。對於相對輕鬆的高速公路駕駛,采埃孚coPILOT將先進的巡航控制系統與主動轉向輔助功能和車道保持輔助功能相結合。此外,采埃孚coPILOT能夠主動變道、穿行和並道,還能持續分析車輛周圍環境,識別行人、對面車輛和交叉路口。

  采埃孚coPILOT配備了相應的傳感器和功能,能夠監控駕駛員並在發生潛在危險情況時觸發警告。例如,當發生駕駛員注意力不集中、幾乎完全未將注意力放在路面交通上或显示出瞌睡跡象等狀況時,警告將會被觸發。此外,采埃孚coPILOT還能夠進行智能路線引導,包括“MyRoute”這一能夠識別重複路線的地圖功能。該系統還配備了語音識別功能,駕駛員能夠通過語音指令便捷地啟用並操作駕駛員輔助功能;在駕駛員想要手動駕駛時,也可以通過語音指令對其禁用。

  在演示車輛中,搭載的采埃孚傳感器組包括一個前置雷達、四個角雷達以及八個攝像頭。其中,兩個攝像頭向前,一個向後,還有兩個分別集成在兩個側鏡中,一個負責監控駕駛員。

  為評估整套傳感器組實時收集的大量數據,高性能處理能力必不可少。這正是采埃孚coPILOT所採用的第二代采埃孚ProAI中央計算機的用武之地:以NVIDIA DRIVE Xavier處理器的高性能、高能效計算能力為核心,采埃孚ProAI可集成並完全控制預訓練算法,實現所有駕駛員輔助功能。該系統具有靈活性、可擴展性且能夠無縫更新。汽車製造商還可以根據需求添加自主開發或采埃孚開發的其他特性和功能。

  采埃孚ProAI產品系列包括從L0級到L5級的四種型號,覆蓋了整個自動駕駛運行範圍。高端型號采埃孚ProAIRoboThink每秒運行速度高達600萬億次(600 teraOPS),是目前移動出行領域功能最強大的AI超級計算機。

  高級駕駛員輔助 隨時隨地,隨您所需

  SAE L3級高度自動駕駛在許多國家和地區暫未被允許,因此采埃孚coPILOT提供SAE L2級半自動駕駛,要求駕駛員持續監控交通狀況。但采埃孚和NVIDIA所提供的L2+級技術更加強大,能夠起到可靠且便利的輔助駕駛作用,如同“私人駕駛助手”一般為駕駛員提供支持。

  “我們相信,像采埃孚coPILOT這樣的擴展型L2+級系統對製造商來說非常具有吸引力:鑒於其廣泛的功能,它在安全性和駕駛舒適性方面為消費者提供了明顯的附加值,且在價格方面也很具有競爭力,”TorstenGollewski如是說。

網站內容來源http://server.it168.com/本站聲明:網站內容來源http://www.it168.com/,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

帶您來看台北網站建置台北網頁設計,各種案例分享

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

冠軍倒計時:參賽隊員眼中的ASC19

冠軍倒計時:參賽隊員眼中的ASC19

2019-04-24 20:34    原創  作者: 謝濤 編輯:
0購買

  【IT168 現場報道】4月24日,ASC19全球總決賽第四天。經過緊張的两天系統搭建與調試后,來自全球各大高校的百位新生代“超算之星”們,將在明天迎來他們最後的答案。

  在這段時間里,這些熱愛超算技術的大學生們在七大賽題上同台競技、各展風采,也在超級團隊對抗賽中與其他隊伍積極交流、通力合作,共同完成超級賽題。既磨練了自己的專業技能,也與更多志同道合的同學建立了親密聯繫。無論成績好壞,他們都已經在ASC舞台上完成了對自我的挑戰,向更高的未來走去。

  

參賽學生接受採訪

  ASC世界大學生超級計算機競賽是由中國發起的世界最大規模的大學生超算競賽,從2012年至今,已為全球超過1400支參賽隊伍、超過7000 名年輕人才搭建了一個展現自我,相互交流的平台,推動了各國、各地區超算人才培養,以及行業應用與技術研發能力的提升。

  按照大賽規則,20支進入全球總決賽的參賽隊伍,在完成前期的競賽系統搭建與調試后,需要在两天時間內完成超級計算機性能基準測試HPL&HPCG、超級團隊對抗賽賽題Fluidity、全球氣候變化模式CESM、人工智能賽題人臉圖像超分辨率(Face SR)、中國科學家研發的第三代基因測序組裝軟件wtdbg以及一個神秘應用賽題。

  每支參賽隊伍的最終成績將根據HPL、HPCG、CESM、Face SR、wtdbg以及神秘賽題的單項成績進行綜合評定,而超級團隊對抗賽則單獨設置了獎項,不計入最終結果。雖然目前ASC19競賽組委會已公布了HPL、HPCG、CESM的成績,但冠軍最後將花落誰家仍然難以預測——如我們所見,單項賽題的成績並不能代表最終成績。

  今年首次設置的超級團隊對抗賽的結果也已經出爐,中山大學、太原理工大學、香港中文大學、德國埃爾朗根-紐倫堡大學組成的團隊最終獲得了“超級團隊獎”,這四支隊伍將平分總計2萬元的獎金。獎勵只是一方面,更重要的是參賽隊員們與來自其他國家、地區、高校的同學們在完成挑戰賽題的過程中,進行了積極踴躍的溝通,彼此學習、共同提高。

  作為世界最大規模的大學生超算競賽,ASC面向前沿技術領域,無論是近幾年加入的AI賽題,還是今年首次設置的超級團隊對抗賽,大賽每年在賽題設置上都會給人帶來新的驚喜。許多參賽學生都表示,有機會使用行業領先的計算硬件親自動手設計、搭建一台超級計算機,完成極具挑戰性的前沿應用賽題,對他們來說是一個非常寶貴的經驗。

  而同學們在競賽中展現出的進取精神也同樣讓人備受感染,他們在競賽中取得的優秀成績令人驚嘆,在他們身上,我們看到了超算行業的廣闊前景與光明未來。隨着超級計算機從科研、氣象等領域向互聯網、製造等更多行業普及應用,超算已成為驅動科技與產業創新的重要力量。在這之中,超算人才的培養是重中之重,ASC競賽以全球化的影響力,獲得了社會各界的認可。

  明天(4月25日)下午,ASC19總決賽閉幕式暨頒獎儀式將隆重舉行,這些辛苦了四天的參賽隊員們,將迎來屬於他們的高光時刻。

  點擊進入IT168的ASC19賽事報道專區,即可在線觀看閉幕式現場視頻直播。

,

網站內容來源http://server.it168.com/本站聲明:網站內容來源http://www.it168.com/,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

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

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

ASC19世界超算大賽:8分鐘全程亮點回顧

ASC19世界超算大賽:8分鐘全程亮點回顧

2019-04-25 16:45    來源:廠商稿  作者: 張靜 編輯:
0購買

ASC19世界超算大賽落幕,兩岸清華分獲冠亞軍。8分鐘全程亮點回顧,看超算青年決戰大連理工賽場。

本站聲明:網站內容來源http://www.it168.com/,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

帶您來看台北網站建置台北網頁設計,各種案例分享

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