記錄java一些東西

1.調用泛型方法

public static void main(String[] args) {
    String[] s1 = {"1", "3", "5"};
    test.<String>print(s1);
}

public static <T> void print(T[] data) {
    for (int i = 0; i < data.length; i++) {
        System.out.println(data[i]);
    }
}

使用.<類型>函數方法的方式調用泛型方法,而此<類型>是可以省略的。

2.泛型類型的定義

  1. 定義類為泛型類型,需要將泛型類型放在類的后面 如public class test<T>
  2. 定義方法為泛型類型,需要將泛型類型寫在方法返回類型的前面。如public static <T> void print(T[] data)

3.泛型通配符

為了避免上面的問題,我們使用通配符來解決。

通配符的三種形式

  1. ? 非限制通配符,和? extends object一樣
  2. ? extends T 上限通配,也就是必須是T的子類型(包含T)
  3. ? supter T 下限通配,也就是必須是T的父類型(包含T)

4.類型擦除

java中的泛型使用的是類型擦除的方法實現的。泛型只存在于編譯階段,而在運行階段是不存在泛型類型的,一旦編譯器在編譯時期檢測類型是安全的,就會將它轉換為原始類型。

下面是編譯完成后的.class運行時文件:

img

也就是說在運行時是沒有泛型這一概念的,泛型只在編譯期用于檢測類型安全。

為什么new E()是錯誤的?

java中,不能直接創建泛型的對象,因為創建對象是在運行時動態創建的,而運行時是沒有泛型類型的。

5.泛型的幾種常見的限制

  1. 不能使用new E(),也就是不能創建泛型對象
  2. 不能使用new E[],也就是不能創建泛型數組
  3. 靜態方法不能使用類的泛型類型作用參數
  4. 異常類不能是泛型的

6.Collections

1.Collections.nCopies

使用此方法可以創建指定對象的n個副本的不可變list。此方法接收一個對象,并接收一個int count的參數來指定要創建幾個該對象的副本。也就是說,此list中會有n個該對象的副本,而且此list是不可變的,也就是不進對該list進行修改的操作。否則,會報錯:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(AbstractList.java:148)
    at java.util.AbstractList.add(AbstractList.java:108)
    at generic.test.main(test.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

2.Collections.fill

表示用指定元素填充(覆蓋)原集合中的所有元素。

    List<Integer> mDatas = new ArrayList<>();
    mDatas.add(1);
    mDatas.add(2);
    mDatas.add(3);
    Collections.fill(mDatas, 4);

打印結果為4 4 4

3.使用Collections建立單元素和不可變的集合和map

圖片

7.Map類型及作用

常用的Map類有hashMaplinkedHashMapTreeMap。

  1. 如果更新map時不需要保持元素的順序,就用HashMap
  2. 如果需要按插入時間或最后訪問時間來排序,就用LinkedHashMap
  3. 如果需要按鍵來進行排序,就使用TreeMap

TreeMap例子

對一段字符串進行分割,然后統計每個被分割部分的單詞出現的次數,并按字母的自然順序進行排序。

圖片

8.算法時間復雜度的計算

在計算算法的時間復雜度時,我們主要看算法時間的增加,主要是由哪個變量引起的,就取此值,寫法為O(值)。比如:

img

下面是關于指數級的時間復雜度的計算:


img

各時間復雜度的對比關系:


img

9.優化的求最大公約數的算法

private static int getMaxGCD(int m, int n) {
        int gcd = 1;
        if (m % n == 0) {
            return n;
        }
        for (int i = n / 2; i >= 1; i--) {
            if (m % i == 0 && n % i == 0) {
                gcd = i;
                break;
            }
        }
        return gcd;
    }

最優化的方法:

private static int getMaxGCD(int m, int n) {
        if (m % n == 0) {
            return n;
        }
        return getMaxGCD(n, m % n);
    }

10.StringTokenizer的用法

StringTokenizer的作用主要是根據指定的分割符將字符串分割成n部分,然后通過hasMoreToken來判斷是否還有下一個被分割的部分,nextToken的方法來獲取對應的數據。

    StringTokenizer stringTokenizer = new StringTokenizer("www.baidu.com", ".a", true);
    while (stringTokenizer.hasMoreTokens()) {
        System.out.println("token:" + stringTokenizer.nextToken());
    }

上面的參數二,表示按.或者a來對字符串進行分割,也就是遇到.或者a就進行分割,默認本身不被算作分割的部分。
參數三,表示將本身也算作分割的一部分。

上面的結果為:

token:www
token:.
token:b
token:a
token:idu
token:.
token:com

11.二叉查找樹

二叉查找樹的特征:對于樹中的每一個節點,它的左子樹中的節點都是小于當前節點的值的;而它的右子樹中的節點都是大于當前節點的值的。

判斷是否包含某個元素

在二叉樹中添加一個元素

img

在二叉樹中添加一個元素,有兩種情況:

  1. 二叉樹中已經存在此元素,會直接丟棄要插入的元素
  2. 將元素添加到某個葉子節點的下一層,也就是最底層。

從上面的代碼示例子,可以得知,當current為null,也就是while循環結束后,就是添加元素所要插入的位置了。通過此元素創建新節點,然后與parent的值進行比較,大于就添加到右邊,小于就添加到左邊。

中序遍歷

遞歸地先遍歷左子樹,然后訪問當前節點,最后右子樹。中序遍歷法以遞增順序顯示BST中的所有節點。

img

后序遍歷

首先遞歸地遍歷左子樹,然后遞歸地遍歷右子樹,最后訪問該節點本身。


img

前序遍歷

首先遞歸訪問當前節點,然后遞歸地訪問該節點的左子樹,最后遞歸地訪問該節點的右子樹。


廣度優先遍歷

逐層訪問樹中的節點。首先訪問根節點,然后從左往右訪問根節點的孩子節點,然后再從左住右的訪問根節點的所有孫子節點,以此類推。

廣度優先遍歷主要是從層級關系出發,一層一層的對樹進行遍歷。

12.圖

1.圖的說明

圖由頂點和邊組成,分為有向圖和無向圖。

2.圖的表示

圖一般由兩種常用的方式來表示,一種是鄰接矩陣(也就是二維數組);另一種是鄰接線性表(鏈表).一般根據圖的情況(邊的多少),來決定使用哪種表示方式:

  1. 如果邊比較多,一般使用鄰接矩陣。
  2. 如果邊比較少,一般使用鄰接線性表。
  3. 由于鄰接矩陣會占用大量的存儲空間,一般建議使用鄰接純線性表。

3.圖的遍歷

  1. 深度優先搜索
  2. 廣度優先搜索

13.多線程

1.新建的線程什么時候會被關閉

run方法中的代碼都執行完畢后,就會被終止。

2.直接調用run方法和start的區別

直接調用run方法,任務會在當前線程上運行,而不是新創建一個線程。

3.使用Runnable,而不直接使用Thread來創建并執行任務的好處

使用Runnable的好處就是把任務和運行任務進行了解耦,更方便復用。

4.yield

讓cpu為其它線程臨時讓出cpu執行時間,并且只能讓同優先級及以上線程有執行機會。

5.sleep

暫停執行一段時間,以給其它線程運行機會,不會考慮線程的優先級。會拋出interruptedException異常,如果線程在sleep狀態下被調用interrupt方法(也就是終止),就會拋出此異常。

synchronized代碼執行中,不會釋放對象鎖。

6.sleep和yield的區別

  1. sleep方法給其它線程運行機會時不會考慮線程的優先級,而yield只會給同級別或者更高級別以運行機會。
  2. 線程執行sleep方法后會轉入阻塞狀態,而調用yield方法后,會進入就緒狀態。
  3. sleep方法聲明拋出InterruptedException異常,而yield沒有聲明任何異常
  4. sleep方法比yield方法有更好的可移植性。(在操作系統調度方面)

7.wait

讓線程讓出cpu執行機會,一旦調用了wait方法后,只能通過notify或者notifyAll來喚醒該線程。也會拋出InterruptedException異常。調用wait后線程處于掛起狀態。

如果某個線程獲得了對象鎖,在調用了wait方法后,會釋放該對象鎖。

同時調用wait之前,該線程必須要獲得線程鎖,否則會拋出IllegalMonitorStateException異常。

8.wait和sleep的區別

  1. wait只能在同步方法或者同步代碼塊中被調用,因為需要獲取對象鎖,否則會拋出IllegalMonitorStateException異常,而sleep可以在任何地方被調用。
  2. wait屬于object的方法,而sleepThread的方法
  3. 在同步代碼中執行時,sleep不會釋放線程鎖,而wait會釋放線程鎖。
  4. 執行wait后,線程進入掛起狀態,只能通過notify或者notifyAll才能被喚醒,而sleep被調用后,會進入阻塞狀態,睡眠時間一過,就會被自動喚醒。

9.join

join的作用是:使一個線程等待另一個線程的結果后再開始執行。

10.setPriority

使用該方法可以設置線程的優先級。

11:線程池

Executorjava中的一個線程池類。一般我們通過靜態方法來創建線程池。也可以通過ThreadPoolExecutor類來創建一個自定義的線程池。

  1. Executors.newFixedThreadPool(int i)

創建固定線程數量的線程池,處于線程池中的線程不會被關閉,除非調用interrupt方法將其終止。

2.Executors.newCachedThreadPool()

此線程池為緩存可伸縮的非常靈活的線程池。當有大量任務需要執行時,該線程池會為任務創建新的線程,可創建線程的數量取決于JVM可創建的最大線程大小。

而當任務執行完畢后,線程處于空閑狀態后60s,會將此線程進行回收。

3.Executors.newSingleThreadExecutor()

創建一個單線程的線程池,這個線程池只有一個線程在工作,也就是相當于單線程串行執行所有任務。

4.Executors.newScheduledThreadPool()

創建一個大小無限的線程池,此線程池支持定時或周期性執行任務的需求。

    //執行線程池大小
    ScheduledExecutorService service = Executors.newScheduledThreadPool(10);

    long initialDelay1 = 1;
    long period1 = 1;
    // 從現在開始1秒鐘之后,每隔1秒鐘執行一次job1
    service.scheduleAtFixedRate(
            new ScheduledExecutorTest("job1"), initialDelay1,
            period1, TimeUnit.SECONDS);

5.Executor.shutdown和shutdown的區別

shutdown調用后,不可以再submit新的task,已經submit的將繼續執行。

shutdownNow試圖停止當前正執行的task,并返回尚未執行的task的list

6.不帶緩沖區的生產者/消費者的示例

1.depositTask代碼(存錢的任務)

    public class DepositTask implements Runnable {
    private Acount mAcount;

    public DepositTask(Acount acount) {
        this.mAcount = acount;
    }

    @Override
    public void run() {
        while (true) {
            try {
                mAcount.deposit((int) (Math.random() * 10 + 1));
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2.WithDrawTask(取錢的任務)

public class WithDrawTask implements Runnable {
    private Acount mAcount;

    public WithDrawTask(Acount acount) {
        this.mAcount = acount;
    }

    @Override
    public void run() {
        mAcount.withDraw((int) (Math.random() * 10 + 1));
    }
}

3.Accout(帳戶)

public class Acount {
    private int balance;
    private static Lock lock = new ReentrantLock();
    private static Condition mCondition = lock.newCondition();


    public void deposit(int amount) {
        lock.lock();
        try {
            balance += amount;
            System.out.println("deposit:" + balance);
            mCondition.signalAll();
        } catch (Exception e) {
        } finally {
            lock.unlock();
        }
    }

    public void withDraw(int amount) {
        lock.lock();
        try {
            while (amount > balance) {
                System.out.println("withDraw: wait.....");
                mCondition.await();
            }
            balance -= amount;
            System.out.println("withdraw:" + amount + "======balance:" + balance);
        } catch (Exception e) {
        } finally {
            lock.unlock();
        }
    }
}

4.測試類

public class test {
    private static Acount acount = new Acount();

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(2);
        service.execute(new DepositTask(acount));
        service.execute(new WithDrawTask(acount));
        service.shutdown();
    }
}

12。 concurrent包

1.BlockingQueue

BlockingQueue(阻塞隊列):是一個依賴生產者/消費者模型來設計的,主要通過put(添加)和take(取出)來模擬生產者和消費者。事實上,使用其它方法添加和刪除時,當隊列為空或者已滿的情況下,是會拋出異常的。

ArrayBlockingQueue(數組阻塞隊列)

此隊列是一個FIFO的有界隊列,有界是說明它的大小是有限的,必須給其設置一個值。

DelayQueue(延遲隊列)

此隊列主要是延遲處理隊列中的元素,可以為中的元素設置一個過期時間,當使用take去取數據時,如果過了過期時間,可以馬上取出數據,如果還沒到過期時間,則等待到達過期時間后才能取出該數據。

在使用此隊列時,需要添加的元素實現Delayd接口。

class DelayedElement implements Delayed {
    private final long delay;

    private final long expire;

    public DelayedElement(long delay) {
        this.delay = delay;
        expire = Calendar.getInstance().getTimeInMillis() + delay;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return expire - Calendar.getInstance().getTimeInMillis();
    }

    @Override
    public int compareTo(Delayed o) {
        return (int) (this.delay - o.getDelay(TimeUnit.MILLISECONDS));
    }

    @Override
    public String toString() {
        return "DelayedElement is " + delay + "\n" + Calendar.getInstance().getTime().toString() + "\n elapsed time is " + getDelay(TimeUnit.DAYS);

    }
}

這樣子看起來,好像這個對象并沒有做什么其它的操作,只是在判斷當前對象是否超時,而沒有具體的東西。你可以在構造方法中加入具體的業務對象來與此延遲對象來進行綁定。

LinkedBlockingQueue(鏈式阻塞隊列)

LinkedBlockingQueue是一個FIFO鏈式結構的隊列,可以指定隊列的最大值,默認為Integer.maxValue().

PriorityBlockingQueue(優先級阻塞隊列)

PriorityBlockingQueue(優先級隊列)是一個無界的并發隊列。添加到隊列中的元素必須實現Comparable接口(讓其進行排序)

SynchronousQueue(同步隊列)

SynchronousQueue(同步隊列):隊列中只能有一個元素,當存在一個元素后,添加操作會進入阻塞,此時的操作應該是取出此單個元素,取出元素后,取出的操作就會被阻塞,而等待添加新的元素,依此循環。

blockingDeque(阻塞雙端隊列接口)

blockingDeque(阻塞雙端隊列):表示可以從任意一端插入數據或者取出數據。當隊列滿時,插入操作會進入阻塞,而當隊列為空時,取出數據會進入阻塞狀態。通過addFirst/addLast以及removeFirst/removeLast.此接口的唯一實現類為LinkedBlockingDeque

LinkedBlockingDeque(鏈式阻塞雙端隊列)

由鏈表組成的雙端可讀寫的阻塞式隊列。

2.信號量

信號量可以用來訪問共享資源的線程數,線程必須從信號量中獲取許可,訪問完資源后,這個線程需要把許可返回給信號量。

img

3.死鎖以及避免死鎖的方法

img
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容