JAVA編程

@TOCjava

JAVA

簡歷:技術(10W)+ 項目(20W)+ 算法(30W) + 業務(50~100W) + 行業視野(上不封頂)正則表達式

①JavaSE

JAVA背景知識

JDK安裝和配置

程序的運行機制
  • Java語言是編譯型和解釋型的結合

image.png

  • JVM(Java Virtual Machine):它定義了指令集、寄存器集、結構棧、垃圾收集堆、內存區域,負責java字節碼解釋運行,邊解釋邊運行,一次編譯隨處運行。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-tPyAuFO8-1615480452506)(C:\Users\UC241027\AppData\Roaming\Typora\typora-user-images\image-20210310171254229.png)]

  • JRE(Java Runtime Environment):Java虛擬機、庫函數、運行Java應用程序必須的文件。
  • JDK(Java Development Kit):包含JRE,以及增長編譯器和調試器等用於程序開發的文件。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-KvO4YieD-1615480452508)(C:\Users\UC241027\AppData\Roaming\Typora\typora-user-images\image-20210310171344212.png)]

Java安裝與配置
  • 環境變量Path配置

    JAVA_HOME : JAVA安裝的目錄算法

    Path:%JAVA_HOME%\bin數據庫

第一個Java程序

  • Java編譯的時候,出現unmappable character for encoding GBK

    解決方法:編程

    一、因爲系統默認編碼不是utf8,因此要將編譯改寫爲javac -encoding UTF-8 XXX.java就能夠正常輸出數組

    二、將XXX.java文件另存爲-->選擇編碼ANSI保存緩存

變量、數據類型、運算符

標識符

  • ASCⅡ字符集:12^8 = 256
  • Unicode國際字符集:2^16 = 65536

變量

  • 變量本質是可操做的存儲空間,空間位置是肯定的,值不肯定;變量名訪問「對應的存儲空間」,操做這個「存儲空間」存儲的值
  • 局部變量、成員變量(也稱實例變量)和靜態變量

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pL6TpdQv-1615480452511)(C:\Users\UC241027\AppData\Roaming\Typora\typora-user-images\image-20210310211250387.png)]

數據類型

  • boolean類型是4個字節,數組中是1個字節(在內存中佔1個字節或4個字節)
  • 數字格式化輸出

在這裏插入圖片描述

System.out.format("%.3f %.3f\n",r,volume);

System.out.printf("%.3f %.3f\n",r,volume);

運算符

  • 整數運算:

    兩數有一個爲long,則結果爲long。安全

    沒有long時,結果爲int。即便操做數全爲short、byte,結果也是int。服務器

  • 浮點運算:

    有一個爲long,結果爲long。網絡

    兩個爲float,結果才爲float。

  • 取模運算:

    通常使用整數,結果是」餘數「,」餘數「符號和左邊相同。

  • 自增、自減

    a++ //先賦值,再自增

    ++a //先自增,再賦值

  • 關係運算符

    \>、>=、<、<= 僅針對數值類型(byte/short/int/long,float/double 以及char-->0~65535)

  • 邏輯運算符

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-oCtv8dkQ-1615480452512)(C:\Users\UC241027\AppData\Roaming\Typora\typora-user-images\image-20210310230353130.png)]

  • 位運算符

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3Mb1d0ax-1615480452516)(C:\Users\UC241027\AppData\Roaming\Typora\typora-user-images\image-20210310231511440.png)]

  • 數據類型的轉換

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Tc6yegud-1615480452517)(C:\Users\UC241027\AppData\Roaming\Typora\typora-user-images\image-20210311133606475.png)]

整型常量是int類型,可是能夠自動轉爲:byte、short、char。只要不超過對應類型的範圍。

控制語句

  1. 控制語句分爲:順序、選擇、循環;
  2. 任何軟件和程序,本質上都是有"變量、選擇語句、循環語句"組成。

switch語句

  • switch語句中case標籤在JDK1.5以前必須是整數(long類型除外)或枚舉,不能字符串,但在JDK1.7以後容許使用字符串

Scanner類 鍵盤輸入

  • java中Scanner類nextInt以後用nextLine沒法讀取輸入

    問題出現緣由:

    這是由於在調用nextLine()函數前調用了Scanner的另外一個函數nextInt()(或是nextDouble())。出現這種狀況的緣由是兩個函數的處理機制不一樣,nextInt()函數在緩衝區中遇到「空格」、「回車符」等空白字符時會將空白字符前的數據讀取走,但空白字符不會被處理掉,而nextLine()函數是在緩衝區中讀取一行數據,這行數據以「回車符」爲結束標誌,nextLine()會把包括回車符在內的數據提走。因此nextInt()後的nextLine()函數並不是讀取不到數據,由於nextInt()將「回車符」留在了緩衝區,nextLine()讀取時遇到的第一個字符即是「回車符」,因此直接結束了。

    解決方法:

    在要使用nextLine()前先調用一次nextLine(),這樣留在緩衝區的「回車符」就會被處理掉,這時第二個nextLine()函數能夠正常讀取到數據。

方法

方法重載(overload):實際是徹底不一樣的方法,只是名稱相同而已,釋義:定義多個方法名相同,但參數不一樣的方法。
  • 構成方法重載的條件:

    • 不一樣的含義:形參類型、形參個數、形參順序不一樣
    • 只有返回值不一樣不構成方法的重載(如:int a(String str){}與void a(String str){}不構成方法重載)
    • 只有形參的名稱不一樣,不構成方法的重載
  • 方法重寫的三個要點:

在這裏插入圖片描述

面向對象編程

  1. 屬性用於定義該類或該類對象包含的數據或者說靜態特徵。成員變量能夠對其初始化,若是不對其初始化,Java使用默認的值對其初始化。
  • 成員變量的默認值

在這裏插入圖片描述

  1. 構造器4個要點

在這裏插入圖片描述

  1. JAVA虛擬機內存模型概念

在這裏插入圖片描述

  • 容易形成內存泄漏的操做

①. 建立大量無用對象
②.靜態集合類的使用
③.各類鏈接對象(IO流對象、數據庫鏈接對象、網絡鏈接對象)未關閉
④.監聽器的使用

  1. 對象的聲明週期
  • 建立對象四步

①.分配對象空間,並將對象成員變量初始化爲0或空
②.執行屬性值得顯式初始化
③.執行構造方法
④.返回對象的地址給相關的變量

  • 使用

經過變量引用操做對象

  • 回收

對象咩有被變量使用,則被認爲是」垃圾「,會被垃圾回收器回收

this、static關鍵字

this關鍵字
  • 建立一個對象分爲四步:

在這裏插入圖片描述
** this的本質是「建立好的對象地址」,在構造方法調用前,對象已經建立。所以,在構造方法中使用this表示"當前對象"。

  • this最常的用法

在這裏插入圖片描述

static關鍵字

在這裏插入圖片描述

繼承

繼承的實現
  • 繼承要點:
    在這裏插入圖片描述
instanceof 運算符

instanceof是二元運算符,左邊是對象,右邊是類;當對象是右邊類或子類所建立對象時,返回true;反之爲false。

public class Person{
    String name;
    int age;
    
    public static void main(String[] args){
        Student s = new Student(「AAA」,66);
        System.out.println(s instanceof Person);
        System.out.println(s instanceof Student);
    }
}

class Student extends Person{
}

方法的重寫 override

子類經過重寫父類的方法,能夠用自身的行爲替換父類的行爲;方法的重寫是實現多態的必要條件。

  • 方法重寫須要符合三個要點:

在這裏插入圖片描述

final關鍵字

屬性和方法前加final,是不可擴展(繼承)和更改的,方法不可重寫,但可重載。

  • final關鍵字的做用:

在這裏插入圖片描述

繼承和組合

組合不一樣於繼承,更加靈活。
組合的核心是將父類對象做爲子類的屬性,而後,子類經過調用這個屬性來獲取父類的屬性和方法。

  • 組合:吸取或併購
public class Animal{
    public static void main(String[] args){
        Taidi t = new Taidi();
        t.dog.shout();
    }
}

class Dog{
    public void shout(){
        System.out.println("wangwang....");
    }
}

//組合
class Taidi {
    Dog dog = new Dog(); //Taidi包含(吸取)了Dog,因此具有了Dog的屬性和方法
}

總結: 繼承除了代碼複用、也能方便咱們對事務建模。」is a「 關係建議使用繼承,」has a「 關係建議使用組合。(如:Student is a Person邏輯就沒問題,但Student has a Person就有問題了;筆記本和芯片的關係屬於包含,則可使用」has a「)

super關鍵字

  1. super 能夠看作是直接父類對象的引用。經過super來訪問被子類覆蓋的方法或屬性。
  2. 使用super調用普通方法,語句沒有位置限制,能夠在子類中隨便調用。
  3. 若構造方法的第一行代碼沒有顯式的調用super()或者this();那麼java默認都會調用super(),含義是調用父類的無參數構造方法。super()可省略。

繼承樹追溯

在這裏插入圖片描述

封裝(encapsulation)

  • 封裝的具體的優勢

在這裏插入圖片描述

  • 封裝的實現---使用訪問控制符

在這裏插入圖片描述

+ protected須要注意的兩個細節

在這裏插入圖片描述

多態

多態指的是同一個方法調用,因爲對象不一樣可能會有不一樣的行爲。

  • 多態的要點

在這裏插入圖片描述

  • 多態的必要三個條件
  1. 繼承
  2. 重寫
  3. 父類引用指向子類對象
  • 類型的強制轉化,分編譯和運行,編譯看左邊,編譯以後是什麼類型就執行什麼樣的方法;運行看右邊。

抽象方法和抽象類

abstract修飾的方法,沒有方法體,只有聲明。定義的是一種"規範",就是告訴子類必需要給抽象方法提供具體的實現。

  • 抽象類的使用要點:

在這裏插入圖片描述

接口 interface

  1. 面向對象的精髓,是對對象的抽象,最能體現這一點的就是接口。
  2. 接口就是比"抽象類"還"抽象"的"抽象類"。(abstract)
  3. 接口就是定標準的,就是要讓別人實現的。(public)
  4. 接口聲明方法的時候能夠不寫public和abstract,默認是有的。
  5. 接口定義的是不變的,如變量只能定義爲常量。能夠不寫public abtract final來修飾變量,默認是有的。

定義接口的詳細說明:
在這裏插入圖片描述

區別:

  • 普通類:具體實現
  • 抽象類:具體實現,規範(抽象方法)
  • 接口:JDK1.8以前只有規範,但JDK1.8以後新增了靜態方法和默認方法

    • 默認方法:
      默認方法和抽象方法的區別是抽象方法必需要被實現,由於默認方法有方法體,因此不須要實現,在接口中default必需要寫,經過實現類的對象調用。
    • 靜態方法:
      能夠在接口中直接定義靜態方法的實現。這個靜態方法直接從屬於接口(接口也是類,一種特殊的類),能夠經過接口名調用。
接口的多繼承

接口徹底支持多繼承,和類的繼承相似,子接口擴展某個父接口,將會得到父接口中所定義的一切。

字符串String 類詳解

字符串String是在方法區的字符串常量池(String Pool)中存儲

String 類和常量池
  • 常量池分三種:

在這裏插入圖片描述

  • String基礎

在這裏插入圖片描述

內部類

  • 內部類:
  1. 定義在一個類的內部的類,目的是方便使用外部類的相關屬性和方法;
  2. 內部類只是一個編譯時概念,一旦編譯成功,就會成爲徹底不一樣的兩個類。

在這裏插入圖片描述

  • 內部類做用

在這裏插入圖片描述

  • 內部類的分類

在這裏插入圖片描述

  1. 非靜態內部類
    在這裏插入圖片描述
//外部類
public class Outer {
    private int age = 10;

    private void show(){
        System.out.println("good!!!");
    }

    //非靜態內部類
    public class Inner{
        private String name = "tom";
        private int age = 20;

        public void showInner(){
            System.out.println("Inner.showInner");
            System.out.println(age);
            System.out.println(Outer.this.age);
            show();
        }
    }

    public static void main(String[] args) {
        Outer.Inner inner = new Outer().new Inner();    //經過 new 外部類名().內部類名() 來建立內部類對象
        inner.showInner();
    }
}
  1. 靜態內部類

在這裏插入圖片描述

//外部類
public class Outer {
    private int a = 10;
    private static int b = 20;

    //靜態內部類
    static class Inner{
        public void test(){
            System.out.println(b);
        }
    }

    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();    //經過 new 外部類名.內部類名() 來建立內部類對象
        inner.test();
    }
}
  1. 匿名內部類

適合那種只須要使用一次的類。

public class AnonymousInnerClass {
    public void test(A a){
        a.run();
    }

    public static void main(String[] args) {
        AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass();
        //匿名內部類
        anonymousInnerClass.test(new A() {
            @Override
            public void run() {
                System.out.println("匿名內部類是沒有名字的類,只需使用一次;若是從新調用一次,就會定義新的匿名內部類!");
            }
        });
    }
}

interface A{
    void run();
}
  1. 局部內部類

定義在方法內部的,做用域只限於本方法。
在這裏插入圖片描述

public class LocalInnerClass{
    public void show(){
        //做用域僅限於該方法
        class Inner{
            public void fun(){
                System.out.println("局部內部類的實現!");
            }
        }
        new Inner().fun();
    }

    public static void main(String[] args){
        new LocalInnerClass().show();
    }
}

數組

數組:相同類型數據的有序集合,數組也是對象。

  • 數組的四個基本特色

在這裏插入圖片描述

數組初始化

  • 一、數組靜態初始化
例如:
int[] a = {1,2,3}; //靜態初始化基本類型數組
Man[] mans = {new Man(1,1),new Man(2,2)}; //靜態初始化引用類型數組
  • 二、數組動態初始化
例如:
int[] a = new int[2]; //動態初始化數組,先分配空間
a[0] = 1; //給數組元素賦值
a[1] = 2; //給數組元素賦值
  • 三、數組的默認初始化

在這裏插入圖片描述

例如:
int[] a = new int[2]; //默認值:0,0
boolean[] b = new boolean[2]; //默認值:false,false
String[] s = new String[2]; //默認值:null,null

總結:默認初始化---->數組元素至關於對象的屬性,遵照對象屬性默認初始化的規則。

異常機制

當程序出現錯誤,程序安全的、繼續執行的機制。

JAVA經常使用類

Wrapper包裝類

包裝類:能夠把基本類型、包裝類對象、字符串三者進行互相轉化

  • 自動裝箱和拆箱

在這裏插入圖片描述

  • 包裝類的緩存問題

當數字在[-128,127]之間的時候,返回緩存數組中的某個元素。

public class Test{
    public static void main(String[] args){
        //當數字在[-128,127]之間的時候,返回的是緩存數組中的某個元素
        Integer i1 = 123; //自動裝箱;編譯器:Integer i1 = Integer.valueOf(123);
        Integer i2 = 123; //自動裝箱;編譯器:Integer i1 = Integer.valueOf(123);
        
        System.out.println(i1 == i2);  // true;是由於123都是從緩存中取的同一個元素
        System.out.println(i1.equals(i2)); // true
    }
}

字符串相關類

String類:不可變字符序列,會產生新對象的。
StringBuilder類:可變字符序列;效率高,可是線程不安全;添加字符序列,返回自身對象。
StringBuffer類:可變字符序列;效率低,可是線程安全;添加字符序列,返回自身對象。
  • String 類
public class Test{
    public static void main(String[] args){
        //編譯器作了優化,在編譯的時候,右邊是字符串常量,不是變量,因此直接將字符串作了拼接
        String str1 = "hello" + " java";    //至關於 str1 = "hello java";
        String str2 = "hello java";
        
        System.out.println(str1 == str2);    //true

        String str3 = "hello";
        String str4 = " java";

        //編譯的時候不知道變量中存儲的是什麼,因此沒辦法在編輯的時候作優化
        String str5 = str3 + str4;

        System.out.println(str2 == str5);    //false
    }
}
  • 效率測試
public class Test {
    public static void main(String[] args) {
        String str = "";

        long num1 = Runtime.getRuntime().freeMemory();
        long time1 = System.currentTimeMillis();

        for(int i = 0;i < 5000;i++){
            str += i;
        }

        long num2 = Runtime.getRuntime().freeMemory();
        long time2 = System.currentTimeMillis();

        System.out.println("String佔用內存:" + (num1 - num2));
        System.out.println("String佔用時間:" + (time2 - time1));

        System.out.println("===================================");

        StringBuilder sb = new StringBuilder("");

        long num3 = Runtime.getRuntime().freeMemory();
        long time3 = System.currentTimeMillis();

        for(int i = 0;i < 5000;i++){
            sb.append(i);
        }

        long num4 = Runtime.getRuntime().freeMemory();
        long time4 = System.currentTimeMillis();

        System.out.println("StringBuilder佔用內存:" + (num3 - num4));
        System.out.println("StringBuilder佔用時間:" + (time4 - time3));

        System.out.println("===================================");

        StringBuffer sb2 = new StringBuffer("");

        long num5 = Runtime.getRuntime().freeMemory();
        long time5 = System.currentTimeMillis();

        for(int i = 0;i < 5000;i++){
            sb2.append(i);
        }

        long num6 = Runtime.getRuntime().freeMemory();
        long time6 = System.currentTimeMillis();

        System.out.println("StringBuffer佔用內存;" + (num5 - num6));
        System.out.println("StringBuffer佔用時間:" + (time6 - time5));
    }
}

效率測試結果以下:
在這裏插入圖片描述

File類

java.io.File類:表明文件和目錄。

枚舉

枚舉類型隱形地繼承自java.lang.Enum。枚舉實質上仍是類,而每一個被枚舉的成員實質就是一個枚舉類型的實例。他們默認都是public static final修飾的。能夠直接經過枚舉類型名使用。

enum 枚舉名 {
    枚舉體(常量列表)
}
  • 特別注意:

++ 1.須要定義

集合(容器)

泛型

泛型簡介

泛型是將類型基於一個佔位符形式來定義,在泛型中,不可使用基本類型,只能用對象類型來定義泛型。
在這裏插入圖片描述

  • 泛型的好處:

在這裏插入圖片描述

總結一下:
在這裏插入圖片描述
  • 類型擦除

編譯時採用泛型寫的類型參數,編譯器會在編譯時去掉。
在這裏插入圖片描述

泛型的使用
  • 定義泛型

在這裏插入圖片描述

  • 泛型類

泛型類是把泛型定義在類上。

  • 泛型接口

泛型接口和泛型類的聲明方式一致。泛型接口的具體類型須要在實現類中進行聲明。

  • 泛型方法

泛型方法是指將方法的參數類型定義成泛型,以便在調用時接受不一樣類型的參數。類型參數能夠有多個,用逗號隔開,如:<K,V>。類型參數通常放到返回值前面。

+ 非靜態方法

在這裏插入圖片描述

+ 靜態方法

靜態方法沒法訪問類上定義的泛型;若是靜態方法操做的引用數據類型不肯定的時候,必需要將泛型定義在方法上。
在這裏插入圖片描述

  • 泛型方法與可變參數

在泛型方法中,泛型也能夠定義可變參數類型。
在這裏插入圖片描述

  • 通配符和上下限定

    • 無界通配符

在這裏插入圖片描述
在這裏插入圖片描述

+ 通配符的上限限定

上限限定表示通配符的類型是T類以及T類的子類或者T接口以及T接口的子接口。
在這裏插入圖片描述

+ 通配符的下限限定

下限限定表示通配符的類型是T類以及T類的父類或者T接口以及T接口的父接口。該方法不適用泛型類。
在這裏插入圖片描述

  • 泛型總結

在這裏插入圖片描述

容器

數組也是一種容器,能夠放置對象或基本類型數據

  • 數組的優點:是一種簡單的線性序列,能夠快速地訪問數組元素,效率高。僅從效率和類型檢查的角度講,數組是最好的。
  • 數組的劣勢:不靈活。容量須要事先定義好,不能隨着需求的辯護而擴容。

在這裏插入圖片描述
總之,容器的底層都是基於數組來完成的。容器中數據都是存儲在內存的。

List

List:有序(元素存入集合的順序和取出的順序一致)、可重複

  • ArrayList是List接口的實現類。是List存儲特徵的具體實現。
  • ArrayList底層是用數組實現的存儲。特色:查詢效率高、增刪效率低、線程不安全。
  • ArrayList:延遲擴容,如要擴容以1.5倍擴容。
Vector

Vector:底層使用數組實現的。線程安全,效率低。Vector的使用與ArrayList是相同的。初始容量是10,如要擴容以2倍擴容。

Stack

Stack:棧容器,是Vector的一個子類,它實現了一個標準的後進先出(LIFO:Last In First Out)的棧。

  • 棧的操做

在這裏插入圖片描述

//棧容器使用案例
public class StackTest {
    public static void main(String[] args) {
        StackTest st = new StackTest();
        st.symmetry();
    }

    //匹配符號的對稱性
    public void symmetry(){
        String str = "...{.....[....(....)....]....}..(....)..[...]...";

        //實例化Stack
        Stack<String> stack = new Stack<>();

        //假設修正法
        boolean flag = true; //假設是匹配的

        //拆分字符串獲取字符
        for(int i = 0;i < str.length();i++){
            char c = str.charAt(i);
            if(c == '{'){
                stack.push("}");
            }
            if(c == '['){
                stack.push("]");
            }
            if(c == '('){
                stack.push(")");
            }

            //判斷符號是否匹配
            if(c == '}'||c == ']'||c == ')'){
                if(stack.empty()){
                    flag = false;
                    break;
                }
                
                String x = stack.pop();

                if(x.charAt(0) != c){
                    flag = false;
                    break;
                }
            }
        }
        if(!stack.empty()){
            flag = false;
        }
        System.out.println(flag);
    }
}
LinkedList
  1. 底層用雙向鏈表實現的存儲。特色:查詢效率低,增刪效率高,線程不安全。
  2. 實現了List接口,因此LinkedList是具有List的存儲特徵的(有序,元素有重複)
Set

Set特色:無序,不可重複。無序指Set中的元素沒有索引,只能遍歷查找;不可重複指不容許加入重複的元素。

HashSet
  • HashSet:是一個沒有重複元素的集合,不保證元素的順序,線程不安全。容許有null元素;採用哈希算法實現,底層是用HashMap實現的,HashMap底層使用的是數組與鏈表實現元素的存儲。查詢效率和增刪效率比較高。Hash算法也稱之爲散列算法。
無序:
在這裏插入圖片描述
不重複:
在這裏插入圖片描述
TreeSet

在這裏插入圖片描述

  • 經過元素自身實現比較規則

在這裏插入圖片描述

  • 經過比較器指定比較規則

在這裏插入圖片描述

Map

Map接口定義了雙例集合的存儲特徵,它不是Collection接口的子接口。雙例集合的存儲特徵是以key與value結構爲單位進行存儲的。

  • Map與Collection的區別

在這裏插入圖片描述

HashMap

在這裏插入圖片描述

  • HashMap的底層源碼

在這裏插入圖片描述
在這裏插入圖片描述

TreeMap

在這裏插入圖片描述

Iterator 迭代器

在這裏插入圖片描述

  • Iterator對象的工做原理

在這裏插入圖片描述

Collections工具類

在這裏插入圖片描述

數據結構

數據結構是以某種特定的佈局方式存儲數據(存儲結構上差別)的容器。
在這裏插入圖片描述

  • 數據結構邏輯分類
  1. 線性結構:元素存在一對一的相互關係

線性表、棧、隊列、串(一堆數組)等

  1. 樹形結構:元素存在一對多的相互關係

二叉樹、紅黑樹、B樹、哈夫曼樹等

  1. 圖形結構:元素存在多對多的相互關係

有向圖、無向圖、簡單圖等

線性結構

棧結構

棧是一種只能從一端存取數據且遵循"後進先出(LIFO)"原則的線性存儲結構

鏈表結構

鏈表結構是由許多節點構成的,每一個節點都包含兩部分:
在這裏插入圖片描述

  • 鏈表分類

單向鏈表
雙向鏈表
雙向循環鏈表

  • 鏈表的特色

在這裏插入圖片描述

  • 鏈表的優缺點

在這裏插入圖片描述

單向鏈表結構

在這裏插入圖片描述

雙向鏈表結構

在這裏插入圖片描述

樹形結構

在這裏插入圖片描述

  • 節點

使用樹結構存儲的每個數據元素都被稱爲「結點」。

  • 節點的度

某個結點所擁有的子樹的個數

  • 樹的深度

樹中節點的作大層次數

  • 葉子結點

度爲0的結點,也叫終端結點。

  • 分支結點

度不爲0的結點,也叫非終端結點或內部結點。

  • 孩子

也可稱之爲子樹或者子結點,表示當前節點下層的直接結點。

  • 雙親

也可稱之爲父結點,表示當前結點的直接上層結點。

  • 根節點

沒有雙親結點的結點。在一個樹形結構中只有一個根節點。

  • 祖先

從當前結點上層的全部結點。

  • 子孫

當前結點下層的全部結點。

  • 兄弟

同一雙親的孩子。

二叉樹

在這裏插入圖片描述

滿二叉樹

在這裏插入圖片描述
在這裏插入圖片描述

徹底二叉樹

在這裏插入圖片描述
在這裏插入圖片描述

二叉樹遍歷

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

正則表達式

Java中正則表達式爲String類型,被驗證的內容一樣爲String類型。經過String類中的matches方法實現內容的匹配校驗。如:」被驗證內容「.matches("正則表達式")
在這裏插入圖片描述
在定義限定內容規則是,若是沒有指定長度限定,那麼默認長度爲1。

內容限定

  • 單個字符限定

[a]:表示當前內容必須是字母a

  • 範圍字符限定

[a-z0-9]:表示內容能夠是a-z之間的任意字母或者0-9之間的任意數字,不分前後

  • 取反限定

[^abc]:表示內容不能是a或b或c。

長度限定

在這裏插入圖片描述

長度限定符號

在這裏插入圖片描述

預約義字符

在正則表達式中能夠經過一些預約義字符來表示內容限定。目的是爲了簡化內容限定的定義
在這裏插入圖片描述

組合定義

經過多個內容限定與長度限定來組合定義

常見的正則表達式

| :或者 ,如:a|b (a或b)
\\.:任意字符 ,如:-|\\. (-或任意一個字符)
在這裏插入圖片描述

IO流

  • 數據源:提供數據的原始媒介。常見的數據源有:數據庫、文件、其餘程序、內存、網絡鏈接、IO設備。

在這裏插入圖片描述

  • 流:抽象、動態的概念,是一連串連續動態的數據集合。
輸入流:數據流從數據源到程序(InputStream、Reader結尾的流)
在這裏插入圖片描述
輸出流:數據流從程序到目的地(OutputStream、Writer結尾的流)
在這裏插入圖片描述
在這裏插入圖片描述
  • JAVA中四大IO抽象類

InputStream/OutputStream和Reader/Writer類是全部IO類的抽象父類

InputStream: 字節輸入流
OutputStream: 字節輸出流
Reader: 讀取的字符流抽象類,數據單位爲字符
Writer: 輸出的字符流抽象類,數據單位爲字符
  • Java中流的細分

按流的方向分類:

輸入流:InputStream、Reader結尾的流
輸出流:OutputStream、Writer結尾的流

按處理的數據單元分類:

字節流:以字節爲單位獲取數據,FileInputStream、FileOutputStream
字符流:以字符爲單位獲取數據,Reader/Writer結尾的流,如FIleReader、FileWriter

按處理對象不一樣分類

節點流:直接從數據源或目的地讀寫數據,如:FileInputStream、FileReader、DataInputStream
處理流:也叫包裝流,不直接鏈接到數據源或目的地,是」處理流的流「。經過對其餘流的處理提升程序的性能,如:BufferedInputStream、BufferedReader。

在這裏插入圖片描述

  • 經過字節緩衝流提升讀寫效率

在這裏插入圖片描述
總結:

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

  • File類

File類是Java提供的針對磁盤中的文件或目錄轉換對象的包裝類。一個File對象能夠表明一個文件或目錄。

文件字節流

經過緩衝區提升讀寫效率

方式一:
在這裏插入圖片描述

public class FileDemo {
    public static void main(String[] args) throws Exception{
        try(FileInputStream fis = new FileInputStream("images/s1.jpg");
            FileOutputStream fos = new FileOutputStream("images/11.jpg");
        ){
            //建立一個緩衝區
            byte[] buff = new byte[1024]; //空間換效率,效率低,但空間節省。
            int len = 0;

            while((len = fis.read(buff)) != -1){
                fos.write(buff,0,len);
            }
            fos.flush();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

方式二:
在這裏插入圖片描述

public class FileDemo {
    public static void main(String[] args) throws Exception{
        try(FileInputStream fis = new FileInputStream("images/s1.jpg");
            FileOutputStream fos = new FileOutputStream("images/11.jpg");
        ){
            //建立一個緩衝區
            byte[] buff = new byte[fis.available()]; //效率換空間,佔內存,但效率快

            fis.read(buff);
            fos.write(buff);
            fos.flush();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
經過字節緩衝流提升讀寫效率

在這裏插入圖片描述

public class FileCopyTools {
    public static void main(String[] args) {
        copyFile("images/s1.jpg","images/11.jpg");
    }

    /**
     * 文件拷貝方法
     */
    public static void copyFile(String src,String des){
        try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(des));
        ){
            int temp = 0;
            while((temp = bis.read()) != -1){
                bos.write(temp);
            }
            bos.flush();
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

文件字符流

  • 若是一個一個字符讀取,結果是Unicode字符,需將結果強轉char才能看懂數據內容。
  • 若是是字符輸出流,建立了兩個字符輸出流並同時向同一個文件輸出內容,默認是會覆蓋。除非加參數true,才能追加。

字符緩衝流
在這裏插入圖片描述

字符輸入緩衝流
在這裏插入圖片描述

字符輸出緩衝流
在這裏插入圖片描述

轉換流

InputStreamReader/OutputStreamWriter用來實現將字節流轉化成字符流。
在這裏插入圖片描述

字符輸出流

  • PrintWriter: 是節點流,能夠直接做用於文件的。

在這裏插入圖片描述

字節數組流

在這裏插入圖片描述

字節數組輸入流(ByteArrayInputStream)
  • ByteArrayInputStream : 則是把內存的"字節數組對象"當作數據源。
  • FileInputStream :是把文件當作數據源。
字節數組輸出流(ByteArrayOutputStream)
  • ByteArrayOutputStream:將流中的數據寫入到字節數組中。
public class ByteArrayOutputStreamDemo {
    public static void main(String[] args) {
        ByteArrayOutputStream bos = null;
        StringBuilder sb = new StringBuilder();
        try{
           bos = new ByteArrayOutputStream();

           bos.write('a');
           bos.write('b');
           bos.write('c');

           byte[] arr = bos.toByteArray();

           for(int i = 0;i < arr.length;i++){
               sb.append((char)arr[i]);
           }

            System.out.println(sb.toString());
        }finally{
            try{
                if(bos != null){
                    bos.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

數據流

在這裏插入圖片描述

  • DataInputStream和DataOutputStream提供了能夠存取與機器無關的全部Java基礎類型數據(如:int、double、String等)。
數據輸出流
//數據輸出流
public class DataIOStreamDemo {
    public static void main(String[] args) {
        try(DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("data.txt")));){
            dos.writeChar('a');
            dos.writeInt(4);
            dos.writeDouble(Math.random());
            dos.writeUTF("您好");
            dos.flush();
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}
數據輸入流

讀取的順序要與數據輸出流寫入的順序一致,不然不能讀取數據

//數據輸入流
public class DataIOStreamDemo {
    public static void main(String[] args) {
        try(DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("data.txt")));){
            //直接讀取數據,注意:讀取的順序要與寫入的順序一致,不然不能讀取數據
            System.out.println("char:" + dis.readChar());
            System.out.println("int:" + dis.readInt());
            System.out.println("double:" + dis.readDouble());
            System.out.println("utf:" + dis.readUTF());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

對象流

數據流只能實現對基本數據類型和字符串類型的讀寫,並不能Java對象進行讀寫操做(字符串除外),而對象流除了能實現對基本數據類型進行讀寫操做,還能對Java對象進行讀寫操做。
在這裏插入圖片描述

  • 對象的序列化和反序列化

在這裏插入圖片描述

序列化

對象的序列化:把java對象轉換爲字節序列的過程。

  • 對象序列化的做用

在這裏插入圖片描述

  • 序列化涉及的類和接口

在這裏插入圖片描述

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

//對象輸出流完成基本數據類型的輸出
public class ObjectIOStreamDemo {
    public static void main(String[] args) {
        try(ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("data")));){
            oos.writeInt(10);
            oos.writeDouble(Math.random());
            oos.writeChar('a');
            oos.writeBoolean(true);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
  • 將對象序列化到文件

在這裏插入圖片描述

反序列化

對象的反序列化:字節序列恢復爲Java對象的過程。

隨機訪問流

在這裏插入圖片描述

  • 核心方法

在這裏插入圖片描述

多線程

程序:
在這裏插入圖片描述
進程:
在這裏插入圖片描述

  • 進程特色

在這裏插入圖片描述
在這裏插入圖片描述
線程:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

  • 線程和進程的區別

在這裏插入圖片描述
在這裏插入圖片描述

  • 併發

在這裏插入圖片描述

  • 方法的執行特色()在這裏插入圖片描述
  • 線程的執行方法的特色

在這裏插入圖片描述

  • 主線程

在這裏插入圖片描述

+ 主線程的特色

它是產生其餘子線程的線程。
它不必定是最後完成執行的線程,子線程可能在它結束以後還在運行。

  • 主線程

在主線程中建立並啓動的線程,通常稱之爲子線程。

線程的建立

經過繼承Thread類實現多線程

在這裏插入圖片描述

經過實現Runnable接口實現多線程
線程的執行流程

在這裏插入圖片描述

線程的生命週期

在這裏插入圖片描述

  • 新生狀態

在這裏插入圖片描述

  • 就緒狀態

在這裏插入圖片描述
在這裏插入圖片描述

  • 運行狀態

在這裏插入圖片描述

  • 阻塞狀態

在這裏插入圖片描述

  • 死亡狀態

在這裏插入圖片描述
在這裏插入圖片描述

線程的使用

終止線程

在這裏插入圖片描述

import java.io.IOException;

public class StopThread implements Runnable{
    private boolean flag = true;

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "線程開始");

        int i = 0;
        while(flag){
            System.out.println(Thread.currentThread().getName() + " " + i++);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println(Thread.currentThread().getName() + "線程結束");
    }

    //勸本身自殺方式終止線程,線程能正常結束。
    public void stop(){
        this.flag = false;
    }

    public static void main(String[] args) throws IOException {
        System.out.println("主線程開始");

        StopThread st = new StopThread();

        Thread t1 = new Thread(st);

        //啓動線程
        t1.start();

        System.in.read();

        st.stop();

        System.out.println("主線程結束");
    }
}
  • 暫停當前線程執行sleep/yield

在這裏插入圖片描述

+ yield 方法的使用

在這裏插入圖片描述

線程聯合

在這裏插入圖片描述

  • join方法的使用

在這裏插入圖片描述

class A implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class JoinThread {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new A());
        
        //啓動A線程
        t.start();
        
        //主線程
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            
            //當i=2時,主線程等待A線程結束以後再運行
            if(i == 2){
                t.join();
            }
            Thread.sleep(1000);
        }
    }
}
Thread類經常使用方法
  • 獲取當前線程名稱
在這裏插入圖片描述

在這裏插入圖片描述

  • 判斷當前線程是否存活

在這裏插入圖片描述

線程優先級

在這裏插入圖片描述

守護線程

在這裏插入圖片描述
在這裏插入圖片描述

  • 守護線程的特色:守護線程會隨着用戶線程死亡而死亡。
  • 守護線程與用戶線程的區別

在這裏插入圖片描述

線程同步(就是把並行改爲串行)

synchronized可阻止併發更新同一個共享資源,實現了同步,可是synchronized不能用來實現不一樣線程之間的消息傳遞(通訊)。
在這裏插入圖片描述

實現線程同步

在這裏插入圖片描述

  • synchronized 關鍵字使用時須要考慮的問題:

在這裏插入圖片描述

> ![在這裏插入圖片描述](https://img-blog.csdnimg.cn/2021032109123238.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpdV90b19saXU=,size_16,color_FFFFFF,t_70)

> ![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20210321091356173.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpdV90b19saXU=,size_16,color_FFFFFF,t_70)
線程同步的使用
使用this做爲線程對象鎖

在不一樣線程中相同對象中synchronized會互斥。

語法結構:

synchronized(this){
    //同步代碼
}

public synchronized void accessVal(int newVal){

}
使用字符串做爲線程對象鎖

全部線程在執行synchronized時都會同步。因字符串是不變序列,因此會持有相同鎖。

synchronized("字符串"){
    //同步代碼
}
使用Class做爲線程對象鎖

在不一樣線程中,擁有相同Class對象中的synchronized會互斥。

synchronized(XX.class){
    //同步代碼
}

synchronized public static void accessVal(){
    //同步代碼
}
使用自定義對象做爲線程對象鎖

在不一樣線程中,擁有相同自定義對象中的synchronized會互斥。放在線程中造成互斥鎖。

synchronized(自定義對象){
    //同步代碼
}
死鎖及解決方案

死鎖是由於同一代碼塊出現嵌套synchronized形成的,解決方法是避免出現嵌套synchronized語句塊。
在這裏插入圖片描述
在這裏插入圖片描述

線程併發協做(生產者/消費者模式)

在這裏插入圖片描述

  • 角色:

    生產者:負責生產數據的模塊
    消費者:負責處理數據的模塊
    緩衝區:消費者不能直接使用生產者數據,它們之間有個「緩衝區」。生產者將生產好的數據放入「緩衝區」,消費者從「緩衝區」拿要處理的數據。
    在這裏插入圖片描述
    緩衝區的好處:
    在這裏插入圖片描述
  • wait() 方法:要在synchronized塊中調用,該方法執行後,線程會將持有的對象鎖釋放,並進入阻塞狀態,其餘須要該對象鎖的線程就能夠繼續運行了。
  • notify() 方法:要在在synchronized塊中調用,該方法執行後,會喚醒處於等待狀態隊列中的一個線程
/**
 * 定義饅頭類
 */
class ManTou{
    private int id;

    public ManTou(int id){
        this.id = id;
    }

    public int getId(){
        return this.id;
    }
}

/**
 * 定義緩衝類
 */
class SyncStack{
    //定義放饅頭的盒子
    private ManTou[] mt = new ManTou[10];

    //定義盒子的suoyin
    private int index;

    /**
     * 放饅頭
     */
    public synchronized void push(ManTou manTou){
        while(this.index == this.mt.length){
            try {
                //該方法執行後,線程會將持有的對象鎖釋放,並進入阻塞狀態,其餘須要該對象鎖的線程就能夠繼續運行了。
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        this.notify(); //該方法執行後,會喚醒處於等待狀態隊列中的一個線程
        this.mt[this.index] = manTou;
        this.index++;
    }

    /**
     * 取饅頭
     */
    public synchronized ManTou pop(){
        while(this.index == 0){
            try {
                //該方法執行後,線程會將持有的對象鎖釋放,並進入阻塞狀態,其餘須要該對象鎖的線程就能夠繼續運行了。
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        this.notify(); //該方法執行後,會喚醒處於等待狀態隊列中的一個線程
        this.index--;
        return this.mt[this.index];
    }
}

/**
 * 定義生產者線程
 */
class Producer extends Thread{
    private SyncStack ss;

    public Producer(SyncStack ss){
        this.ss = ss;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("生產饅頭:" + i);

            ManTou manTou = new ManTou(i);
            this.ss.push(manTou);
        }
    }
}

/**
 * 定義消費者線程
 */
class Customer extends Thread{
    private SyncStack ss;

    public Customer(SyncStack ss){
        this.ss = ss;
    }

    @Override
    public void run() {
        for (int i = 0;i < 10;i++) {
            ManTou manTou = this.ss.pop();

            System.out.println("消費饅頭:" + i);
        }
    }
}

public class ProduceThread {
    public static void main(String[] args) {
        SyncStack ss = new SyncStack();

        new Thread(new Producer(ss)).start();
        new Thread(new Customer(ss)).start();
    }
}

線程併發協做總結
在這裏插入圖片描述

  • 線程經過哪些方法來進行消息傳遞,總結以下:

下列的方法均是java.lang.Object類的方法,都只能在同步方法或者同步代碼塊中使用,不然會拋出異常。
在這裏插入圖片描述

網絡編程

在這裏插入圖片描述

網絡通訊協議

OSI七層協議模型:分別是:應用層、表示層、會話層、傳輸層、網絡層、數據鏈路層、物理層。
在這裏插入圖片描述

TCP/IP協議

應用層、傳輸層、互聯網絡層、網絡接口層(物理 + 數據鏈路層)
在這裏插入圖片描述

  • 傳輸過程當中,會涉及到封裝和解封

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
總結:發送數據必須同時指定IP地址和端口。
#### URL(Uniform Resource Locator)
在www上,每一信息資源都有統一且惟一的地址。URL由四部分組成:協議、存放資源的主機域名、自願文件和端口號。
#### Socket
在這裏插入圖片描述
#### TCP和UDP協議
在這裏插入圖片描述
在這裏插入圖片描述

TCP協議

在這裏插入圖片描述

UDP協議

在這裏插入圖片描述

網絡編程中經常使用類

  • InetAddress類:封裝計算機的IP地址和域名。沒有構造方法,若是要獲得對象,只能經過getLocalHost()、getByName()等靜態方法建立對象。
  • InetSocketAddress類:包含IP和端口信息,經常使用於Socket通訊。此類實現IP套接字地址(IP地址 + 端口號),不依賴任何協議。相比於InetAddress多了端口號。
  • URL類:標識了計算機的資源,它是指向互聯網「資源」的指針。(IP地址標識了Internet上惟一的計算機)

TCP通訊實現

  • 請求-響應 模式
Socket類:發送TCP消息
ServerSocket類:建立服務器

在這裏插入圖片描述

  • Socket的編程順序

在這裏插入圖片描述

UDP通訊實現

在這裏插入圖片描述

  • DatagramPacket:數據容器(封包)的做用

表示數據報包。數據報包用來實現將發送的數據進行封包處理的。

相關文章
相關標籤/搜索