JAVA基础

JAVA基础

1、进制与转换

  • 二进制向十进制转化:从低位次(数字最右边是低位次)开始,按位次乘以2的位次次幂,然后求和。其他进制向十进制转化与二进制类似。

  • 二进制转8进制:从低位次开始,每三位进制划分一组,产生8进制的数,然后连起来,就得到一个八进制的数
    在这里插入图片描述

  • 二进制转16进制:从低位次开始,每四位进制划分一组,产生16进制的数,然后连起来,就得到一个16进制的数
    在这里插入图片描述

15*4 = 120 几进制?
在这里插入图片描述
注意:绝大部分小数转化为二进制是表示不精确的,导致计算机在存储小数的时候是不精确的。

数据的原、反、补码过程

  • 任何数据在计算机中存储的是补码;
  • 规定最高位是一个符号位,0表示正数,1表示负数;
  • 直接算出来的二进制数字称为原码;
  • 规定正数的原码、反码、补码是一致的;
  • 负数的反码是在原码的基础上,最高位不变,其余的1变0、0变1;
  • 负数的补码是在反码的基础上+1;
  • 规定用-0表示当前类型的最小值
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2、基本数据类型

2.1 变量

变量:由变量名、数据类型、值三部分组成。它是记录数据存储的容器

2.2 基本类型

在计算机中,是以二进制形式来存储数据,每一位二进制在内存中称之为是一“位”(bit,简写b),8位 = 1字节(byte,简写B);1024B=1KB、MB、GB。。。。

2.2.1 基本数据类型

  • 数值型
    • 整数型
      • byte(字节型) ,1个字节,取值范围-128~127;
      • short(短整型),2个字节,取值范围-32768~32767;
      • int(整型),4个字节,取值范围-20亿~20亿,在java中整数默认为int类型;
      • long(长整型), 8个字节,需要在结尾添加l/L作为标识;
    • 浮点型
      • float(单精度),4个字节,虽只有四个字节,但取值范围要比long还要大,需在结尾添加f/F标识
      • double(双精度),8个字节,在java中小数默认为double类型
  • 字符型
    • char(字符型),2个字节,取值范围0~65535,字符在存储过程中需要按照某种规则转化为数字,这种转化规则称之为编码。ASCI表取值范围0~127
      • ISO-8859-1(西欧码表),1个字节 表示1个字符
      • 所有的码表必须兼容西欧码表,前256个字符是一样的,而且前256个字符永远占用1个字节。
      • gb2312(国标码),gbk兼容gb2312,2个字节 表示1个字符,收录了绝大部分常见的简体汉字和一部分的繁体字。
      • Unicode编码体系(万国码):UTF-8,3个字节表示1个字符;utf-16,2个字节表示1个字符
  • 布尔型:boolean,4个字节
数据类型转换
隐式类型转换
  • 小的类型可以自动转化为大的类型,自动类型转换, 也叫隐式类型转换

  • 整数可以自动转化为小数,但是可能产生精度损失
    在这里插入图片描述

  • 字符可以自动转化为整数

    • 如short = ‘a’;char c = 97; 直接赋值不会报错
    • 如char c = ‘a’;short s = c; 不可以这样赋值。原因是short类型和char类型范围没有完全重合,不能完全包含。
      在这里插入图片描述
      在这里插入图片描述
显式类型转换
  • 大的类型给小的类型转换,也叫强制类型转换
    注意:大类型可以强制转为小类型,但是在转化的时候因为字节的损失所以可能导致数据
    不准确。

2.2.2 引用数据类型

数组:[]、字符串:String、类:class、接口:interface

注意字符串 + 任何数据 = 字符串

3、运算符

3.1 算术运算符

在这里插入图片描述

  • byte/short/char在运算的时候会自动提升为int
  • int 在计算完成之后结果一定是 int
  • 小类型和大类型运算的时候结果一定是大类型
  • 整数/0 ,会报算术异常
  • 非零小数/0、非零数字/0.0,得到的结果为Infinity
  • 0/0.0、0.0/0、0.0/0.0,得到的结果为NaN
  • %的结果的符号看的是%左边数字的符号
  • ++/–自增/自减,在变量之前:先自增再赋值/先自减再赋值,在变量之后:先赋值再自增/先赋值再自减
  • byte/short/char可以参与自增/自减运算,运算之后结果类型不变

3.2 赋值运算符

=

  • 除了=之外,其他的符号都是相当于在这个变量本身的基础上来进行运算
  • 除了=之外,其他的符号都要求这个变量必须有值
  • java中不支持连等定义,如(int i=j=5);但支持连等运算,如(int i = 5;i -= i *= i++;结果为-20)
  • 都可以byte/short/char类型参与运算,运算之后结果类型不变
  • 在运算的时候是从左往右编译的,但是在计算结果的时候从右往左计算
    在这里插入图片描述
  • int i = 5;i = i++; 结果为5,通过远算符优先级来解释,因自增运算符的优先级要高于赋值运算符。

3.3 关系运算符

在这里插入图片描述

  • 运算的结果一定是逻辑值(true/false)

3.4 逻辑运算符

主要针对逻辑值进行运算的
在这里插入图片描述

  • &: 两边为true,则为true;遇false,则为false
  • |: 两边为false,则为false;遇true,则为true
  • !: 非真即假;非假即真
  • ^: 两边相同则为假,两边不同则为真
  • &&: 运算规则和&是一致的,如果前边的表达式的结果是false,则后边的表达式就不在运算了,短路,再考虑使用&&时,两边要有交集才可。
  • ||: 运算规则和|是一致的,如果前边的表达式的结果是true,则后边的表达式就不在运算了,短路,使用||时,两边有其一满足条件即可。
  • ||&&前边的时候能够把&&给短路掉,但是&&||前边,不能把||短路掉
//`||`在`&&`前边的时候能够把`&&`给短路掉
public class test {
   
    public static void main(String[] args) {
   
        int i = 3,j = 5;
        boolean b = true || i++ > 1 && j++ > 3;

        System.out.println(b); //true
        System.out.println(i); //3
        System.out.println(j); //5
    }
}
//`&&`在`||`前边,不能把`||`短路掉
public class test {
   
    public static void main(String[] args) {
   
        int i = 3,j = 5;
        boolean b = false && i++ > 1 || j++ > 3;

        System.out.println(b); //true
        System.out.println(i); //3
        System.out.println(j); //6
    }
}

3.5 位运算

注意:位运算只针对整数的补码进行运算
在这里插入图片描述

  • &|^
    在这里插入图片描述
  • 交换值方式
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    • 交换值的三种方式的优劣性
      • 亦或法:效率最高,使用频率低,只适用于整数值的交换。
      • 加减法:效率低于亦或法,但又高于追尾法,理论上适用于数值型,但在小数上不准确,往往还是在整数上使用多。
      • 追尾法:效率最低,使用频率高,适用于所有的类型
  • <<>>>>>
    在这里插入图片描述
    • 在进行移位运算,并不是直接移动对应的位数,而是将要移动的位数对32进行取余,移动的是余数对应的位数。如:28 << 35 = 28 << (35%32) = 28 << 3 = 224;右移为也类似。
  • ~:取反
    在这里插入图片描述

3.6 三元运算符

  • 逻辑值?表达式1:表达式2
  • 执行顺序:先判断逻辑值,如果逻辑值为true,那么执行表达式1;反之执行表达式2
  • 三元表达式依然是一个表达式,所以需要有一个计算结果,这个计算结果定义变量来进行存储。如:int i = 5,j = 8;i > j ? System.out.println(i):System.out.println(j);报错原因是没有结果可存储。
  • 表达式1和表达式2的计算结果类型要一致或能兼容或能类型能转化
    在这里插入图片描述
  • 三元表达式在嵌套时,最好加上括号加以区分
public class test {
   
    public static void main(String[] args) {
   
        int i = 3,j = 8,k = 5;

        int max = i > j ? (i > k ? i : k) : (j > k ? j : k);

        System.out.println("最大值:" + max);
    }
}

3.7 运算符优先级

() ~ ++ -- ! * / % + - << >> >>> 关系 逻辑 & | 三元运算符 赋值 :从左至右,优先级逐渐降低。
总结:一元运算 > 二元运算 > 三元运算 > 赋值
在这里插入图片描述

3.8 综合案例

  • 定义一个整数变量,判断这个整数是一个奇数还是一个偶数
public class test {
   
    public static void main(String[] args) {
   
        /**
         * 定义一个整数变量,判断这个整数是一个奇数还是一个偶数
         */
        int num = 15;

        //1&奇数为奇数,1&偶数为偶数,以此来判断奇偶数
        String str = (num & 1) == 1 ? "奇数" : "偶数";
        System.out.println(str);
    }
}
  • 定义一个变量表示分数,分数>=90-A、>=80-B、>=70-C、>=60-D、<60-E
public class test {
   
    public static void main(String[] args) {
   
        /**
         * 定义一个变量表示分数,分数>=90-A、>=80-B、>=70-C、>=60-D、<60-E
         */
        double score = 80;

        //嵌套三元运算符,需要加括号加以区分
        char level = score >= 90 ? 'A' : ((score >= 80) ? 'B' : ((score >= 70) ? 'C' : ((score >= 60) ? 'D' : 'E')));

        System.out.println("分数对应的等级为:" + level);
    }
}
  • 定义一个变量表示年份,判断这一年是平年还是闰年
public class test {
   
    public static void main(String[] args) {
   
        /**
         * 定义一个变量表示年份,判断这一年是平年还是闰年
         *
         * 分析:
         *      闰年:逢百年整除400,不是百年整除4
         *      平年:其他均为平年
         *      如:2000为闰年(逢百年整除400)、2012为闰年(不是百年整除4)、2100为平年(逢百年不能整除400)
         */
        int year = 1600;

        //嵌套三元运算符
        String str = year % 100 == 0 ? (year % 400 == 0 ? "闰年" : "平年") : ( year % 4 == 0 ? "闰年" : "平年");
        System.out.println(str);
    }
}

在这里插入图片描述
在这里插入图片描述

4、流程控制

4.1 顺序结构

指代码从上到下、从左到右来依次编译执行

4.2 分支结构

4.2.1 判断结构

对于判断结构适用于判断范围,首先要对逻辑值进行判断,只有逻辑值为true代码块才会被执行。

if(逻辑值){
   
	code;
}
  • 执行顺序
    • 如果逻辑值为true,那么就执行code,反之,不执行。
if(逻辑值){
   
	code1;
}else{
   
	code2;
}

  • 执行顺序
    • 先执行逻辑值,
    • 如果逻辑值为true,那么就执行code1;
    • 如果逻辑值为false,则执行code2。
if(逻辑值1){
   
	code1;
}else if(逻辑值2){
   
	code2;
}...
  • 执行顺序
    • 先执行逻辑值1,如果逻辑值1为true,,就执行code1;
    • 如果逻辑值1为false,则会执行逻辑值2,如果逻辑值2为true ,执行code2。…
应用案例
  • 输入三个整数,获取最大值
import java.util.Scanner;

public class test {
   
    public static void main(String[] args) {
   
        /**
         * 输入三个整数,获取最大值
         */
        Scanner s = new Scanner(System.in);
        int i = s.nextInt();
        int j = s.nextInt();
        int k = s.nextInt();

        //方法一:
        int max = i;

        if(max < j){
   
            System.out.println("三个数中的最大值为:" + j);
        }

        if(max < k){
   
            System.out.println("三个数中的最大值为:" + k);
        }
        
        //方法二:
        if(i > j){
   
            if(i > k){
   
                System.out.println("三个数中的最大值为:" + i);
            }else{
   
                System.out.println("三个数中的最大值为:" + k);
            }
        }else{
   
            if(j > k){
   
                System.out.println("三个数中的最大值为:" + j);
            }else{
   
                System.out.println("三个数中的最大值为:" + k);
            }
        }
    }
}
  • 输入分数,获取分数的等级
import java.util.Scanner;

public class test {
   
    public static void main(String[] args) {
   
        /**
         * 输入分数,获取分数的等级
         */
        Scanner s = new Scanner(System.in);

        double score = s.nextDouble();
		
		//合法性的校验,要首先考虑
        if(score > 100 || score < 0){
   
            System.out.println("分数不合法");
        }else if(score >= 90){
   
            System.out.println("A");
        }else if(score >= 80){
   
            System.out.println("B");
        }else if(score >= 70){
   
            System.out.println("C");
        }else if(score >= 60){
   
            System.out.println("D");
        }else
            System.out.println("E"); //代码块只有`一句话`,那么`{}`可以省略不写
    }
}

注意:如果if或者是else中的代码块只有一句话,那么{}可以省略不写

4.2.2 选择结构

  • 选项可把它理解为选择,是多个确定的数据供选择
  • switch以及case中的选项:只能是byte/short/char/int,JDK1.7之后支持String,枚举
  • 如果case之后没有break,那么从匹配的选项开始,然后依次往下执行,直到遇到break或者switch的末尾才结束。
  • 打印每一个月有多少天
public class test {
   
    public static void main(String[] args) {
   
        /**
         * 打印每一个月有多少天
         *
         * 案例:
         *      31天的有哪几个月:1、3、5、7、8、10、12
         *      30天的有哪几个月:4、6、9、11
         * 		如果是闰年:2月有29天
         * 		如果是平年:2月有28天
         */

        int month = 4;
        switch (month){
   
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                System.out.println(month + " 月为31天");
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                System.out.println(month + " 月为30天");
                break;
            case 2:
                System.out.println(month + " 月为28天");
                break;
        }
    }
}
  • 如果每一个case之后都有break,case的顺序不影响结果
  • 如果有一个或者多个case之后没有break,那么case会影响结果
switch(选项){
   
	case 选项1:
		code1;
		break; //表示当前选项的结束
	case 选项2:
		code2;
		break;
	...
	default: //如果其他选项都不匹配,则执行default的code;合法性校验,可写在此处
		coden;
}
应用案例
  • 输入三个数字分别表示年月日,计算这一天是这一年的第几天
import java.util.Scanner;

public class test {
   
    public static void main(String[] args) {
   
        /**
         * 输入三个数字分别表示年月日,计算这一天是这一年的第几天
         *
         */
        Scanner s = new Scanner(System.in);
        int year = s.nextInt();
        int month = s.nextInt();
        int day = s.nextInt();

        //定义变量记录总得天数
        int sum = 0;
		//解题思路:借用没有break,它会依次往下累加,
        switch(month){
   
            case 12:sum += 30; //12月的时候,会经历完整的11月
            case 11:sum += 31; //11月的时候,会经历完整的10月
            case 10:sum += 30;
            case 9:sum += 31;
            case 8:sum += 31;
            case 7:sum += 30;
            case 6:sum += 31;
            case 5:sum += 30;
            case 4:sum += 31;
            case 3:
            	//闰年和平年的判断,来确定2月的天数
                if(year % 400 == 0 || year % 100 != 0 && year % 4 == 0){
   
                	//闰年29天
                    sum += 29;
                }else{
   
                	//平年28天
                    sum += 28;
                }
            case 2:sum += 31;
            case 1:sum += 0;
        }
        sum += day;
        System.out.println(sum);
    }
}

4.3 循环结构

4.3.1 while循环

需要定义变量来控制循环的次数,控制好循环执行的条件,控制次数的变量需要改变
在这里插入图片描述

while(逻辑值){
   
	code;
}
  • 执行流程
    在这里插入图片描述
应用案例
  • 输入一个整数n,打印1~n中所有的能被3整除,而不能被5整除的数字
import java.util.Scanner;

public class test {
   
    public static void main(String[] args) {
   
        /**
         * 输入一个整数n,打印1~n中所有的能被3整除,而不能被5整除的数字
         *
         * 解题思路:
         *      先获取1~n中所有3的倍数
         *      再判断这个数是否能够被5整除
         */
        Scanner s = new Scanner(System.in);

        int n = s.nextInt();

        int count = 3;

        while(count <= n){
   
            if(count % 5 != 0) System.out.println(count);
            count += 3;
        }
    }
}

  • 输入一个整数n,输出这个n是几位数
import java.util.Scanner;

public class test {
   
    public static void main(String[] args) {
   
        /**
         * 输入一个整数n,输出这个n是几位数
         *
         */
        Scanner s = new Scanner(System.in);

        int n = s.nextInt();

        //定义一个变量来记录位数
        int count = 0;

        while(n != 0){
   
            count++;
            //整数除以10,直到被除等于0,位数就可以判断了,每除以一次10,就减少一位
            n /= 10;
        }
        System.out.println(count);
    }
}
  • 输入一个整数n,打印这个整数的所有因数
import java.util.Scanner;

public class test {
   
    public static void main(String[] args) {
   
        /**
         * 输入一个整数n,打印这个整数的所有因数
         *
         * 解题思路:
         *          1、先获取1~n的所有数
         *          2、在判断这个数能否整除n
         */
        Scanner s = new Scanner(System.in);

        int n = s.nextInt();

        int count = 0;

        while(count <= n){
   
            if(n % count == 0) System.out.println(count);
            count++;
        }
    }
}

4.3.2 do while循环

无论逻辑值是否满足,代码块至少执行一次,因代码块在循环条件之上,只要稍微改一下while循环条件,就能实现do while的效果。

do{
   
	code; //代码块在逻辑值之上,所以不管循环条件是否满足都会执行一次
}while(逻辑值);

在这里插入图片描述

4.3.3 for循环

for(定义循环变量;控制条件;改变循环变量){
   
	code;
}

在这里插入图片描述
总结
1、如果需要执行多次建议使用循环
2、如果次数固定或者变化比较规律,建议使用for循环;如果次数不固定或者变化没有规律,建议使用while循环。
在这里插入图片描述

应用案例
public class test {
   
    public static void main(String[] args) {
   
        /**
         *  *** 	第n行
         *  **
         *  *   	第1行
         * 
         *      思路:
         *          1、行数:n->1
         *          2、第i行的*个数:i->1
         */

        for (int i = 3; i > 0; i--) {
   
            for (int j = i; j > 0; j--) {
   
                System.out.print("*");
            }
            System.out.println();
        }

        /**
         *   *  	第1行
         *  **
         * ***  	第n行
         *
         *      思路:
         *          1、行数:1->n
         *          2、第i行的空格个数:1->n-i
         *          3、第i行的*个数:1->i
         */
        for (int i = 1; i <= 3; i++) {
   
            for(int j = 1;j <= 3 - i;j++){
   
                System.out.print(" ");
            }
            for(int k = 1;k <= i;k++){
   
                System.out.print("*");
            }
            System.out.println();
        }

        /**
         *  *** 	第n行
         *   **
         *    * 	第1行
         * 
         *      思路:
         *          1、行数:n->1
         *          2、第i行的空格个数:n-i->1
         *          3、第i行的*个数:i->1
         */
        for (int i = 3; i > 0; i--) {
   
            for(int j = 3 - i;j > 0;j--){
   
                System.out.print(" ");
            }
            for(int k = i; k > 0;k--){
   
                System.out.print("*");
            }
            System.out.println();
        }

        /**
         *      *			第1行
         *     ***
         *    *****
         *   *******		第n行
         *
         *          思路:
         *              行数:1->n
         *              第i行空格数:1->n-i
         *              第i行*数:1->2*i - 1
         */
        for (int i = 1; i <= 4; i++) {
   
            for(int j = 1; j <= 4 - i; j++){
   
                System.out.print(" ");
            }
            for(int k = 1; k <= 2 * i - 1;k++){
   
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
public class test {
   
    public static void main(String[] args) {
   
        /**
         *    *
         *    **
         *    ***
         *    ****
         *    *****
         */

        //方法一:
        for (int i = 1; i <= 5; i++) {
   
            for(int j = 1;j <= i;j++){
   
                System.out.print("*");
            }
            System.out.println();
        }

        //方法二:
        for(int i = 1,j = 1;i <= 5;j++){
   
        	//打印*
            System.out.print("*");
            //判断这一行是否到达了末尾
            if(j == i){
   
            	//如果到达末尾,换行
                System.out.println();
                //新的一行,行数+1
                i++;
                j = 0;
            }
        }
    }
}

4.3.4 break和continue

  • break:仅在选择结构和循环结构中是使用,表示终止当前的一层结构
  • continue:只能用于循环结构中。表示跳过当前循环继续下次循环。
应用案例
  • 输入一个数字,判断这个数字是否是一个质数
import java.util.Scanner;

public class test {
   
    public static void main(String[] args) {
   
        /**
         *  输入一个数字,判断这个数字是否是一个质数
         *
         *     分析:
         *          1、质数->只能被1和自身整除,1不是质数
         *          2、n -> 只需从2~n-1判断即可,所以判断的次数就为:n-2
         *          3、以因数为例:因数是能整除的数(如:6 :1、2、3、6,规律:只要过了一半的数都
         *          未能整除,但要除了自身的数,则就没有能整除的数)
         *          4、由此质数的判断次数则会变为:2~n/2(除了1和自身的数,只要判断n/2之间的数就可以了)
         */

        Scanner s = new Scanner(System.in);
        int num = s.nextInt();

        //合法性校验
        if(num <= 1){
   
            System.out.println(num + " 不是质数");
        }else{
   
            //数字是质数,为true;不是质数,则为false
            boolean flag = true;
            for(int i = 2; i <= num/2;i++){
   
                if(num % i == 0){
   
                    flag = false;
                    break;
                }
            }

            if(flag) System.out.println(num + " 是质数");
            else System.out.println(num + " 不是质数");
        }
    }
}
  • 100文钱买100只鸡,3文买一只公鸡,2文买一只母鸡,1文买3只小鸡
public class test {
   
    public static void main(String[] args) {
   
        /**
         *  百钱百鸡:100文钱买100只鸡,3文买一只公鸡,2文买一只母鸡,1文买3只小鸡
         *
         *     分析:
         *         1、3文买一只公鸡,那么100文能买33只公鸡(gj)
         *         2、2文买一只母鸡,那么100文能买50只母鸡(mj)
         *         3、1文买3只小鸡,那么100文能买300只小鸡(xj)
         */
         //方法一:
        for(int gj = 0;gj < 33;gj++){
   
            for(int mj = 0;mj < 50;mj++){
   
                for(int xj = 0;xj < 100;xj++){
   
                    if(xj % 3 == 0){
   
                        if((gj + mj + xj) == 100 && (3 * gj + 2 * mj + xj * 1/3) == 100){
   
                            System.out.println("公鸡数量:" + gj + "母鸡数量:" + mj + "小鸡数量:" + xj);
                        }
                    }
                }
            }
        }

		//方法二:
		for(int gj = 0;gj < 33;gj++){
   
			for(int mj = 0;mj < 50;mj++){
   
				int xj = 100 - gj -mj;
				//xj的数量必须要满足能被3整除
				if(xj % 3 == 0 && (3 * gj + 2 * mj + xj/3) == 100){
   
					System.out.println("公鸡数量:" + gj + ",母鸡数量:" + mj + ",小鸡数量:" + xj);
				}
			}	
		}
    }
}
  • 输入一个数字n,然后将n分解质因数
import java.util.Scanner;

public class test {
   
    public static void main(String[] args) {
   
        /**
         *  输入一个数字n,然后将n分解质因数
         *
         *     分析:
         *         1、要从最小质数2开始循环
         *         2、分解数字n,得到n被整除的质数,要求上一个质数必须除尽,才能进行下一个质数整除。
         *            例如:100从最小质数2开始整除 得50,还能被2整除,得25,分解的数不能被2整除,
         *                 说明2被除尽了;
         *                 然后下一个最小质数3开始整除,发现不能整除;
         *                 在进行下一个数4整数,但4不是质数;
         *                 所以再进行下一个质数5开始整除,得5,分解的数还能被5整除,得1,
         *                 分解的数不能再被5整除,说明5被除尽了。
         */
        Scanner s = new Scanner(System.in);
        int n = s.nextInt();

        //循环条件和控制次数可先不写,根据计算的实际情况来填写
        for(int i = 2;n != 1;){
   
            if(n % i == 0){
   
                System.out.println(i);
                /**
                 * 整除后将值重新赋给n,如此能继续寻找下一个质数,
                 * 直到n被整除的结果为1,循环结束,
                 * 此时把n!=1作为for循环的循环条件
                 */
                n /= i;
            }else{
   
                //上一个质数i已经除尽了,需要自增i++
                i++;
            }
        }
    }
}

在这里插入图片描述

5、一维数组

在这里插入图片描述

  • 存储同一类型的多个数据容器
  • 大小固定
  • 对存入的数组元素进行了编号,这个编号称为下标也称索引,是从0开始算的。

5.1 定义数组

数组5.1.15.1.2的声明和初始化是能分开的,5.1.3的声明和初始化不能分开

5.1.1 动态初始化

只知道大小,不知道具体元素

数据类型[] 数组名 = new 数组类型[长度];

:int[] arr = new int[5];//表示定义了一个能存储5个整型元素的数组

5.1.2 静态初始化①

数组类型[] 数组名 = new 数据类型[]{
   元素1,元素2,...};//数组的长度是确定的,长度就不能变了

:int[] arr = new int[]{1,2,3,4,5,6};

5.1.3 静态初始化②

数组类型[] 数组名 = {
   元素1,元素2,...};

例:int[] arr = {1,2,3,4,5,6};

5.1.4 内存

  • 方法实参传递给形参的时候一定足以:一切都是值传递

  • 如果是基本数据类型,那么传递的就是字面值

  • 如果是引用数据类型,那么传递的就是地址值
    在这里插入图片描述

  • Java将内存分为了5块:栈内存堆内存方法区本地方法栈PC计数器(寄存器)
    A 、栈内存:存储变量。变量在声明的时候存储到栈内存中,不会自动给值,除非程序中手动给值。变量在栈内存中使用完成之后要立即释放
    B、堆内存:存储的是对象。对象在存储到堆内存中之后,会被堆内存赋予一个默认值。对象使用完成不一定会从堆内存中立即移除,而是在不确定的某个时刻被回收

    • byte/short/int:默认值为0
    • long:默认值为0L
    • float:默认值为0.0F
    • double:默认值为0.0
    • char:默认值为\u000;用的是utf-16来存储的,\u000是空字符
    • boolean:默认值为false
    • 引用类型数据:数组、String、类,默认值为null

5.2 遍历数组

5.2.1 普通for循环:先获取下标,然后利用下标获取元素

备注:可循环,也可改变数组元素

for(int i = 0;i < arr.length;i++){
   
	//通过下标获取数组元素
	System.out.println(arr[i]);
}

5.2.2 增强for循环:定义变量来依次表示每一个元素

注意:只能遍历数组而不能改变数组中元素

for(int i:arr){
   
	//由于数组的连续性,不依赖下标直接获取元素
	System.out.println(i);
}

5.2.3 数组的元素拼接成字符串返回

String str = Arrays.toString(arr);
System.out.println(str);

5.2.4 数组的排序

  • 冒泡选择排序:可升序也可降序,时间复杂度:O(n^2)
  • Arrays.sort(arr) :只能升序排序,底层是以快速排序+归并排序,时间复杂度:O(nlogn)
应用案例
  • 获取数组中的最值
public class test {
   
    public static void main(String[] args) {
   
        /**
         *  获取数组中的最大值
         */
        int[] arr = {
   2,8,9,2,7,3,0,8,3,1,4};

        //方法一:
        int max1 = arr[0]; //定义最大值

        for(int i = 0;i < arr.length;i++){
   
            if(arr[i] > max1) max1 = arr[i];
        }
        System.out.println("数组中的最大值为:" + max1);

        //方法二:
        int max2 = 0; //定义最大值的索引

        for(int i = 0;i < arr.length;i++){
   
            if(arr[i] > arr[max2]) max2 = i;
        }

        System.out.println("通过下标获取最大值:" + arr[max2]);
    }
}
  • 查询指定元素的位置
public class Test5 {
   
    public static void main(String[] args) {
   
        /**
         * 查询指定元素的位置
         */
        int[] arr = {
   12,34,56,7,3,10};

        //调用方法
        int index = getIndex(arr,56);
        if(index != -1)
            System.out.println("元素对应的索引:" + index);
        else //index = -1
            System.out.println("没有该元素!");
    }

    /**
     * 定义一个方法:查询数组中指定的元素对应的索引
     * 不确定因素:哪个数组,哪个指定元素(形参)
     * 返回值:索引
     */

    public static int getIndex(int[] arr,int ele){
   
        int index = -1;//这个初始值只要不是数组的索引即可
        for (int i = 0; i < arr.length; i++) {
   
            if(arr[i] == ele){
   
                index = i;//只要找到了元素,那么index就变成为1
                break;//只要找到这个元素,循环就停止
            }
        }

        return index;
    }
}

  • 添加元素
import java.util.Scanner;

public class Test5 {
   
    public static void main(String[] args) {
   
        /**
         * 添加元素
         */
        int[] arr = {
   12,34,56,7,3,10};

        //输出增加元素前的数组
        System.out.print("增加元素前的数组:");
        for (int i = 0; i < arr.length; i++) {
   
            if(i != arr.length - 1 )
                System.out.print(arr[i] + ",");
            else
                System.out.println(arr[i]);
        }

        //从键盘接收数据
        Scanner sc = new Scanner(System.in);
        System.out.print("请录入你要添加元素的指定下标:");
        int index = sc.nextInt();
        System.out.print("请录入你要添加的元素:");
        int ele = sc.nextInt();

        //增加元素
        //调用方法
        insertEle(arr,index,ele);
        /**
         * arr[5]=arr[4]
         * arr[4]=arr[3]
         * arr[3]=arr[2]
         *
         * 有规律的重复,可用循环解决
         */
//        int index = 1;
//        for(int i = arr.length - 1; i >= (index + 1);i--){
   
//            arr[i] = arr[i - 1];
//        }
//        arr[index] = 666;
        //输出增加元素后的数组
        System.out.print("增加元素后的数组:");
        for (int i = 0; i < arr.length; i++) {
   
            if(i != arr.length - 1 )
                System.out.print(arr[i] + ",");
            else
                System.out.println(arr[i]);
        }
    }

    /**
     * 提取一個添加元素的方法:
     * 在数组的指定位置上添加一个指定的元素
     * 在哪个数组的哪个位置添加哪个元素
     * 不确定因素:形参;哪个数组;哪个位置;哪个元素
     * 返回值:无
     * @param arr
     */
    public static void insertEle(int[] arr,int index,int ele){
   
        for(int i = arr.length - 1; i >= (index + 1);i--){
   
            arr[i] = arr[i - 1];
        }

        arr[index] = ele;
    }
}
  • 删除指定元素
import java.util.Arrays;

public class Test5 {
   
    public static void main(String[] args) {
   
        /**
         * 添加元素
         */
        int[] arr = {
   12,34,56,7,3,10};

        //输出删除元素前的数组
        System.out.print("删除元素前的数组:");
        System.out.println(Arrays.toString(arr));

        //找到要删除的元素对应的索引即可:
        int index = -1;
        for(int i = 0;i < arr.length;i++){
   
            if(arr[i] == 3){
   
                index = i;
                break;
            }
        }

        //删除元素
        //调用方法

        /**
         * arr[2]=arr[3]
         * arr[3]=arr[4]
         * arr[4]=arr[5]
         * arr[5]=0
         *
         * 有规律的重复,可用循环解决
         */
        if(index != -1){
   
            for(int i = index;i <= arr.length - index;i++){
   
                arr[i] = arr[i + 1];
            }
            arr[arr.length - 1] = 0;
        }else{
   
            System.out.println("没有你要删除的元素!!!");
        }


        //输出增加元素后的数组
        System.out.print("增加元素后的数组:");
        System.out.println(Arrays.toString(arr));
    }
}
  • 数组冒泡排序
import java.util.Arrays;

public class test {
   
    public static void main(String[] args) {
   
        /**
         *  数组冒泡排序
         *
         *      分析:
         *          1、冒泡排序的轮次:arr.length - 1,可确定外循环需要循环的次数
         *          2、冒泡排序过程中,第i轮需比较元素的次数:arr.length - i,可确定内循环需要循环的次数
         */
        int[] arr = {
   2,8,9,2,7,3,0,8,3,1,4};

        for(int i = 1;i < arr.length;i++){
   
            for(int j = 1;j < arr.length - i + 1;j++){
   
                if(arr[j - 1] > arr[j]){
   
                    //追尾法实现值交换
                    int temp = arr[j - 1];
                    arr[j - 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        //打印排序后的数组
        System.out.println(Arrays.toString(arr));
    }
}

在这里插入图片描述
扩展

  • 时间复杂度
    A、时间复杂度:找重复执行的这段代码,将这段代码的执行时间认为是单位1,那么执行这个单位1的次数就是时间复杂度(用O()表示)----习惯上,只考虑最高阶,不考虑系数
    B、冒泡排序的时间复杂度:O(n^2)
    C、时间复杂度符合形式:n^x(logn)^x,n^x(logn)^y
    在这里插入图片描述
  • 空间复杂度
    A、在已知条件下,执行这段代码需要额外耗费的空间数量
    • 以冒泡为例解释:数组长度随意变化的情况下,冒泡排序只需要3个变量,不随长度变化而变化。3 = 3 * n ^0 ->n ^0------空间复杂度为:O(1)

注意:时间复杂度不决定时间的长短,决定的是次数的多少。

  • 数组选择排序
import java.util.Arrays;

public class test {
   
    public static void main(String[] args) {
   
        /**
         *  数组选择排序
         *
         *      分析:
         *          1、选择排序的轮次:arr.length - 1,可确定外循环需要循环的次数
         *          2、选择排序过程中,第i轮选择的下标:i - 1
         *          3、要比较的下标:i -> arr.length - 1(控制要比较的下标)
         */
        int[] arr = {
   2,8,9,2,7,3,0,8,3,1,4};

        //控制轮数
        for(int i = 1;i < arr.length;i++){
   
            //控制要比较的下标
            for(int j = i; j < arr.length;j++){
   
                //判断选择的下标与要比较的下标数组元素大小
                if(arr[i - 1] > arr[j]){
   
                    //交换值
                    int temp = arr[i - 1];
                    arr[i - 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        //打印排序的结果
        System.out.println(Arrays.toString(arr));
    }
}

在这里插入图片描述
扩展`:

  • 时间复杂度
    A、选择排序的时间复杂度:O(n^2)

  • 空间复杂度
    A、选择排序的空间复杂度为:O(1)

5.2.5 数组的反转

  • 传统方法:创建新数组,从原数组倒着拿,往新数组正着放,时间复杂度:O(n);空间复杂度:O(n)
  • 首尾交换法:时间复杂度:O(n);空间复杂度:O(1)
应用案例
  • 数组反转
import java.util.Arrays;

public class test {
   
    public static void main(String[] args) {
   
        /**
         *  数组的反转
         *
         *      分析:
         *          1、首尾交换法实现
         */
        int[] arr = {
   2,8,9,2,7,3,0,8,3,1,4};

        for(int i = 0,j = arr.length - 1;i < j;i++,j--){
   
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        //打印排序的结果
        System.out.println(Arrays.toString(arr));
    }
}

5.2.6 数组元素的查找

  • 数组无序的情况,逐个遍历比较
应用案例
public class test {
   
    public static void main(String[] args) {
   
        /**
         *  数组无序的情况下,二分法查找数组元素的索引
         *
         */
        int[] arr = {
   2,8,9,2,7,3,0,8,3,1,4};
        
        int num = 9;
        for(int i = 0;i < arr.length;i++){
   
            if(arr[i] == num){
   
                System.out.println("数组中的 " + num + " 所在的索引为:" + i);
            }
        }
    }
}
  • 数组有序的情况,使用二分法查找,时间复杂度:O(logn);空间复杂度:O(1)
应用案例
public class test {
   
    public static void main(String[] args) {
   
        /**
         *  数组有序的情况下,查找数组元素的索引
         *
         */
        int[] arr = {
   14,26,37,58,64,68,82,90};
        int num = 58;

        //记录最小值的下标
        int min = 0;

        //记录最大值的下标
        int max = arr.length - 1;

        //计算中间值的下标
        int mid = (min + max)/2;
        
		//方式一:
        while(arr[mid] != num){
   
            if (num > arr[mid]) min = mid + 1;
            else max = mid - 1;

            if(min > max){
   
                mid = -1;
                break;
            }
            mid = (min + max)/2;
        }
        System.out.println("数组中的 " + num + " 所在的索引为:" + mid);

		//方法二:
        while(min <= max){
   
            if(num == arr[mid]) break;
            else if(num > arr[mid]) min = mid + 1;
            else max = mid - 1;
            mid = (min + max)/2;
        }
        System.out.println("数组中的 " + num + " 所在的索引为:" + mid);
    }
}

在这里插入图片描述

5.2.7 数组的复制

  • 数组复制
System.arraycopy(源数组,复制源数组元素的起始下标,目标数组,目标数组的起始下标,要复制的长度);
  • 数组扩容
    本质上是在做数组的复制过程,复制完成之后一定是产生了一个的数组
Arrays.copyOf(源数组,改变源数组长度);
应用案例
import java.util.Arrays;

public class test {
   
    public static void main(String[] args) {
   
        int[] arr1 = {
   5,6,9,11,6,3,8,4,18};
        int[] arr2 = new int[5];

        /**
         *  数组的复制
         */
        System.arraycopy(arr1,3,arr2,1,3);

        for (int i : arr2) {
   
            System.out.println(i);
        }

        /**
         *  数组的扩容
         *
         *     实际上数组的扩容本质上就是数组的复制过程
         *     System.arraycopy(arr1,0,newArr,0,arr1.length); //数组的复制
         *     arr1 = newArr; //把复制的新数组的内存地址赋给arr1
         *
         *     ============================================
         *     底层对数组扩容时,有做数组长度的判断,扩容的最小数组长度遵循小者优先
         *          int[] newArr = new int[len];
         *          int min = arr1.length > len ? len : arr1.length;
         */

        /**
         * arr1.length < len,因此新数组的长度为arr1.length,
         * 扩容后数组长度为arr1.length;
         * 此种情况:扩容
         */
        arr1 = Arrays.copyOf(arr1,15);

        /**
         *  arr1.length > len ,因此新数组的长度为len,
         *  扩容后数组长度为5
         *  此种情况:缩容
         */
        // arr1 = Arrays.copyOf(arr1,5);
    }
}

5.2.8 main方法

在这里插入图片描述
在这里插入图片描述

5.2.9 可变参数

  • JDK1.5出现的新特性
  • 作用提供一个方法,参数的个数是可变的
  • 解决了部分方法的重载问题
  • 方法的内部对可变参数的处理跟数组是一样的
  • 可变参数和其他数据一起作为形参的时候,可变参数一定要放在最后
public class Test5 {
   
    /**
     * 可变参数:作用提供一个方法,参数的个数是可变的
     * int... num
     * double... num
     * 作用:解决了部分方法的重载问题
     * @param args
     */
    public static void main(String[] args) {
   
        method01(10);
        method01();
        method01(20,30,40);
        method01(new int[]{
   11,2,33,44});
    }

    public static void method01(int... num){
   
        System.out.println("------------1");

        for (int i : num) {
   
            System.out.print(i + "\t");
        }
        System.out.println();
    }
}

5.2.10 Arrays

import java.util.Arrays;

public class Test5 {
   
    public static void main(String[] args) {
   
        //给定一个数组
        int[] arr = {
   1,3,7,2,4,8};

        //toString:对数组进行遍历查看的,返回的是一个字符串,这个字符串比较好看
        System.out.println(Arrays.toString(arr));

        //binarySearch:二分法查找,使用这个方法前提:一定是一个有序的数组
        Arrays.sort(arr);
        System.out.println(Arrays.binarySearch(arr,4));

        //copyOf:完成数组的复制
        int[] arr2 = {
   1,3,7,2,4,8};
        int[] newArr = Arrays.copyOf(arr2,4);
        System.out.println(Arrays.toString(newArr));

        //copyOfRange:区间复制
        int[] newArr2 = Arrays.copyOfRange(arr2,1,4); //[1,4)--->1~3位置
        System.out.println(Arrays.toString(newArr2));

        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值