久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

編寫高質(zhì)量代碼:改善Java程序的151個建議

 LZS2851 2017-05-08

java中通用的方法和準則

1.不要讓常量和變量中出現(xiàn)易混淆的字母

比如: long i = 1l;

別人很難一下子看清楚是11還是1l,,所以應(yīng)該這樣寫1L,。

命名規(guī)范:
1.包名全部小寫
2.類名首字母大寫
3.方法名稱,,首字母小寫,后面單詞首字母大寫
4.常量要用大寫,,并且用下劃線隔開
5.變量要用小寫

2.莫讓常量蛻變成變量

    interface Const {
        public static final int RANDOM_NUM = new Random().nextInt(10);
    }

        for (int j = 0; j < 5; j++) {
            Log.i("clp", "num =" + Const.RANDOM_NUM);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

上面的代碼,,每次運行值都會不一樣。

RE:只有在值固定的時候,,才考慮用final,。否則輕易不要用。 static有時候在臨時保存數(shù)據(jù)的時候會用到,。

3.三元操作符的類型務(wù)必一致

        int i = 80;
        String s1 = String.valueOf(i < 100 ? 90 : 100);
        String s2 = String.valueOf(i < 100 ? 90 : 100.0);
        Log.i("clp", "s1=" + s1);
        Log.i("clp", "s2=" + s2);

I/clp: s1=90
I/clp: s2=90.0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

規(guī)則:
1.如果2個類型不能相互轉(zhuǎn)換,,就返回Object類型
2.如果是明確類型的表達式(比如變量),,則int類型轉(zhuǎn)為long,,long類型轉(zhuǎn)為float
…還有其他規(guī)則

4.避免帶有邊長參數(shù)的方法重載

    public int getCount(int type, int i, int j) {
        return i + j;
    }


    public int getCount(int type, int... value) {
        int count = 0;
        for (int i : value) {
            count *= i;
        }
        return count;
    }

        Log.i("clp", "count=" + getCount(1, 3, 4));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

上面的代碼,,很容易搞混,可能不分析具體原因,,不知道會調(diào)用那個,。
RE:其實會調(diào)用int參數(shù)的那個,因為編譯器從最簡單的開始,。

I/clp: count=7

5.不要讓null或者空值影響到邊長方法

    public void methodA(String name, Integer... value) {

    }

    public void methodA(String name, String... value) {

    }

        methodA("a", 1, 2);
        methodA("b", "e", "e");
        methodA("c");//編譯器報錯
        methodA("c", null);//編譯器報錯
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

上面解決的辦法是傳入空的String,。
RE:我感覺最好的辦法是,避免這種寫法,,遇到這種情況,,不要去重載。

基本類型

27.謹慎包裝類型的大小比較

Integer i = new Integer(2);
Integer j = new Integer(2);
//比較封裝對象的大小,,只能使用i.compareTo(j),。 
//i==j,i>j,j<j都返回false。  i==j是返回對象的引用地址,。i>j,j<j是值的比較,。
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

28.優(yōu)先使用整形池

        int input = 127;//128 555
        Integer ii = new Integer(input);
        Integer jj = new Integer(input);
        Log.i("clp", "new 產(chǎn)生的對象:" + (ii == jj));//都為false
        ii = input;
        jj = input;
        Log.i("clp", "基本類型產(chǎn)生的對象" + (ii == jj));//127為true,128 555為false
        ii = Integer.valueOf(input);
        jj = Integer.valueOf(input);
        Log.i("clp", "valueOf 產(chǎn)生的對象" + (ii == jj));//127為true,,128 555為false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

1.new產(chǎn)生的對象比較,,肯定為false
2.自動裝箱和Integer.valueOf一樣(裝箱時通過valueOf實現(xiàn))
3.valueOf的實現(xiàn)方式,在-128和127之間,,使用的是緩沖,。超過的話,直接new

    public static Integer valueOf(int i) {
        final int offset = 128;
        if (i > -128 && i < 127) {
            return IntegerCache.cache[i + offset];
        }
        return new Integer(i);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

29.優(yōu)先使用基本類型

        int i = 14;
        f(i);
        f(Integer.valueOf(i));

    public static void f(long i) {
        Log.i("clp", "基本類型的方法被調(diào)用");
    }

    public static void f(Long i) {
        Log.i("clp", "包裝的方法被調(diào)用");
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

輸出結(jié)果:
Log.i(“clp”, “基本類型的方法被調(diào)用”);
Log.i(“clp”, “基本類型的方法被調(diào)用”);

解析:1.自動裝箱只有在賦值時才有關(guān)系,,重載可以編譯通過
2.f(i)不會報錯,,因為編輯器會自動把i加寬,變?yōu)閘ong
3.f(Integer.valueOf(i))不會報錯:基本類型,,可以先加寬在包裝,。但是不能直接包裝。所以1.先轉(zhuǎn)變?yōu)镮nteger對象,,然后調(diào)用方法的時候發(fā)現(xiàn)沒有,,自動轉(zhuǎn)換為int基本類型 3.發(fā)現(xiàn)沒有,自動加寬變?yōu)閘ong
4.如果把f(long i)方法給注釋掉,,代碼是編譯不通過的

30.不要隨便設(shè)置隨機種子

Random random = new Random(1000);
        for (int i = 0; i < 4; i++) {
            CldLog.i("clp", "第" + i + "次的隨機數(shù)為:" + random.nextInt());
        }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

RE:按照上面的代碼寫,,每次運行都會得到想通的隨機數(shù)。通過Random random = new Random(),,則不能固定范圍
04-15 11:35:44.565 15244-15244/cld.navi.mainframe I/clp: 第0次的隨機數(shù)為:-1244746321 @initControls:CldModeA.Java(72)
04-15 11:35:44.565 15244-15244/cld.navi.mainframe I/clp: 第1次的隨機數(shù)為:1060493871 @initControls:CldModeA.java(72)
04-15 11:35:44.565 15244-15244/cld.navi.mainframe I/clp: 第2次的隨機數(shù)為:-1826063944 @initControls:CldModeA.java(72)
04-15 11:35:44.565 15244-15244/cld.navi.mainframe I/clp: 第3次的隨機數(shù)為:1976922248 @initControls:CldModeA.java(72)

正確寫法如下:

        Random random = new Random();
        for (int i = 0; i < 4; i++) {
            CldLog.i("clp", "第" + i + "次的隨機數(shù)為:" + random.nextInt(20));
        }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

類,、對象及方法

31.接口中不要存在實現(xiàn)代碼

RE:這個都知道

32.靜態(tài)變量一定要先聲明后賦值

    static {
        i = 100;
    }
    public static int i = 1;
    //輸出結(jié)果,,i等于1
    public static int i = 1;
    static {
        i = 100;
    }
    //輸出結(jié)果,i等于100
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

1.靜態(tài)變量是類加載的時候分配到存儲區(qū)的
2.靜態(tài)變量在類初始化的時候首先被加載,,分配地址空間,,還沒賦值
3.按照靜態(tài)類和靜態(tài)塊的先后順序賦值,所以誰的位置在后面,,誰有最終的決定權(quán)

33.不要復(fù)寫靜態(tài)方法

public class Base {

    public static void doBaseStatic() {
        Log.i("clp", "doBaseStatic");
    }

    public void doBase() {
        Log.i("clp", "doBase No Static");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
public class Sub extends Base {

    public static void doBaseStatic() {
        Log.i("clp", "do Sub Static");
    }

    public void doBase() {
        Log.i("clp", "do Sub No Static");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
        Base mBase = new Sub();
        mBase.doBase();//do Sub No Static
        Base.doBaseStatic();//doBaseStatic
        mBase.doBaseStatic();//doBaseStatic
        //Android Studio用上面的寫法會提示
        Sub.doBaseStatic();//do Sub Static
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

1.mBase.doBaseStatic()實際上調(diào)用的是父類的方法,。因為靜態(tài)方法不依賴實例對象,是通過類名訪問的

34.構(gòu)造函數(shù)盡量簡化

public abstract class Server {

    public static int DEFAULT_PORT = 4000;

    public Server() {
        Log.i("clp", "Server");
        int port = getPort();
        Log.i("clp", "port=" + port);
//        Log.i();
    }

    protected abstract int getPort();

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
public class ServerIml extends Server {

    public int port = 100;

    public ServerIml(int port) {
        Log.i("clp", "ServerIml");
        this.port = port;
    }

    @Override
    protected int getPort() {
//        return port;//值為0
        return DEFAULT_PORT;//返回值4000
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
ServerIml serverIml = new ServerIml(80);
  • 1
  • 1

這個跟構(gòu)造方法的執(zhí)行順序有關(guān),。
04-15 14:35:54.027 7381-7381/com.example.demo I/clp: Server
04-15 14:35:54.027 7381-7381/com.example.demo I/clp: port=4000
04-15 14:35:54.027 7381-7381/com.example.demo I/clp: ServerIml

執(zhí)行順序如下:
1.子類的構(gòu)造函數(shù)接收int類型的參數(shù)(沒有賦值)
2.父類初始化常量,,也就是DEFAULT_PORT,并賦值為4000
3.執(zhí)行父類無參的構(gòu)造方法
4.調(diào)用int port = getPort();獲取端口號 ,,調(diào)用子類端口號的實現(xiàn)方法,。此時DEFAULT_PORT已經(jīng)有值,但是port子類的
構(gòu)造函數(shù)還沒有執(zhí)行,,所以沒有賦值,,返回0
5.父類初始化完畢,開始初始化子類
6.子類被賦值為100
7.執(zhí)行子類的構(gòu)造函數(shù),,重新賦值為80

35.避免在構(gòu)造函數(shù)中初始化其他類

public class Son extends Father {

    public void doSomeThing() {
        Log.i("clp", "doSomeThing");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
public class Father {

    Father() {
        new Other();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
public class Other {

    Other() {
        new Son();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
Son son = new Son();
        son.doSomeThing();
  • 1
  • 2
  • 1
  • 2

上面的代碼,,直接回導(dǎo)致程序死掉。陷入死循環(huán),。

36.使用構(gòu)造代碼塊精煉程序

代碼塊:
1.使用static{}的靜態(tài)代碼塊,。類創(chuàng)建的時候加載
2.方法后面{}的普通代碼塊,必須通過調(diào)用方法名稱使用
3.synchronize修飾的同步代碼塊
4.構(gòu)造代碼塊,,在類中沒有任何修飾,,直接使用{}

public class CldGouzaoUtil {
    {
        Log.i("clp", "構(gòu)造代碼塊");
    }

    public CldGouzaoUtil() {
        Log.i("clp", "構(gòu)造方法");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

04-15 14:59:55.597 22529-22529/com.example.demo I/clp: 構(gòu)造代碼塊
04-15 14:59:55.597 22529-22529/com.example.demo I/clp: 構(gòu)造方法

構(gòu)造代碼塊,不同于static代碼塊,,它是依賴于構(gòu)造方法執(zhí)行,。所以用途主要為
1.初始化實例變量
2.初始化實例環(huán)境
RE:2個都是在構(gòu)造方法執(zhí)行前執(zhí)行一些初始化、檢測的操作,。

37.構(gòu)造代碼塊會想你所想

public class CldGouzaoUtil {

    protected static int numOfNew = 0;

    {
        numOfNew++;
    }

    public CldGouzaoUtil() {

    }

    public CldGouzaoUtil(String mDes) {
        this();
    }

    public static int getNumOfNew() {
        return numOfNew;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
        new CldGouzaoUtil();
        new CldGouzaoUtil("haha");
        new CldGouzaoUtil("haha");
        Log.i("clp", "初始化的次數(shù)為:" + CldGouzaoUtil.getNumOfNew());
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

04-15 15:31:37.737 19985-19985/com.example.demo I/clp: 初始化的次數(shù)為:3

new CldGouzaoUtil(“haha”)這種構(gòu)造函數(shù)調(diào)用this的,,構(gòu)造代碼塊也只會執(zhí)行一次。而且只要不殺死程序,,次數(shù)會一直保留,。

38.使用靜態(tài)內(nèi)部類提高封裝性

//使用靜態(tài)內(nèi)部類加強類的封裝性和提高代碼的可讀性
public class CldInnerStatic {
    //提高封裝性-比如這個代表home是外部類的子行為
    //提高代碼的可讀性
    //形似內(nèi)部,神似外部---可以脫離外部存在
    String name;
    public Home home;

    private static int outer = 100;

    public CldInnerStatic(String name) {
        this.name = name;
    }

    public void setHome(Home home) {
        this.home = home;
    }

    //不持有外部類的引用
    //靜態(tài)內(nèi)部類不依賴外部類
    public static class Home {//靜態(tài)內(nèi)部類

        public String addr;//地址

        public int tel;//家庭電話

        public Home(String addr, int tel) {
            this.addr = addr;
            this.tel = tel;

//            name = "哈哈";//報錯-不能訪問外部類的變量
            outer = 80;//靜態(tài)內(nèi)部類可以訪問外部類static的變量
        }
    }

    public class Company {

//        public static int comAddr = "";//報錯-普通內(nèi)部類不能聲明static的方法和變量

        //報錯
//        public static void setComName() {//普通內(nèi)部類不能聲明static的方法和變量
//
//        }
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
CldInnerStatic innerStatic = new CldInnerStatic("張三");
innerStatic.setHome(new CldInnerStatic.Home("上海", 02166666666));
  • 1
  • 2
  • 1
  • 2

39.使用匿名內(nèi)部類的構(gòu)造函數(shù)

        List<String> mList = new ArrayList<>();
        List<String> mList2 = new ArrayList<>() {
        };

        List<String> mList3 = new ArrayList<>() {
            {//代碼塊
            }
        };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

第二種和第三種都是相當于匿名內(nèi)部類List mlist2 = new Sub();

40.匿名類的構(gòu)造函數(shù)很特殊

public class CldCalculator {

    {//在這里,,計算出來的值就為0,,在使用的地方就是正確的
        setOperator();
        Log.i("clp", "setOperator");
    }

    private int i, j, result;

    public CldCalculator() {

    }

    public CldCalculator(int i, int j) {
        Log.i("clp", "CldCalculator");
        this.i = i;
        this.j = j;
    }

    protected void setOperator() {
        result = i + j;
    }

    public int getResult() {
        return result;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
public class SubCal extends CldCalculator {

    {//在這里,計算出來的值就為0,在使用的地方就是正確的
        setOperator();
        Log.i("clp", "setOperator");
    }

    public SubCal(int i, int j) {

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
        CldCalculator calculator = new CldCalculator(1, 2) {
//            {
//                setOperator();//這里使用,,值是正確的
//                Log.i("clp", "setOperator");
//            }
        };
        Log.i("clp", "result=" + calculator.getResult());

        CldCalculator calculator1 = new SubCal(1, 2);
        Log.i("clp", "calculator1=" + calculator.getResult());//結(jié)果為0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

兩個結(jié)果不一樣,,因為匿名內(nèi)部類的特殊處理機制。一般的類都是默認調(diào)用父類的無參構(gòu)造,。但是匿名類沒有名字,,直接由
構(gòu)造代碼塊代替,直接調(diào)用了父類的同參構(gòu)造方法,。然后再調(diào)用自己的構(gòu)造代碼塊,。

41.讓多繼承成為現(xiàn)實

使用內(nèi)部類,巧妙的實現(xiàn)多繼承

public interface Father {
    int Strong();//強壯指數(shù)
}

public interface Mother {
    int kind();//溫柔指數(shù)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
public class FatherIml implements Father {
    @Override
    public int Strong() {
        return 8;
    }
}

public class MotherIml implements Mother {
    @Override
    public int kind() {
        return 8;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
public class Son extends FatherIml implements Mother {
    @Override
    public int Strong() {
        return super.Strong() + 2;//比付清還要強壯
    }

    @Override
    public int kind() {
        return new MotherIml() {
            @Override
            public int kind() {
                return super.kind() - 2;//溫柔比母親少了2個點
            }
        }.kind();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
        Son son = new Son();
        Log.i("clp", "strong =" + son.Strong() + ";kind=" + son.kind());
        //結(jié)果:04-15 17:32:13.267 14610-14610/? I/clp: strong =10;kind=6
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

42.讓工具類不可實例化

工具類的正確構(gòu)建方式:1.不能實例化 2.不能繼承

public final class CldUtil {

    private CldUtil() {
        throw new Error("不要實例化我");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

43.避免對象的淺拷貝

public class Person implements Cloneable {
    //名稱
    private String name;
    //父親
    private Person father;

    public Person(String name) {
        this.name = name;
    }

    public Person(String name, Person father) {
        this.name = name;
        this.father = father;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setFather(Person father) {
        this.father = father;
    }

    public String getName() {
        return name;
    }

    public Person getFather() {
        return father;
    }

    @Override
    public Person clone() {//對象的拷貝
        Person p = null;
        try {
            p = (Person) super.clone();
            p.setFather(new Person(p.getFather().getName()));//如果沒有這句話,,就是淺拷貝,加了這句話,,就是深拷貝
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return p;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
        Person father = new Person("父親");
        Person p1 = new Person("大兒子", father);
        Person p2 = p1.clone();
        p2.setName("小兒子");
//        p2.setFather(new Person("干爹"));
        p2.getFather().setName("干爹");
        Log.i("clp", "fist name=" + p1.getName() + ";father =" + p1.getFather().getName());
        Log.i("clp", "sec name=" + p2.getName() + ";father =" + p2.getFather().getName());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

使用淺拷貝
04-15 17:55:30.827 2810-2810/com.example.demo I/clp: fist name=大兒子;father =干爹
04-15 17:55:30.827 2810-2810/com.example.demo I/clp: sec name=小兒子;father =干爹
使用p2.setFather(new Person(“干爹”));或者深拷貝
04-15 17:58:27.197 2810-2810/com.example.demo I/clp: fist name=大兒子;father =父親
04-15 17:58:27.197 2810-2810/com.example.demo I/clp: sec name=小兒子;father =干爹

44.推薦使用序列化實現(xiàn)對象的拷貝

public class Person implements Serializable {
    private static final long serialVersionUID = 201704161112L;
    //名稱
    public String name;
    //父親
    public Person person;

    public Person(String name) {
        this.name = name;
    }

    public Person(String name, Person person) {
        this.name = name;
        this.person = person;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
    //使用字節(jié)流實現(xiàn)對象的拷貝
    public static <T extends Serializable> T clone(T obj) {
        //final和static的序列化問題會被引入到對象的拷貝中???
        //transient變量也會影響到拷貝的結(jié)果???
        T cloneObj = null;
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(obj);//如果不實現(xiàn)序列化,,則會拋出序列化異常
            objectOutputStream.close();
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
            cloneObj = (T) objectInputStream.readObject();
            objectInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cloneObj;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

01-04 19:27:44.620 17104-17104/old.pkg.com.myapplicati I/clp: 名稱:小兒子;父親為:父親
01-04 19:27:44.620 17104-17104/old.pkg.com.myapplicati I/clp: 名稱:大兒子;父親為:干爹

45.復(fù)寫equals方法時不要識別不出自己

public class Person {
    //名稱
    public String name;

    public Person(String name) {
        this.name = name;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Person) {
            Person person = (Person) obj;
            //equalsIgnoreCase為忽略大小寫
            return name.equalsIgnoreCase(person.getName());
//            return name.equalsIgnoreCase(person.getName().trim());
//            01-04 19:41:01.360 30991-30991/old.pkg.com.myapplicati I/clp: p1 is equals =false
//
//            return name.equalsIgnoreCase(person.getName());
//            01-04 19:41:48.420 32459-32459/old.pkg.com.myapplicati I/clp: p1 is equals =true
        }
        return super.equals(obj);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
        Person p1 = new Person("張三  ");
        Log.i("clp", "p1 is equals =" + p1.equals(p1));
  • 1
  • 2
  • 1
  • 2

使用:
return name.equalsIgnoreCase(person.getName().trim());
01-04 19:41:01.360 30991-30991/old.pkg.com.myapplicati I/clp: p1 is equals =false

return name.equalsIgnoreCase(person.getName());
01-04 19:41:48.420 32459-32459/old.pkg.com.myapplicati I/clp: p1 is equals =true

46.equals應(yīng)該考慮null值情景

接上面的例子,如果按照下面的方式判斷,,就會報錯

        Person p1 = new Person("張三  ");
        Person p2 = new Person(null);
        Log.i("clp", "p1 p2 is equals =" + p2.equals(p1));
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

所以,,應(yīng)該按照下面的寫:

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Person) {
            Person person = (Person) obj;
            if (person.getName() == null || name == null) {
                return false;
            }
            //equalsIgnoreCase為忽略大小寫
            return name.equalsIgnoreCase(person.getName());
//            return name.equalsIgnoreCase(person.getName().trim());
//            01-04 19:41:01.360 30991-30991/old.pkg.com.myapplicati I/clp: p1 is equals =false
//
//            return name.equalsIgnoreCase(person.getName());
//            01-04 19:41:48.420 32459-32459/old.pkg.com.myapplicati I/clp: p1 is equals =true
        }
        return super.equals(obj);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

47.在equals中使用getClass進行類型判斷

接上面例子,如果有一個子類,,代碼如下:

public class ManPerson extends Person {

    public int id;


    public ManPerson(String name, int id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof ManPerson) {
            ManPerson person = (ManPerson) obj;
            return super.equals(obj) && person.id == id;
        }
        return super.equals(obj);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

然后進行判斷:

        Person p1 = new Person("張三");
        ManPerson manPerson = new ManPerson("張三", 100);
        Log.i("clp", "p1 manPerson is equals =" + p1.equals(manPerson));
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

結(jié)果是true,。

這是因為p1為父類,所以使用了父類的equals方法進行判斷,。關(guān)鍵就是equals方法中使用了instanceof,。故修改如下:

    @Override
    public boolean equals(Object obj) {
        if (obj.getClass() != null && obj.getClass() == this.getClass()) {
            Person person = (Person) obj;
            if (person.getName() == null || name == null) {
                return false;
            }
            //equalsIgnoreCase為忽略大小寫
            return name.equalsIgnoreCase(person.getName());
//            return name.equalsIgnoreCase(person.getName().trim());
//            01-04 19:41:01.360 30991-30991/old.pkg.com.myapplicati I/clp: p1 is equals =false
//
//            return name.equalsIgnoreCase(person.getName());
//            01-04 19:41:48.420 32459-32459/old.pkg.com.myapplicati I/clp: p1 is equals =true
        }
        return super.equals(obj);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

48.覆寫equals方法必須覆寫hashCode方法

        Map<Person, Object> map = new HashMap<Person, Object>() {
            {
                put(new Person("張三"), new Object());
            }
        };
        Log.i("clp", "map has key=" + map.containsKey(new Person("張三")));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

上面方法,如果不覆寫hashCode,,會返回false,。

因為map是根據(jù)hashCode值決定數(shù)組的下標(HashMap底層是通過數(shù)組保存的)。如果不覆寫,,每一個對象都有一個hasCode,,自然會找不到

所以Person類中添加如下方法:

    @Override
    public int hashCode() {
        return name.hashCode();
    }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

49.推薦覆寫toString()

原因是本身,此此方法返回的是對象引用的地址值,。
01-04 21:29:51.320 27893-27893/old.pkg.com.myapplicati I/clp: person =newpkg.pkg.com.myapplication2.algorithm.Person@bd2e9

        Person person = new Person("張三");
        Log.i("clp", "person =" + person.toString());
  • 1
  • 2
  • 1
  • 2

01-04 21:29:12.490 26591-26591/old.pkg.com.myapplicati I/clp: person =name =張三

50.使用package-info類為包服務(wù)

作用:
1.聲明友好類和包內(nèi)訪問常量
2.為在包上標注注解提供便利
3.提供包的整體注釋說明

51.不要主動進行垃圾回收

因為System.gc會停止所有的相應(yīng),,去進行檢測內(nèi)存中是否有可回收的對象??赡軙容^耗時,,10S或者20S也說不準。

字符串

52.推薦使用String直接量賦值

        String s1 = "張三";
        String s2 = " 張三 ";
        String s3 = new String("張三");
        String s4 = s3.intern();
        Log.i("clp", " s1 s2 is equals=" + (s1 == s2));
        Log.i("clp", " s1 s3 is equals=" + (s1 == s3));
        Log.i("clp", " s1 s4 is equals=" + (s1 == s4));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

01-04 21:51:49.220 19875-19875/old.pkg.com.myapplicati I/clp: s1 s2 is equals=false
01-04 21:51:49.220 19875-19875/old.pkg.com.myapplicati I/clp: s1 s3 is equals=false
01-04 21:51:49.220 19875-19875/old.pkg.com.myapplicati I/clp: s1 s4 is equals=true

Java為了避免產(chǎn)生大量的對象,,內(nèi)部有一個字符串池,。創(chuàng)建字符串時,會先判斷池子中是否有這個字符串,,有就直接返回,,
如果沒有,,就創(chuàng)建一個,丟到池子當中,,并返回,。
使用new 創(chuàng)建,肯定是新建了一個對象,。
intern方法會檢查當前的對象,,在池子中是否有字面值相等的引用對象,如果有就返回池子中的對象,,沒有就放置到池子中,,并返回。

會不會有線程安全問題?
String是一個不可變對象,。
1.不可能有子類
2.String中提供的方法中的返回值,,都會新建一個對象,不會對原對象進行修改,。

要不要考慮垃圾回收?
字符串池,,是保存子JVM的常量池當中,不會進行垃圾回收,。

53.注意參數(shù)中傳遞的參數(shù)要求

    //刪除字符串
    public static String remove(String orgin, String sub) {
        return orgin.replaceAll(sub, "");
    }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
        Log.i("clp", "result =" + CldStringUtil.remove("好是好", "好"));
        Log.i("clp", "result =" + CldStringUtil.remove("$是$", "$"));
  • 1
  • 2
  • 1
  • 2

結(jié)果:
01-04 22:08:33.220 6359-6359/old.pkg.com.myapplicati I/clp: result =是
01-04 22:08:33.220 6359-6359/old.pkg.com.myapplicati I/clp: result =

replaceAll要求第一個參數(shù)是正則表達式,。$這個符號在正則表達式中是字符串的結(jié)束位置。

修改如下:

    //刪除字符串
    public static String remove(String orgin, String sub) {
        while (orgin.contains(sub)) {
            orgin = orgin.replace(sub, "");
        }
        return orgin;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

54.正確使用String,、StringBuffer,、StringBuilder

1.String一旦創(chuàng)建,不可變
2.StringBuffer是線程安全的,,StringBuilder是線程不安全的,。
所以StringBuffer的性能要比StringBuilder低。
3.性能方法,,因為String每次都會新建,,所以會遠慢于StringBuffer和StringBuilder

55.注意字符串的位置

        String s1 = 1 + 2 + "abc";
        String s2 = "abc" + 1 + 2;
        Log.i("clp", "s1=" + s1);
        Log.i("clp", "s2=" + s2);
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

01-05 06:40:30.540 28819-28819/old.pkg.com.myapplicati I/clp: s1=3abc
01-05 06:40:30.540 28819-28819/old.pkg.com.myapplicati I/clp: s2=abc12

1.從左到右依次拼接
2.只要遇到String,則所有數(shù)據(jù)都轉(zhuǎn)換為String類進行拼接
3.如果是原始數(shù)據(jù),,則直接進行拼接,,如果是對象,則調(diào)用toString()
4.在+表達式中,,String具有最高的優(yōu)先級

56.自由選擇字符串拼接方法

    String s = "";
    long time = System.currentTimeMillis();
    for (int i = 0; i < 5000; i++) {
        s += "a";
    }
    long timeend = System.currentTimeMillis() - time;
    Log.i("clp", "time1 =" + timeend);

    String a = "";
    long time2 = System.currentTimeMillis();
    for (int i = 0; i < 5000; i++) {
        s = s.concat("a");
    }
    long timeend2 = System.currentTimeMillis() - time2;
    Log.i("clp", "time1 =" + timeend2);

    StringBuilder b = new StringBuilder();
    long time3 = System.currentTimeMillis();
    for (int i = 0; i < 5000; i++) {
        b.append("a");
    }
    long timeend3 = System.currentTimeMillis() - time3;
    Log.i("clp", "time1 =" + timeend3);

    StringBuffer c = new StringBuffer();
    long time4 = System.currentTimeMillis();
    for (int i = 0; i < 5000; i++) {
        c.append("a");
    }
    long timeend4 = System.currentTimeMillis() - time4;
    Log.i("clp", "time1 =" + timeend4);

01-05 06:53:02.410 3080-3080/old.pkg.com.myapplicati I/clp: time1 =1160
01-05 06:53:04.070 3080-3080/old.pkg.com.myapplicati I/clp: time1 =1668
01-05 06:53:04.080 3080-3080/old.pkg.com.myapplicati I/clp: time1 =5
01-05 06:53:04.090 3080-3080/old.pkg.com.myapplicati I/clp: time1 =8

書上說concat執(zhí)行時間比直接添加少一倍,。但是在我手機上測試為啥還要高???

57.推薦在復(fù)雜字符串操作中使用正則表達式

//使用正則表達式計算單詞的數(shù)量
    public static int getCount(String word) {
        //正在表達式
        Pattern pattern = Pattern.compile("\\b\\w+\\b");
        Matcher matcher = pattern.matcher(word);
        int count = 0;
        while (matcher.find()) {
            count++;
        }
        return count;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
        String s = "How are you !Good!";
        Log.i("clp", "count=" + CldStringUtil.getCount(s));
  • 1
  • 2
  • 1
  • 2

01-05 07:10:17.220 8910-8910/old.pkg.com.myapplicati I/clp: count=4

58.強烈建議使用UTF編碼

文件格式為UTF-8

        try {
            String s = "張三";
            byte[] b = s.getBytes("GBK");
            Log.i("clp", "string is =" + new String(b));
            Log.i("clp", "string is =" + new String(b, "GBK"));
        } catch (Exception e) {

        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

輸出結(jié)果:
01-05 07:20:10.370 11249-11249/old.pkg.com.myapplicati I/clp: string is =????
01-05 07:20:10.370 11249-11249/old.pkg.com.myapplicati I/clp: string is =張三

59.對字符串排序持一種寬容的態(tài)度

1.使用Arrays.sort肯定不行,它是根據(jù)UNICODE代碼表來排序的,。

2.使用Collator,,但是只能包含常用的7000多個漢字。

        String[] sortName = {"張三", "李四", "王五"};
        Comparator c = Collator.getInstance(Locale.CHINA);
        Arrays.sort(sortName, c);
        for (String str : sortName) {
            Log.i("clp", "name =" + str);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

原因:java使用UNICODE編碼。
GB2312->GB18030->UNICODE

數(shù)組和集合

60.性能考慮,,數(shù)組是首選

    //基本類型是在棧內(nèi)操作的,。而對象是在堆內(nèi)操作的。
    //棧的特點是:速度快,、容量小   堆的特點是:速度慢,,容量大。
    public static int getCountArray(int[] list) {
        int sum = 0;
        long time = System.currentTimeMillis();
        for (int i = 0; i < list.length; i++) {
            sum += list[i];
        }
        long timeend = System.currentTimeMillis() - time;
        Log.i("clp", "array time is =" + timeend);
        return sum;
    }

    public static int getCountList(List<Integer> list) {
        int sum = 0;
        long time = System.currentTimeMillis();
        for (int i = 0; i < list.size(); i++) {
            sum += list.get(i);//做了一次拆箱操作,。Integer通過intValue方法自動轉(zhuǎn)換為了int基本類型
        }
        long timeend = System.currentTimeMillis() - time;
        Log.i("clp", "data time is =" + timeend);
        return sum;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
        int[] data = new int[100000];
        for (int i = 0; i < data.length; i++) {
            data[i] = 2;
        }
        CldArrayUtil.getCountArray(data);
        List<Integer> list = new ArrayList<Integer>();
        for (int j = 0; j < 100000; j++) {
            list.add(2);
        }
        CldArrayUtil.getCountList(list);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

01-05 08:13:19.740 21326-21326/old.pkg.com.myapplicati I/clp: array time is =4
01-05 08:13:19.880 21326-21326/old.pkg.com.myapplicati I/clp: data time is =35
數(shù)組的效率是集合的10倍,。這個說法是對的。

61.若有必要,,使用變長數(shù)組

    public static int[] expandArray(int[] data, int length) {//指定新的數(shù)組長度
        if (length < 0) {
            length = 0;
        }
        return Arrays.copyOf(data, length);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
        int[] data = new int[20];
        for (int i = 0; i < data.length; i++) {
            data[i] = 2;
        }
        data = CldArrayUtil.expandArray(data, 50);
        Log.i("clp", "length =" + data.length);
        Log.i("clp", "data[2]=" + data[2]);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

01-05 08:26:57.310 23679-23679/old.pkg.com.myapplicati I/clp: length =50
01-05 08:26:57.310 23679-23679/old.pkg.com.myapplicati I/clp: data[2]=2

62.警惕數(shù)組的淺拷貝

Arrays.copyOf為數(shù)組的淺拷貝,,如果是基本類型,直接拷貝值,。如果是對象,,拷貝的是引用地址。
所以如果改變拷貝后的對象的值,,拷貝前的值也會發(fā)生變化。

解決方式:重新生成對象,。

63.在明確的場景下,,為集合指定初始容量

1.例如ArrayList,如果不指定,,初始容量為10.每次如果長度不夠,,就自動擴容到1.5倍。
所以,,如果要指定一個長度為50的List,,最好直接指定容量

        List<String> mlist = new ArrayList<>(50);
        for (int i = 0; i < 60; i++) {//列表長度為50,添加60個元素
            mlist.add("2");
        }
        Log.i("clp", "list size =" + mlist.size());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

01-05 19:23:08.320 4367-4367/old.pkg.com.myapplicati I/clp: list size =60

Vector,、HashMap,、Stack類似。

64.多種最值算法,,適時選擇

        int[] data = new int[100000];
        for (int i = 0; i < data.length; i++) {
            data[i] = new Random().nextInt(10000);
        }
        //使用數(shù)組排序
        int max = data[0];
        long time = System.currentTimeMillis();
        for (int i : data) {
            max = max > data[i] ? max : data[i];
        }
        long timeEnd = System.currentTimeMillis() - time;
        Log.i("clp", "timeEnd=" + timeEnd);
        Log.i("clp", "max data = " + max);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

01-05 19:35:47.690 8007-8007/old.pkg.com.myapplicati I/clp: timeEnd=6
01-05 19:35:47.690 8007-8007/old.pkg.com.myapplicati I/clp: max data = 9999

        int[] data = new int[100000];
        for (int i = 0; i < data.length; i++) {
            data[i] = new Random().nextInt(10000);
        }
        //使用Arrays排序
        int max = data[0];
        long time = System.currentTimeMillis();
        Arrays.sort(data.clone());
        long timeEnd = System.currentTimeMillis() - time;
        Log.i("clp", "timeEnd=" + timeEnd);
        Log.i("clp", "max data = " + data[data.length - 1]);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

01-05 19:37:36.810 9440-9440/old.pkg.com.myapplicati I/clp: timeEnd=172
01-05 19:37:36.810 9440-9440/old.pkg.com.myapplicati I/clp: max data = 9281

排序10萬個數(shù)據(jù),,才有細微的差別。所以,,小數(shù)據(jù)性能影響不大,。用Arrays.sort排序代碼可讀性高一點。

求第二大元素,正常通過數(shù)據(jù)循環(huán)查找可以搞定,,下面使用TreeSet實現(xiàn)(過濾掉相同數(shù)據(jù)).

        long time = System.currentTimeMillis();
        List<Integer> mList = Arrays.asList(data);
        TreeSet<Integer> ts = new TreeSet<Integer>(mList);
        int max = ts.lower(ts.last());
        long timeEnd = System.currentTimeMillis() - time;
        Log.i("clp", "timeEnd=" + timeEnd);
        Log.i("clp", "sec max data = " + max);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

01-05 19:42:18.750 10551-10551/old.pkg.com.myapplicati I/clp: timeEnd=1092
01-05 19:42:18.750 10551-10551/old.pkg.com.myapplicati I/clp: sec max data = 9998

65.避開基本類型數(shù)組轉(zhuǎn)換列表陷進

        int[] data = new int[100000];
        for (int i = 0; i < data.length; i++) {
            data[i] = new Random().nextInt(10000);
        }
        List mList = Arrays.asList(data);
        Log.i("clp", "list size =" + mList.size());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

01-05 19:50:27.710 13585-13585/old.pkg.com.myapplicati I/clp: list size =1

asList需要輸入一個泛型化的邊長參數(shù),,基本類型是不能泛型化的,但是數(shù)組可以。所以上面就把數(shù)組泛型化為只有一個數(shù)組的,。

mList.get(0)數(shù)據(jù)如下:
這里寫圖片描述

其他7個基本類型也有這個問題,,所以如果要用,請使用包裝類型,。

66.asList方法產(chǎn)生的List對象不可更改

        Integer[] data = new Integer[5];
        for (int i = 0; i < 5; i++) {
            data[i] = new Random().nextInt(10);
        }
        List<Integer> mList = Arrays.asList(data);
        mList.add(2);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
java.lang.RuntimeException: Unable to start activity ComponentInfo
{old.pkg.com.myapplicati/newpkg.pkg.com.myapplication2.MainActivity}: java.lang.UnsupportedOperationException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2279)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2329)
at android.app.ActivityThread.access$1100(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1242)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

因為通過asList產(chǎn)生的List不同于正常使用的List,,不能使用add remove方法。
只有size toArray get set contains五個方法可以用,。

List mList = Arrays.asList(1, 2, 3);這種方式生成數(shù)組有巨大的隱患,。

67.不同的列表選擇不同的遍歷方法

        new Thread(new Runnable() {
            @Override
            public void run() {
                List<Integer> mList = new ArrayList<>();
                for (int i = 0; i < 80 * 100; i++) {
                    mList.add(new Random().nextInt(200));
                }
                long start = System.currentTimeMillis();
                int average = CldArrayUtil.average(mList);

                Log.i("clp", "time =" + (System.currentTimeMillis() - start) + "ms");
                Log.i("clp", "average=" + average);

                List<Integer> mList2 = new LinkedList<>();
                for (int i = 0; i < 80 * 100; i++) {
                    mList2.add(new Random().nextInt(200));
                }
                long start2 = System.currentTimeMillis();
                int average2 = CldArrayUtil.average(mList2);

                Log.i("clp", "time2 =" + (System.currentTimeMillis() - start2) + "ms");
                Log.i("clp", "average2=" + average2);
            }
        }).start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

使用fori循環(huán)

    //求平局數(shù)
    public static int average(List<Integer> list) {
        int sum = 0;
        for (int i = 0; i < list.size(); i++) {
            sum += list.get(i);
        }
        return sum / list.size();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

01-05 21:07:22.310 2140-2188/old.pkg.com.myapplicati I/clp: time =8ms
01-05 21:07:22.310 2140-2188/old.pkg.com.myapplicati I/clp: average=98
01-05 21:07:23.280 2140-2188/old.pkg.com.myapplicati I/clp: time2 =929ms
01-05 21:07:23.280 2140-2188/old.pkg.com.myapplicati I/clp: average2=98

8000個就是快1S,80萬個就是100S!!!!

    //求平局數(shù)
    public static int average(List<Integer> list) {
        int sum = 0;
//        for (int i = 0; i < list.size(); i++) {
//            sum += list.get(i);
//        }
        for (Integer i : list) {
            sum += i;
        }
        return sum / list.size();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

01-05 21:09:06.990 3137-3185/old.pkg.com.myapplicati I/clp: time =5ms
01-05 21:09:06.990 3137-3185/old.pkg.com.myapplicati I/clp: average=99
01-05 21:09:07.030 3137-3185/old.pkg.com.myapplicati I/clp: time2 =9ms
01-05 21:09:07.030 3137-3185/old.pkg.com.myapplicati I/clp: average2=98

在手機上測試,使用foreach方法,,消耗的時間差不多???

ArrayList實現(xiàn)了隨機讀取(RandomAcess),,而LinkedList實現(xiàn)了迭代器。

書上建議通過判斷是否有RandomAcess

    //求平局數(shù)
    public static int average(List<Integer> list) {
        int sum = 0;
        if (list instanceof RandomAccess) {//針對ArrayList可以隨機讀取的
            for (int i = 0; i < list.size(); i++) {
                sum += list.get(i);
            }
        } else {//針對LinkedList這種
            for (Integer i : list) {
                sum += i;
            }
        }
        return sum / list.size();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

01-05 21:11:53.070 4250-4304/old.pkg.com.myapplicati I/clp: time =4ms
01-05 21:11:53.070 4250-4304/old.pkg.com.myapplicati I/clp: average=98
01-05 21:11:53.130 4250-4304/old.pkg.com.myapplicati I/clp: time2 =12ms
01-05 21:11:53.130 4250-4304/old.pkg.com.myapplicati I/clp: average2=98

68.頻繁插入和刪除時用LinkedList

ArrayList和LinkedList性能比較

添加:

        new Thread(new Runnable() {
            @Override
            public void run() {
                List<String> mArrayList = new ArrayList<String>();
                for (int i = 0; i < 10; i++) {
                    mArrayList.add("a");
                }
                long start = System.currentTimeMillis();
                for (int i = 0; i < 100000; i++) {
                    mArrayList.add(2, "a");
                }
                Log.i("clp", "array list time =" + (System.currentTimeMillis() - start) + "ms");
                List<String> mLinkedList = new LinkedList<String>();

                for (int i = 0; i < 10; i++) {
                    mLinkedList.add("a");
                }
                long start2 = System.currentTimeMillis();
                for (int i = 0; i < 100000; i++) {
                    mLinkedList.add(2, "a");
                }
                Log.i("clp", "linked list time =" + (System.currentTimeMillis() - start2) + "ms");


            }
        }).start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

01-05 21:34:13.060 10127-10170/old.pkg.com.myapplicati I/clp: array list time =15847ms
01-05 21:34:13.170 10127-10170/old.pkg.com.myapplicati I/clp: linked list time =116ms

10萬個數(shù)據(jù)的話,,相差100倍,。

刪除:

        new Thread(new Runnable() {
            @Override
            public void run() {
                List<String> mArrayList = new ArrayList<String>();
                for (int i = 0; i < 10 * 10000; i++) {
                    mArrayList.add("a");
                }
                long start = System.currentTimeMillis();
                while (mArrayList.size() > 0){
                    mArrayList.remove(0);
                }
                Log.i("clp", "array list time =" + (System.currentTimeMillis() - start) + "ms");
                List<String> mLinkedList = new LinkedList<String>();

                for (int i = 0; i < 10 * 10000; i++) {
                    mLinkedList.add("a");
                }
                long start2 = System.currentTimeMillis();
                while (mLinkedList.size() > 0) {
                    mLinkedList.remove(0);
                }
                Log.i("clp", "linked list time =" + (System.currentTimeMillis() - start2) + "ms");


            }
        }).start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

01-05 21:37:58.600 11330-11372/old.pkg.com.myapplicati I/clp: array list time =15108ms
01-05 21:37:58.700 11330-11372/old.pkg.com.myapplicati I/clp: linked list time =13ms

刪除,性能相差1000倍,。

修改:

        new Thread(new Runnable() {
            @Override
            public void run() {
                List<String> mArrayList = new ArrayList<String>();
                for (int i = 0; i < 10 * 10000; i++) {
                    mArrayList.add("a");
                }
                long start = System.currentTimeMillis();
                for (int i = 0; i < 10 * 10000; i++) {
                    mArrayList.set(10000, "b");
                }
                Log.i("clp", "array list time =" + (System.currentTimeMillis() - start) + "ms");
                List<String> mLinkedList = new LinkedList<String>();

                for (int i = 0; i < 10 * 10000; i++) {
                    mLinkedList.add("a");
                }
                long start2 = System.currentTimeMillis();
                for (int i = 0; i < 10 * 10000; i++) {
                    mLinkedList.set(10000, "b");
                }
                Log.i("clp", "linked list time =" + (System.currentTimeMillis() - start2) + "ms");


            }
        }).start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

01-05 21:40:26.700 12467-12523/old.pkg.com.myapplicati I/clp: array list time =28ms
01-05 21:40:55.580 12467-12523/old.pkg.com.myapplicati I/clp: linked list time =28672ms

總結(jié):頻繁的刪除和插入,,使用LinkedList。 如果頻繁的獲取和修改,。使用ArrayList

69.列表相等只需關(guān)系元素數(shù)據(jù)

判斷集合是否相等時,,只需要判斷元素是否相等即可。

        ArrayList<String> mList = new ArrayList<String>();
        mList.add("a");

        Vector<String> mVList = new Vector<String>();
        mVList.add("a");

        Log.i("clp", "is equals =" + mList.equals(mVList));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

01-06 06:56:50.610 25692-25692/old.pkg.com.myapplicati I/clp: is equals =true

equals是在AbstractList中實現(xiàn)的,,代碼如下:

    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof List))
            return false;

        ListIterator<E> e1 = listIterator();
        ListIterator e2 = ((List) o).listIterator();
        while (e1.hasNext() && e2.hasNext()) {
            E o1 = e1.next();
            Object o2 = e2.next();
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }
        return !(e1.hasNext() || e2.hasNext());
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

70.子列表只是原列表的一個視圖

        List<String> mlist = new ArrayList<String>();
        mlist.add("A");
        mlist.add("B");
        ArrayList<String> mBList = new ArrayList<>(mlist);

        List<String> mCList = mlist.subList(0, mlist.size());
        mCList.add("C");

        Log.i("clp", "mlist mBlist is equals =" + mlist.equals(mBList));
        Log.i("clp", "mlist mCList is equals =" + mlist.equals(mCList));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

01-06 07:18:39.990 29976-29976/old.pkg.com.myapplicati I/clp: mlist mBlist is equals =false
01-06 07:18:39.990 29976-29976/old.pkg.com.myapplicati I/clp: mlist mCList is equals =true

subList是在原數(shù)組上進行操作,。

71.推薦使用subList處理局部列表

        List<String> mList = new ArrayList<String>();
        for (int i = 0; i < 100; i++) {
            mList.add("a");
        }
        //刪除第20~30之間的元素
        mList.subList(20, 30).clear();
        Log.i("clp", "mList size =" + mList.size());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

01-06 07:28:51.470 32234-32234/old.pkg.com.myapplicati I/clp: mList size =90

72.生成子列表之后不要再操作原列表

        List<String> mList = new ArrayList<String>();
        for (int i = 0; i < 100; i++) {
            mList.add("a");
        }
        List<String> mSubList = mList.subList(20, 30);
        mList.add("d");
        Log.i("clp", "mlist size =" + mList.size());
        Log.i("clp", "mSubList size =" + mSubList.size());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

java.lang.RuntimeException: Unable to start activity ComponentInfo
{old.pkg.com.myapplicati/newpkg.pkg.com.myapplication2.MainActivity}:
java.util.ConcurrentModificationException

操作子列表也有可能導(dǎo)致報錯,如下:

        List<String> mList = new ArrayList<String>();
        for (int i = 0; i < 100; i++) {
            mList.add("a");
        }
        List<String> mSubList = mList.subList(20, 30);
        List<String> mSubList2 = mList.subList(10, 30);
        mSubList.add("d");
//        mSubList2.add("e");
        Log.i("clp", "mlist size =" + mList.size());
        Log.i("clp", "mSubList size =" + mSubList.size());
        Log.i("clp", "mSubList2 size =" + mSubList2.size());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

73.使用Comparator進行排序

public class Person implements Comparable<Person> {

    public int id;
    public String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public int compareTo(Person person) {
        if (person == null) {
            return -1;
        }
        return Integer.valueOf(id).compareTo(Integer.valueOf(person.id));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
        List<Person> mList = new ArrayList<Person>();
        mList.add(new Person(2, "張二"));
        mList.add(new Person(1, "張一"));
        mList.add(new Person(4, "張四"));
        mList.add(new Person(3, "張三"));
        Collections.sort(mList);
        for (int i = 0; i < mList.size(); i++) {
            Log.i("clp", "index =" + i + ";name =" + mList.get(i).name);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

使用Comparator可以拓展排序,。

        List<Person> mList = new ArrayList<Person>();
        mList.add(new Person(2, 440300, "張二"));
        mList.add(new Person(1, 440322, "張一"));
        mList.add(new Person(4, 440310, "張四"));
        mList.add(new Person(3, 440200, "張三"));
        mList.add(new Person(6, 440200, "張六"));
        mList.add(new Person(5, 440200, "張五"));
        Collections.sort(mList, new PerComparator());
        for (int i = 0; i < mList.size(); i++) {
            Log.i("clp", "index =" + i + ";cityId=" + mList.get(i).cityId + ";name =" + mList.get(i).name);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
    //先按照cityId進行排序,,如果相等,就按照id排序
    public class PerComparator implements Comparator<Person> {
        @Override
        public int compare(Person person, Person t1) {
            if (person.cityId > t1.cityId) {//1的畫,,是排后面
                return 1;
            } else if (person.cityId == t1.cityId) {//如果城市相等,,按照id排序
                if (person.id > t1.id) {
                    return 1;
                } else if (person.id == t1.id) {
                    return 0;
                } else {
                    return -1;
                }
            } else {
                return -1;
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

如果想實現(xiàn)倒序,直接使用:
Collections.sort(mList, Collections.reverseOrder(new PerComparator()));

    Collections.reverse(mList);---對排序之后的,,進行倒序

Comparable實現(xiàn)默認排序,。Comparator可以實現(xiàn)拓展排序。

74.不推薦使用binarySearch對列表進行檢索

1.indexOf是通過for循環(huán)進行排序查找第一個符合條件的
2.binarySearch是通過二分查找,,但是前提也是必須先排序

所以,,如果已經(jīng)排序的,使用binarySearch性能會高很多,。

75.集合中的元素必須做到compartTo和equals同步

public class Person implements Comparable<Person> {

    public int id;
    public String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public int compareTo(Person person) {
        if (person == null) {
            return -1;
        }
        return person.name.compareTo(this.name);
    }

    @Override
    public boolean equals(Object o) {
        if (o == null) {
            return false;
        }
        if (o == this) {
            return true;
        }
        if (this.getClass() != o.getClass()) {
            return false;
        }
        Person p = (Person) o;
        return Integer.valueOf(id).compareTo(Integer.valueOf(p.id)) == 0;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
        List<Person> mList = new ArrayList<Person>();
        mList.add(new Person(1, "張二"));
        mList.add(new Person(1, "張一"));

        Person p = new Person(1, "張一");
        int index1 = mList.indexOf(p);
        int index2 = Collections.binarySearch(mList, p);
        Log.i("clp", "index1=" + index1);
        Log.i("clp", "index2=" + index2);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

04-18 11:51:12.192 12423-12423/com.example.demo I/clp: index1=0
04-18 11:51:12.192 12423-12423/com.example.demo I/clp: index2=1

indexOf是通過對象中的equals來判斷是否相等,,
binarySearch是通過compartTo來判斷是否相等,。所以2個方法應(yīng)該同步。

76.集合運算中使用更優(yōu)雅的方式

        List<String> mList1 = new ArrayList<String>();
        mList1.add("a");
        mList1.add("b");
        List<String> mList2 = new ArrayList<String>();
        mList2.add("a");
        mList2.add("c");

        //并集
//        mList1.addAll(mList2);
//        Log.i("clp", "并集 size=" + mList1.size());
//        //04-18 12:07:46.552 12423-12423/com.example.demo I/clp: 并集 size=4

        //交集
//        mList1.retainAll(mList2);
//        Log.i("clp", "交集 size=" + mList1.size());
        //04-18 12:08:55.022 12423-12423/com.example.demo I/clp: 交集 size=1

        //差集
//        mList1.removeAll(mList2);
//        Log.i("clp", "差集 size=" + mList1.size());
        //04-18 12:09:44.782 12423-12423/com.example.demo I/clp: 差集 size=1

        //無重復(fù)的并集
        mList2.removeAll(mList1);
        mList1.addAll(mList2);
        Log.i("clp", "無重復(fù)的并集 size=" + mList1.size());
//        04-18 12:10:34.862 12423-12423/com.example.demo I/clp: 無重復(fù)的并集 size=3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

無重復(fù)的并集,,不能使用HashSet,,因為會把本來重復(fù)的元素合并掉。

77.使用shuffle打亂列表

        int count = 10;
        List<String> mList = new ArrayList<>(10);
        for (int i = 0; i < 10; i++) {
            mList.add(i + "");
        }
//        for (int i = 0; i < 10; i++) {
//            int random = new Random().nextInt(10);
//            Collections.swap(mList, i, random);
//        }
        Collections.shuffle(mList);//打亂順序
        for (int i = 0; i < 10; i++) {
            Log.i("clp", "value" + mList.get(i));
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

78.減少HashMap中元素的數(shù)量

1.比ArrayList多了Entry對象,,如果有40萬個數(shù)據(jù),,就是多了40萬個對象
2.擴容機制不一樣,HashMap是2倍擴容,,ArrayList是1.5倍
3.HashMap有一個加載因子,,意思是到達容量的0.75就開始擴容了

所以大量數(shù)據(jù)的時候,HashMap比ArrayList先內(nèi)存溢出,。

79.集合中的哈希碼盡量不要重復(fù)

HashMap是通過哈希值,,實現(xiàn)比ArrayList快速的查找,如果哈希碼是一樣的,,性能就和鏈表的性能是一樣的,。

80.多線程使用Vector和HashTable

        final Vector<String> mVList = new Vector<String>();
        for (int i = 0; i < 10000; i++) {
            mVList.add("火車票" + i);
        }
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        String mR = mVList.remove(0);
                        Log.i("clp", "cur thread id=" + Thread.currentThread().getId() + ";remove =" + mR);
                    }
                }
            }).start();
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

多個線程同步,但是不能實現(xiàn),,一個線程讀的時候,,另一個線程在寫。

81.非穩(wěn)定序列推薦使用List

        SortedSet<Person> sortSet = new TreeSet<Person>();
        sortSet.add(new Person(15, "張三"));
        sortSet.add(new Person(10, "張四"));
        for (Person per : sortSet) {
            Log.i("clp", "id=" + per.id + ";name=" + per.name);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

04-18 15:44:55.202 31018-31018/com.example.demo I/clp: id=10;name=張四
04-18 15:44:55.202 31018-31018/com.example.demo I/clp: id=15;name=張三

        SortedSet<Person> sortSet = new TreeSet<Person>();
        sortSet.add(new Person(15, "張三"));
        sortSet.add(new Person(10, "張四"));
        sortSet.first().id = 20;
        for (Person per : sortSet) {
            Log.i("clp", "id=" + per.id + ";name=" + per.name);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

04-18 15:45:49.532 31018-31018/com.example.demo I/clp: id=20;name=張四
04-18 15:45:49.532 31018-31018/com.example.demo I/clp: id=15;name=張三

SortedSet只有在插入的時候,,進行排序,。

    sortSet = new TreeSet<Person>(new ArrayList<Person>(sortSet));

可以通過new 重新構(gòu)建。

基本類型,,建議使用SortedSet,如果是自己創(chuàng)建的對象,,可以使用Colletions.sort

82.集合大家族

一,、List
實現(xiàn)List的接口主要有:ArrayList-動態(tài)數(shù)組 LinkedList-雙向鏈表 Vector-線程安全的動態(tài)數(shù)組 Stack-對象棧,先進后出

二,、Set-不包含重復(fù)元素的集合:
EnumSet-枚舉類型的專用Set,,所有的元素都是枚舉類型
HashSet-以哈希碼決定元素位置的Set,與HashMap類似,,提供快速的插入和查找
TreeSet-自動排序的Set,,實現(xiàn)了SortedSet接口

三、Map-分為排序的Map和非排序Map
TreeMap-根據(jù)Key值自動排序
HashMap
HashTable
Properties:HashTable的子類,,主要從Property文件中加載數(shù)據(jù),,并提供方便的讀寫。
EnumMap
WeakHashMap:可以被垃圾回收的HashMap

四,、Queue隊列-分為阻塞和非阻塞隊列

五,、數(shù)組
所有的集合底層存儲的都是數(shù)組,,數(shù)據(jù)可以存儲基本類型,集合不行,。

六,、工具類
數(shù)組的工具類:Array和Arrays
集合的工具類:Collections

如果需要精確排序,則需要使用開源項目,。如pinyin4j,。

枚舉和注解

83.推薦使用枚舉定義常亮

public enum SeaSon {
    Sping, Summer, Autumn, Winner;

    public static SeaSon getCommonSeason() {
        return Sping;
    }

}

        for (SeaSon s : SeaSon.values()) {
            Log.i("clp", "s values =" + s);
        }

        Log.i("clp", "common =" + SeaSon.getCommonSeason());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

04-19 10:26:24.608 14196-14196/com.example.demo I/clp: s values =Sping
04-19 10:26:24.608 14196-14196/com.example.demo I/clp: s values =Summer
04-19 10:26:24.608 14196-14196/com.example.demo I/clp: s values =Autumn
04-19 10:26:24.608 14196-14196/com.example.demo I/clp: s values =Winner
04-19 10:26:24.608 14196-14196/com.example.demo I/clp: common =Sping

84.使用構(gòu)造函數(shù)協(xié)助描述枚舉項

public enum SeaSon {
    Sping("春"), Summer("夏"), Autumn("秋"), Winner("冬");

    private String desc;

    SeaSon(String desc) {
        this.desc = desc;
    }

    public String getDesc() {
        return desc;
    }

    public static SeaSon getCommonSeason() {
        return Sping;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
        for (SeaSon s : SeaSon.values()) {
            Log.i("clp", "s values =" + s.getDesc());
        }

        Log.i("clp", "common =" + SeaSon.getCommonSeason());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

構(gòu)造函數(shù)還可以比這個更復(fù)雜,傳遞對象等,。

85.小心switch帶來的空值異常

    public void doSwSeaSon(SeaSon seaSon) {
        switch (seaSon) {
            case Sping:
                Log.i("clp", "Sping");
                break;
            default:
                Log.i("clp", "其他類型");
                break;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
doSwSeaSon(null);
  • 1
  • 1

java.lang.NullPointerException: Attempt to invoke virtual method ‘int com.cp.demo.java.SeaSon.ordinal()’ on a null object reference

case的其實是:SeaSon.Sping.ordinal(),所以要做對象的空值判斷,。

86.在switch的default代碼塊中增加AssertionError錯誤

因為枚舉類型和case沒有強制關(guān)系,如果后續(xù)增加了一個,,沒有case,,就會導(dǎo)致switch漏掉這個枚舉項。

87.枚舉使用valueOf前必須進行校驗

否則會拋出異常

        List<String> mList = Arrays.asList("Sping", "sss");
        for (int i = 0; i < mList.size(); i++) {
            SeaSon sea = SeaSon.valueOf(mList.get(i));
            if (sea == null) {
                Log.i("clp", "沒有此枚舉值");
            } else {
                Log.i("clp", "有值");
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

java.lang.IllegalArgumentException: sss is not a constant in com.cp.demo.java.SeaSon

兩種方案:
1.捕獲異常

        List<String> mList = Arrays.asList("Sping", "sss");
        for (int i = 0; i < mList.size(); i++) {
            try {
                SeaSon sea = SeaSon.valueOf(mList.get(i));
                Log.i("clp", "有值");
            } catch (IllegalArgumentException e) {
                Log.i("clp", "沒有此枚舉值");
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

04-19 11:35:20.148 13538-13538/com.example.demo I/clp: 有值
04-19 11:35:20.148 13538-13538/com.example.demo I/clp: 沒有此枚舉值

2.拓展枚舉類

    public static boolean contains(String name) {
        for (SeaSon sen : values()) {
            if (sen.name().equals(name)) {
                return true;
            }
        }
        return false;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
        List<String> mList = Arrays.asList("Sping", "sss");
        for (int i = 0; i < mList.size(); i++) {
            boolean sea = SeaSon.contains(mList.get(i));
            if (sea) {
                Log.i("clp", "有值");
            } else {
                Log.i("clp", "沒有此枚舉值");
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

88.用枚舉實現(xiàn)工廠方法模式更簡潔

1.非靜態(tài)方法實現(xiàn),。

public interface Car {
    public void drive();
}

public class FortCar implements Car {

    @Override
    public void drive() {
        Log.i("clp", "fort drive");
    }
}

public class BuickCar implements Car {

    @Override
    public void drive() {
        Log.i("clp", "buick drive");
    }
}

public enum CarFactory {
    FortCar, BuickCar;

    public Car create() {
        switch (this) {
            case FortCar:
                return new FortCar();
            case BuickCar:
                return new BuickCar();
            default:
                Log.i("clp", "無效參數(shù)");
        }
        return null;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

04-19 11:55:34.988 1940-1940/com.example.demo I/clp: fort drive

2.通過抽象方法生成

public enum CarFactory {
    FortCar {
        @Override
        public Car create() {
            return new FortCar();
        }
    }, BuickCar {
        @Override
        public Car create() {
            return new BuickCar();
        }
    };

    public abstract Car create();

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

89.枚舉項的數(shù)量限制的64個以內(nèi)

long e = -1L >>> -65;//value=1
long e = -1L >>> -1;//value=1
long e = -1L >>> 63;//value=1
long e = -1L >>> 1;//9223372036854775807

long e = -1L >>> 62;//value=3

int e = -1 >>> 31;//value=1
int e = -1 >>> 1;//2147483647
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

小于等于64和大于64處理的機制是不一樣的,。

        Enum[] universe = getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");

        if (universe.length <= 64)
            return new RegularEnumSet<>(elementType, universe);
        else
            return new JumboEnumSet<>(elementType, universe);

RegularEnumSet:
    void addAll() {
        if (universe.length != 0)
            elements = -1L >>> -universe.length;
    }

JumboEnumSet:
    void addAll() {
        for (int i = 0; i < elements.length; i++)
            elements[i] = -1;
        elements[elements.length - 1] >>>= -universe.length;
        size = universe.length;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

所以內(nèi)部是以64位拆分進行分組。

90.小心注解繼承

91.枚舉和注解結(jié)合使用威力很大

92.注意@Overrig不同版本的區(qū)別

如果是Java1.6版本的程序移植到1.5版本環(huán)境中,,就需要刪除實現(xiàn)接口方法上的@Override注解

泛型和反射

93.Java的泛型是類型擦除的

java的編譯期和運行期解讀:
http://bbzoh.cn/content/14/0218/23/9440338_353675002.shtml

編譯期:源碼->class文件的過程
運行期:在JVM中運行的過程

    public void initList(List<Integer> mList) {

    }

    public void initList(List<String> mList) {

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

按照上面這種方式寫,,報錯。
initList(List)’ clashes with ‘initList(List)’; both methods have same erasure

        List<String> mList = new ArrayList<String>();
        List<Integer> mIList = new ArrayList<Integer>();
        Log.i("clp", "is equals=" + (mList.getClass() == mIList.getClass()));
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

04-25 15:49:13.356 2760-2760/old.pkg.com.myapplicati I/clp: is equals=true

他們擦除后的類型都是List

Java泛型-類型擦除:
http://blog.csdn.net/caihaijiang/article/details/6403349

94.不能初始化泛型參數(shù)和數(shù)組

        T t = new T();//報錯
        T[] mTArray = new T[];//報錯
        List<T> mList = new ArrayList<T>();//報錯
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

以上3個寫法,,在AS上面都報錯,,需要在運行期指定T類型。

95.強制聲明泛型的實際類型

List<Integer> mList = CldCalMiniUtil.asList();//正確
List<Integer> mList = CldCalMiniUtil.<Integer>asList();//正確
List<Number> mList2 = CldCalMiniUtil.asList(1, 2.2);//報錯
List<Number> mList2 = CldCalMiniUtil.<Number>asList(1, 2.2);//正確--這里使用了強制聲明
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多