java基础

什么是JDK,JRE

JDK 基本介绍

  • 1) JDK 的全称(JavaDevelopment Kit Java 开发工具包) JDK =JRE+java 的开发工具 [java,javac,javadoc,javap 等]
  • 2) JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE。所以安装了JDK,就不用在单独 安装JRE了。

JRE 基本介绍

  • 1) JRE(Java Runtime Environment JRE =JVM+Java 的核心类库[类] Java 运行环境)
  • 2) 包括Java虚拟机(JVMJavaVirtual Machine)和 Java 程序所需的核心类库等,如果想要运行一个开发好的Java程序, 计算机中只需要安装JRE即可。

JDK、JRE 和 JVM的包含关系

  • 1) JDK=JRE+ 开发工具集(例如Javac,java编译工具等)
  • 2) JRE=JVM+JavaSE标准类库(java核心类库)
  • 3) 如果只想运行开发好的 .class文件 只需要JRE

Java执行流程分析

java的数据类型

  • 1.java数据类型分为两大类基本数据类型,引用类型
  • 2.基本数据类型有8中数值型[byte,short,int,long,float,double]char,boolean
  • 3.引用类型[类,接口,数组]

整数类型 

整型的使用细节
  • Java各整数类型有固定的范围和字段长度,不受具体OS[操作系统]的影响,以保证java程序的可移植性。
  • Java的整型常量(具体值)默认为int型,声明long型常量须后加'l'或L
  • java程序中变量常声明为int型,除非不足以表示大数,才使用long
  • bit: 计算机中的最小存储单位。byte:计算机中基本存储单元,1byte =8 bit。[二进制再详细说]
  • 思考题:long 类型,有几个 bit[8个字节*8bit= 64]

浮点类型

说明一下

  • 1) 关于浮点数在机器中存放形式的简单说明,浮点数=符号位+指数位+尾数位
  • 2) 尾数部分可能丢失,造成精度损失(小数都是近似值)。
浮点型使用细节
  1. 与整数类型类似,Java 浮点类型也有固定的范围和字段长度,不受具体OS的影响。[float 4 个字节 double 是 8个字节]
  2. Java 的浮点型常量(具体值)默认为double型,声明float型常量,须后加'f’或'F'
  3. 浮点型常量有两种表示形式
    十进制数形式:如:5.12 512.0f .512(必须有小数点)
    科学计数法形式:如:5.12e2[5.12*10的2次方]5.12E-2[5.12/10的2次方]
  4. 通常情况下,应该使用double型,因为它比float型更精确。[举例说明]
    double num9 = 2.1234567851;
    float num10 = 2.1234567851F;
  5. 浮点数使用陷阱当我们对运算结果是小数的进行相等判断时要小心,例:2.7和8.1 / 3 比较

字符类型(char)

字符类型可以表示单个字符,字符类型是 char,char是两个字节(可以存放汉字),多个字符我们用字符串 String

字符类型使用细节
  1. 字符常量是用单引号( ' ' )括起来的单个字符。例如:char c1 ='a'; char c2 ='中';char c3 = '9';
  2. Java中还允许使用转义字符 '\' 来将其后的字符转变为特殊字符型常量。例如:char c3= '\n' ;// '\n'表示换行符
  3. 在java中,char的本质是一个整数,在输出时,是unicode码对应的字符。
    Unicode编码转换工具,ASCII与Unicode互转-站长工具 (wujingquan.com)http://tool.chinaz.com/ Tools/Unicode.aspx
  4. 可以直接给char赋一个整数,然后输出时,会按照对应的unicode 字符输出[97 -> a]
  5. char类型是可以进行运算的,相当于一个整数,因为它都对应有Unicode码

字符编码

1、字符型 存储到 计算机中,需要将字符对应的码值(整数)找出来,比如'a'
存储:'a' ==> 码值 97 ==> 二进制(110 0001) ==> 存储:
读取:二进制(110 0001) => 97 ===> 'a' => 显示

2、字符和码值的对应关系是通过字符编码表决定的(是规定好)

介绍一下字符编码表[sublime测试]
  • ASCII (ASCII编码表 一个字节表示,一个128个字符,实际上一个字节可以表示256个字符,只用128个)
  • Unicode (Unicode 编码表 固定大小的编码 使用两个字节来表示字符,字母和汉字统一都是占用两个字节,这样浪费空间)
  • utf-8(编码表,大小可变的编码 字母使用1个字节,汉字使用3个字节)
  • gbk(可以表示汉字,而且范围广,字母使用1个字节,汉字2个字节)
  • gb2312(可以表示汉字,gb2312<gbk)
  • big5 码(繁体中文,台湾,香港)
ASCII码介绍(了解)
  • ASCII:上个世纪60年代,美国制定了一套字符编码(使用一个字节),对英语字符与二进制位之间的关系,做了统一的规定。这被称为ASCII码。ASCII码一共规定了128个字符的编码,只占用了一个字节的后面7位,最前面的1位同一规定为0。
    特别提示:一个字节可以表示256个字符,ASCII码只用了 128个字符
  • 看一个完整的ASCII码表[资料中]
  • 缺点:不能表示所有字符
 Unicode编码介绍(了解)
  • Unicode的好处:一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,使用 Unicode 没有乱码的问题。
  • Unicode 的缺点:一个英文字母和一个汉字都占用2个字节,这对于存储空间来说是浪费。
  • 2的16次方是 65536,所以最多编码是65536个字符。
  • 编码0-127的字符是与ASCI的编码一样.比如'a'在ASCII码是 0x61,在unicode码是ox0061,都对应97.因此 Unicode码兼容 ASCII码.
UTF-8编码介绍(了解)
  • UTF-8 是在互联网上使用最广的一种 Unicode 的实现方式(改进)
  • UTF-8 是一种变长的编码方式。它可以使用 1-6 个字节表示一个符号,根据不同的符号而变化字节长度。
  • 使用 大小可变的编码 字母占1个字节汉字占3个字节

布尔类型:boolean

  • 布尔类型也叫boolean类型,booolean类型数据只允许取值true和false,无null

  • boolean类型占1个字节。

  • boolean 类型适于逻辑运算,一般用于程序流程控制

  • 不可以用0或非0的整数替代false和true,这点和C语言不同

基本数据类型转换

自动类型转换

当java程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数据类型,这个就是自动类型转换。

数据类型按精度(容量)大小排序为(背,规则)

自动类型转换注意和细节
  1. 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。
  2. 当我们把精度(容量)大 的数据类型赋值给精度(容量)小 的数据类型时,就会报错,反之就会进行自动类型转换。
  3. (byte,short)和 char之间不会相互自动转换。
  4. byte,short,char 他们三者可以计算,在计算时首先转换为int类型。
  5. boolean 不参与转换
  6. 自动提升原则: 表达式结果的类型自动提升为 操作数中最大的类型

强制类型转换

自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符 ( ),但可能造成精度降低或溢出,格外要注意

强制类型转换细节说明
  • 当进行数据的大小从 大——>小,就需要使用到强制转换
  • 强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
  • char类型可以保存 int的常量值,但不能保存int的变量值,需要强转
  • byte和short,char类型在进行运算时,当做int类型处理。

基本数据类型和 String 类型的转换

介绍:在程序开发中,我们经常需要将基本数据类型转成String 类型。或者将String类型转成基本数据类型。

基本数据类型
语法:将基本类型的值 + ""即可

JavaApi文档

  • APl(Application Programming Interface,应用程序编程接口)是 Java 提供的基本编程接口(java提供的类还有相关的方法)。
    中文在线文档:https://www.matools.comhttps://www.matools.com/
  • Java语言提供了大量的基础类,因此 Oracle公司也为这些基础类提供了相应的API文档,用于告诉开发者如何使用这些类,以及这些类里包含的方法。
  • Java类的组织形式[!图]

运算符

运算符介绍:运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。

  • 1) 算术运算符
  • 2) 赋值运算符
  • 3) 关系运算符 [比较运算符]
  • 4) 逻辑运算符
  • 5) 位运算符 [需要二进制基础]
  • 6) 三元运算符

算术运算符

算术运算符是对数值类型的变量进行运算的,在Java程序中使用的非常多。

细节说明

  1. 对于除号"/",它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。例如:int x= 10/3,结果是 3
  2. 当对一个数取模时,可以等价 a%b=a-a/b*b, (注意:a%b当a是小数时,公式=a - (int) a / b * b)这样我们可以看到 取模的一个本质运算。
  3. 当 自增 当做-一个独立语言使用时,不管是 ++i; 还是 i++; 都是一样的,等价
  4. 当自增 当做表达式使用时j = ++i 等价 i = i + 1,j = i
  5. 当自增 当做表达式使用时j = i++ 等价 j = i,i = i + 1

关系运算符(比较运算符)

逻辑运算符

用于连接多个条件(多个关系表达式),最终的结果也是一个boolean值。

  • 1) 短路与 && , 短路或 |,取反 !
  • 2) 逻辑与 &,逻辑或 |,^ 逻辑异或

 && 和 & 使用区别
  • 1)&&短路与:如果第一个条件为 false,则第二个条件不会判断,最终结果为 false,效率高
  • 2)& 逻辑与:不管第一个条件是否为 false,第二个条件都要判断,效率低
  • 3)开发中, 我们使用的基本是使用短路与&&, 效率高
|| 和 | 使用区别
  • 1)||短路或:如果第一个条件为 true,则第二个条件不会判断,最终结果为 true,效率高
  • 2)| 逻辑或:不管第一个条件是否为 true,第二个条件都要判断,效率低
  • 3)开发中,我们基本使用 ||

赋值运算符

赋值运算符就是将某个运算后的值,赋给指定的变量。

赋值运算符的分类
√基本赋值运算符 = int a = 10;
√复合赋值运算符
+= ,-= ,*= , /= ,%= 等 , 重点讲解一个 += ,其它的使用是一个道理
a += b; [等价 a = a + b; ]
a -= b; [等价 a = a - b; ]

复合赋值运算符会进行类型转换。

//演示赋值运算符的使用
public class AssignOperator{
    public static void main(String[] args) {
        int n1 = 10;
        n1 += 4; // n1 = n1 + 4;
        System.out.println(n1); // 14
        n1 /= 3; // n1 = n1 / 3;
        System.out.println(n1); // 4
​
        //复合赋值运算符会进行类型转换
        byte b = 3;
        b += 2; // 等价 b = (byte)(b + 2);
        b++; // b = (byte)(b + 1);
    }
}

运算符优先级

  • 1) 运算符有不同的优先级,所谓优先级就是表达式运算中的运算顺序。如右表,上一行运算符总优先于下一行。
  • 2) 只有单目运算符、赋值运算符是从右向左运算的。

关键字

定义:被Java语言赋予了特殊含义,用做专门用途的字符串(单词)
特点:关键字中所有字母都为小写

进制(程序员的基本功)

进制介绍 对于整数,有四种表示方式:

  • 二进制:0,1,满2进1.以0b或0B开头。
  • 十进制:0-9,满10进1。
  • 八进制:0-7,满8进1.以数字0开头表示。
  • 十六进制:0-9及A(10)-F(15),满16进1.以0x或0X开头表示。此处的A-F不区分大小写。

进制的转换(基本功)

第一组:
1) 二进制转十进制
2) 八进制转十进制
3) 十六进制转十进制

第二组:
1) 十进制转二进制
2) 十进制转八进制
3) 十进制转十六进制  

第三组
1) 二进制转八进制
2) 二进制转十六进制

第四组
1) 八进制转二进制
2) 十六进制转二进制

二进制转换成十进制示例

规则:从最低位(右边)开始,将每个位上的数提取出来,乘以2的(位数-1)次方,然后求和。

案例:请将 0b1011 转成十进制的数

0b1011 = 1 * 2的(1-1)次方 + 1 * 2的(2-1)次方 + 0 * 2的(3-1)次方 + 1 * 2的(4-1)次方法= 1 + 2 + 0 + 8 = 11

八进制转换成十进制示例

规则:从最低位(右边)开始,将每个位上的数提取出来,乘以8的(位数-1)次方,然后求和。

案例:请将 0234 转成十进制的数 0234 = 4 * 8 ^ 0 + 3 * 8 ^ 1 + 2 * 8 ^ 2 = 4 + 24 + 128 = 156

十六进制转换成十进制示例

规则:从最低位(右边)开始,将每个位上的数提取出来,乘以 16 的(位数-1)次方,然后求和。

案例:请将 0x23A 转成十进制的数

0x23A = 10 * 16 ^ 0 + 3 * 16 ^ 1 + 2 * 16 ^ 2 = 10 + 48 + 512 = 570

十进制转换成二进制

规则:将该数不断除以 2,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的二进制。一个字节有8位。

案例:请将 34 转成二进制 = 0B00100010

十进制转换成八进制

规则:将该数不断除以8,直到商为0为止,然后将每步得到的余数倒过来,就是对应的八进制。 案例:请将 131 转成八进制 =>0203

十进制转换成十六进制

规则:将该数不断除以16,直到商为0为止,然后将每步得到的余数倒过来,就是对应的十六进制。

案例:请将 237 转成十六进制 =>0xED

二进制转换成八进制

规则:从低位开始,将二进制数每三位一组,转成对应的八进制数即可。

案例:请将 ob11010101 转成八进制 ob11(3)010(2)101(5) => 0325

二进制转换成十六进制

规则:从低位开始,将二进制数每四位一组,转成对应的十六进制数即可。

案例:请将 ob11010101 转成十六进制 ob1101(D)0101(5) = 0xD5

八进制转换成二进制

规则:将八进制数每1位,转成对应的一个3位的二进制数即可。

案例:请将 0237 转成二进制 02(010)3(011)7(111) = 0b10011111

十六进制转换成二进制

规则:将十六进制数每1位,转成对应的4位的一个二进制数即可。

案例:请将 0x23B 转成二进制0x2(0010)3(0011)B(1011) = 0b001000111011

原码、反码、补码

原码 :最高位是符号位,0代表正数,1代表负数,非符号位为该数字绝对值的二进制。

反码:正数的反码与原码一致,负数的反码是对原码按位取反,只是最高位(符号位)不变。 

补码:正数的补码与原码一致,负数的补码是对原码按位取反加1,符号位不变。

位运算符

java 中有 7 个位运算(&、|、 ^ 、~、>>、<<和 >>>)

还有3个位运算符 >>、>>和 >>>,运算规则:

  • 1) 算术右移 >>:低位溢出,符号位不变,并用符号位补溢出的高位
  • 2) 算术左移 >>:符号位不变,低位补0
  • 3) >>> 逻辑右移也叫无符号右移,运算规则是: 低位溢出,高位补 0
  • 4) 特别说明:没有 <<< 符号
应用案例

1)int a=1>>2; //1 => 00000001 => 00000000 本质 1 / 2 / 2 =0

2)int c=1<<2; //1 => 00000001 => 00000100 本质 1 * 2 * 2 = 4

键盘输入语句

在编程中,需要接收用户输入的数据,就可以使用键盘输入语句来获取。需要一个 扫描器(对象), 就是Scanner

步骤 :
  • 1) 导入该类的所在包, java.util.*
  • 2) 创建该类对象(声明变量)
  • 3) 调用里面的功能
案例演示:

要求:可以从控制台接收用户信息,【姓名,年龄,薪水】

import java.util.Scanner;//表示把java.util下的Scanner类导入
public class Input{
    public static void main(String[] args){
        //演示接受用户的输入
        //步骤
        //Scannner类 表示 简单文本扫描器,在java.util 包
        //1. 引入/导入 Scanner类所在的包
        //2. 创建 Scanner 对象 , new 创建一个对象
        //   myScanner 就是 Scanner类的对象
        Scanner myScanner = new Scanner(System.in);
        //3. 接受用户输入
        System.out.println("请输入名字");
        
        //当程序执行到 next 方法时,会等待用户输入
        String name = myScanner.next(); //接受用户输入字符串
        System.out.println("请输入年龄");
        int age = myScanner.nextInt(); //接受用户输入int
        System.out.println("请输入薪水");
        double sal = myScanner.nextDouble(); //接受用户输入double
        System.out.println("人的信息如下:");
        System.out.println("名字=" + name + "年龄" + age + "薪水" + sal);
    }
}

第5章 程序控制结构

在程序中,程序运行的流程控制决定程序是如何执行的,是我们必须掌握的,主要有三大流程控制语句。

1)顺序控制 2)分支控制 3)循环控制

switch注意事项和细节讨论

第6章数组、排序和查找

数组介绍

  • 数组可以存放多个同一类型的数据。
  • 数组也是一种数据类型,是引用类型。 即:数(数据)组(一组)就是一组数据

使用方式

使用方式1-动态初始化

使用方式2-动态初始化

先声明数组
语法:数据类型 数组名[];
也可以 数据类型[] 数组名; int a[]; 或者 int[] a;

创建数组
语法: 数组名=new 数据类型[大小]; a=new int[10];

使用方式3-静态初始化

数组使用注意事项和细节

  • 1) 数组是多个相同类型数据的组合,实现对这些数据的统一管理
  • 2) 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用。
  • 3) 数组创建后,如果没有赋值,有默认值 int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000,boolean false,String null
  • 4) 使用数组的步骤 1. 声明数组并开辟空间 2 给数组各个元素赋值 3 使用数组
  • 5) 数组的下标是从0开始的。
  • 6) 数组下标必须在指定范围内使用,否则报:下标越界异常,比如int [] arr=new int[5]; 则有效下标为 0-4
  • 7) 数组属引用类型,数组型数据是对象(object)
public class ArrayDetail {
    public static void main(String[] args) {
        //1. 数组是多个相同类型数据的集合,实现对这些数据的统一管理
        // int arr1[] = {1, 2, 3, 60, "hello"};//String -> int
        double arr2[] = {1.1, 2.2, 3.3, 60.6, 100};//int -> double
​
        //2. 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用
        String arr3[] = {"北京", "jack", "milan"};
​
        //3. 数组创建后,如果没有赋值,有默认值
        //int 0,short 0,byte 0,long 0,
        //float 0.0,double 0.0,char \u0000,
        //boolean false,String null
        //
        short arr4[] = new short[3];
        System.out.println("=====数组 arr4=====");
        for(int i = 0; i < arr4.length; i++){
            System.out.println(arr4[i]);
        }
​
        //6. 数组下标必须在指定范围内使用,否则报:下标越界异常,比如
        //int [] arr = new int[5];则有效下标为 0-4
        //即数组的下标/索引 最小 0最大 数组长度-1 (4)
        int arr[] = new int[5];
        //System.out.println(arr[5]);//数组越界
    }
}

 数组应用案例

创建一个char类型的26个元素的数组,分别放置'A'-'Z'。使用for循环访问所有元素并打印出来。提示:char类型 数据运算'A'+2->'C'

public class ArrayExercise01{
    public static void main(String[] args) {
        /*
        创建一个 char 类型的 26 个元素的数组,分别 放置'A'-'Z'。
        使用 for 循环访问所有元素并打印出来。
        提示:char 类型数据运算 'A'+1 -> 'B' 
        思路分析
        1. 定义一个 数组 char[] chars = new char[26]
        2. 因为 'A' + 1 = 'B' 类推,所以老师使用 for 来赋值
        3. 使用 for 循环访问所有元素
        */
        char chars[] = new char[26];
        for(int i = 0;i < chars.length; i++){
            //chars 是 char[]
            //chars[i] 是 char
            chars[i] = (char)('A' + i);//'A' + i 是 int , 需要强制转换
        }
        //循环输出
        System.out.println("===chars 数组===");
        for(int i = 0; i < c1.length;i++){
            System.out.print(c1[i]);
        }
    }
}
public class ArrayExercise02 {
    //编写一个 main 方法
    public static void main(String[] args) {
        //请求出一个数组 int[]的最大值 {4,-1,9, 10,23},并得到对应的下标
        //思路分析
        //1. 定义一个 int 数组 int[] arr = {4,-1,9, 10,23};
        //2. 假定 max = arr[0] 是最大值 , maxIndex=0;
        //3. 从下标 1 开始遍历 arr, 如果 max < 当前元素,说明 max 不是真正的
        // 最大值, 我们就 max=当前元素; maxIndex=当前元素下标
        //4. 当我们遍历这个数组 arr 后 , max 就是真正的最大值,maxIndex 最大值
        // 对应的下标
        int[] arr = {4,-1,9,10,23};
        int max = arr[0];//假定第一个元素就是最大值
        int maxIndex = 0; //
        for(int i = 1; i < arr.length; i++) {//从下标 1 开始遍历 arr
            if(max < arr[i]) {//如果 max < 当前元素
                max = arr[i]; //把 max 设置成 当前元素
                maxIndex = i;
            }
        }
        //当我们遍历这个数组 arr 后 , max 就是真正的最大值,maxIndex 最大值下标
        System.out.println("max=" + max + " maxIndex=" + maxIndex);
    }
}

数组赋值机制

1)基本数据类型赋值,这个值就是具体的数据,而且相互不影响。

int n1 = 2;

int n2 = n1;

2)数组在默认情况下是引用传递,赋的值是地址。

看一个案例,并分析数组赋值的内存图(重点, 难点. )。

//代码 ArrayAssign.java

int[] arr1 = {1,2,3};

int[] arr2 = arr1;

数组拷贝

编写代码 实现数组拷贝(内容复制)ArrayCopy.java 将 int[] arr1 = {10,20,30}; 拷贝到 arr2 数组, 要求数据空间是独立的.

public class ArrayCopy{
    public static void main(String[] args) {
        //将 int[] arr1 = {10,20,30}; 拷贝到arr2数组,
        //要求数据空间是独立的
        //
        int arr1[] = {10,20,30};
​
        //创建一个新的数组arr2,开辟新的数据空间
        //大小 arr1.length;
        int arr2[] = new int[arr1.length];
​
        //遍历 arr1,把每个元素拷贝到对应的元素位置
        for(int i = 0; i < arr1.length; i++){
            arr2[i] = arr1[i];
        }
        //修改 arr2, 不会对 arr1 有影响. 
        arr2[0] = 100;
        
        //输出 arr1
        System.out.println("====arr1 的元素====");
        for(int i = 0;i < arr1.length;i++){
            System.out.println(arr1[i]);//10,20,30
        }
        //
        System.out.println("====arr2 的元素====");
        for(int i = 0; i < arr2.length; i++) {
            System.out.println(arr2[i]);
        }
    }
}

数组反转

要求:把数组的元素内容反转。
ArrayReverse.java arr {11,22,33,44,55,66} {66,55,44,33,22,11}

public class ArrayReverse{
    public static void main(String[] args) {
        //定义数组
        int arr1[] = {11,22,33,44,55,66};
        //思路
        //规律
        //1. 把 arr[0] 和 arr[5] 进行交换 {66,22,33,44,55,11}
        //2. 把 arr[1] 和 arr[4] 进行交换 {66,55,33,44,22,11}
        //3. 把 arr[2] 和 arr[3] 进行交换 {66,55,44,33,22,11}
        //4. 一共要交换 3 次 = arr.length / 2
        //5. 每次交换时,对应的下标 是 arr[i] 和 arr[arr.length - 1 -i]
        //代码
        //优化
        int temp = 0;
        int len = arr.length; //计算数组的长度
        for( int i = 0; i < len / 2; i++) {
            temp = arr[len - 1 - i];//保存
            arr[len - 1 - i] = arr[i];
            arr[i] = temp;
        }
        System.out.println("===翻转后数组===");
        for(int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");//66,55,44,33,22,11
        }
    }
}

数组添加/扩容

要求:实现动态的给数组添加元素效果,实现对数组扩容。ArrayAdd.java

  • 1)原始数组使用静态分配int[]arr={1,2,3}
  • 2)增加的元素4,直接放在数组的最后arr={1,2,3,4}
  • 3)用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n
import java.util.Scanner;
public class ArrayAdd{
	public static void main(String[] args) {
        /*
        要求:实现动态的给数组添加元素效果,实现对数组扩容。ArrayAdd.java
        1.原始数组使用静态分配 int[] arr = {1,2,3}
        2.增加的元素 4,直接放在数组的最后 arr = {1,2,3,4}
        3.用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n
        思路分析
        1. 定义初始数组 int[] arr = {1,2,3}//下标 0-2
        2. 定义一个新的数组 int[] arrNew = new int[arr.length+1];
        3. 遍历 arr 数组,依次将 arr 的元素拷贝到 arrNew 数组
        4. 将 4 赋给 arrNew[arrNew.length - 1] = 4;把 4 赋给 arrNew 最后一个元素
        5. 让 arr 指向 arrNew ; arr = arrNew; 那么 原来 arr 数组就被销毁
        6. 创建一个 Scanner 可以接受用户输入
        7. 因为用户什么时候退出,不确定,老师使用 do-while + break 来控制
		*/
		Scanner scanner = new Scanner(System.in);
		int arr[] = {1,2,3};
		char answer = ' ';
		do {
			int[] arrNew = new int[arr.length + 1];
            //遍历 arr 数组,依次将 arr 的元素拷贝到 arrNew 数组
            for(int i = 0; i < arr.length; i++) {
            	arrNew[i] = arr[i];
            }
            System.out.println("请输入你要添加的元素");
            int addNum = myScanner.nextInt();
            //把 addNum 赋给 arrNew 最后一个元素
            arrNew[arrNew.length - 1] = addNum;
            //让 arr 指向 arrNew, arr = arrNew;
            //输出 arr 看看效果
            System.out.println("====arr 扩容后元素情况====");
            for(int i = 0; i < arr.length; i++) {
            	System.out.print(arr[i] + "\t");
            }
            //问用户是否继续
            System.out.println("是否继续添加 y/n");
            char key = myScanner.next().charAt(0);
            if( key == 'n') { //如果输入 n ,就结束
            	break;
            }
        }while(true);
        System.out.println("你退出了添加...");
		
	}
}

排序的介绍

排序是将多个数据,依指定的顺序进行排列的过程。 排序的分类:内部排序和外部排序

  • 内部排序:指将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、选择式排序法和插入式排序法);
  • 外部排序法: 数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法和直接合并排序法)。

冒泡排序法

冒泡排序(BubbleSorting)的基本思想是:通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素 的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。

public class BubbleSort {
    //编写一个 main 方法
    public static void main(String[] args) {
        //化繁为简,先死后活
        /*
            数组 [24,69,80,57,13]
            第 1 轮排序: 目标把最大数放在最后
            第 1 次比较[24,69,80,57,13]
            第 2 次比较[24,69,80,57,13]
            第 3 次比较[24,69,57,80,13]
            第 4 次比较[24,69,57,13,80]
        */
        int[] arr = {24, 69, 80, 57, 13, -1, 30, 200, -110};
        int temp = 0; //用于辅助交换的变量
        //将多轮排序使用外层循环包括起来即可
        //先死后活 =》 4 就是 arr.length - 1
        for( int i = 0; i < arr.length - 1; i++) {//外层循环是 4 次
            for( int j = 0; j < arr.length - 1 - i; j++) {//4 次比较-3 次-2次-1 次
                //如果前面的数>后面的数,就交换
                if(arr[j] > arr[j + 1]) {
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
            System.out.println("\n==第"+(i+1)+"轮==");
            for(int j = 0; j < arr.length; j++) {
                System.out.print(arr[j] + "\t");
            }
        }
        // for( int j = 0; j < 4; j++) {//4 次比较
        //  //如果前面的数>后面的数,就交换
        //  if(arr[j] > arr[j + 1]) {
        //      temp = arr[j];
        //      arr[j] = arr[j+1];
        //      arr[j+1] = temp;
        //  }
        // }
        // System.out.println("==第 1 轮==");
        // for(int j = 0; j < arr.length; j++) {
        //  System.out.print(arr[j] + "\t");
        // }
        // /*
        // 第 2 轮排序: 目标把第二大数放在倒数第二位置
        // 第 1 次比较[24,69,57,13,80]
        // 第 2 次比较[24,57,69,13,80]
        // 第 3 次比较[24,57,13,69,80]
        // */
        // for( int j = 0; j < 3; j++) {//3 次比较
        如果前面的数>后面的数,就交换
        //if(arr[j] > arr[j + 1]) {
        //temp = arr[j];
        //arr[j] = arr[j+1];
        //arr[j+1] = temp;
        //}
        //}
        // System.out.println("\n==第 2 轮==");
        // for(int j = 0; j < arr.length; j++) {
        // System.out.print(arr[j] + "\t");
        // }
        // 第 3 轮排序: 目标把第 3 大数放在倒数第 3 位置
        // 第 1 次比较[24,57,13,69,80]
        // 第 2 次比较[24,13,57,69,80]
        // for( int j = 0; j < 2; j++) {//2 次比较
        // //如果前面的数>后面的数,就交换
        // if(arr[j] > arr[j + 1]) {
        // temp = arr[j];
        // arr[j] = arr[j+1];
        // arr[j+1] = temp;
        // }
        // }
        // System.out.println("\n==第 3 轮==");
        // for(int j = 0; j < arr.length; j++) {
        // System.out.print(arr[j] + "\t");
        // }
        // /*
        // 第 4 轮排序: 目标把第 4 大数放在倒数第 4 位置
        // 第 1 次比较[13,24,57,69,80]
        // */
        // for( int j = 0; j < 1; j++) {//1 次比较
        // //如果前面的数>后面的数,就交换
        // if(arr[j] > arr[j + 1]) {
        // temp = arr[j];
        // arr[j] = arr[j+1];
        // arr[j+1] = temp;
        // }
        // }
        // System.out.println("\n==第 4 轮==");
        // for(int j = 0; j < arr.length; j++) {
        // System.out.print(arr[j] + "\t");
        // }
        }
}
 
//自己的方法
public class BubbleSort{
	public static void main(String[] args) {
		int a[] = {24,69,80,57,13};
		int temp = 0;
		for(int i = 0; i < a.length -1; i++){
			for(int j = i + 1;j < a.length ;j++){
				if(a[i] > a[j]){
					temp = a[j];
					a[j] = a[i];
					a[i] = temp;
				}
			}
		}
		for(int i = 0; i < a.length; i++){
		  	System.out.println(a[i]);
		 }
	}
}

查找

在java中,我们常用的查找有两种:

  • 1)顺序查找SeqSearch.java
  • 2)二分查找

案例演示:

1)有一个数列:白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王猜数游戏:从键盘中任意输入一个名称,判断数列中是否 包含此名称【顺序查找】要求:如果找到了,就提示找到,并给出下标值。

import java.util.Scanner;
public class SeqSearch {
        //编写一个 main 方法
        public static void main(String[] args) {
        /*
        有一个数列:白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王猜数游戏:
        从键盘中任意输入一个名称,判断数列中是否包含此名称【顺序查找】
        要求: 如果找到了,就提示找到,并给出下标值
        思路分析
        1. 定义一个字符串数组
        2. 接收用户输入, 遍历数组,逐一比较,如果有,则提示信息,并退出
        */
        //定义一个字符串数组
        String[] names = {"白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"};
        Scanner myScanner = new Scanner(System.in);
        System.out.println("请输入名字");
        String findName = myScanner.next();
        //遍历数组,逐一比较,如果有,则提示信息,并退出
        //这里老师给大家一个编程思想/技巧, 一个经典的方法
        int index = -1;
        for(int i = 0; i < names.length; i++) {
            //比较 字符串比较 equals, 如果要找到名字就是当前元素
            if(findName.equals(names[i])) {
                System.out.println("恭喜你找到 " + findName);
                System.out.println("下标为= " + i);
                //把 i 保存到 index
                index = i;
                break;//退出
            }
        }
        if(index == -1) { //没有找到
        	System.out.println("sorry ,没有找到 " + findName);
        }
    }
}

多维数组-二维数组

多维数组我们只介绍二维数组。 二维数组的应用场景

使用方式1:动态初始化

  • 1)语法:类型[][] 数组名=new 类型[大小][大小]
  • 2)比如:int a[][]=new int[2][3]
  • 3)使用演示
  • 4)二维数组在内存的存在形式(!!画图
public class TwoDimensionalArray01 {
    //编写一个 main 方法
    public static void main(String[] args) {
        /*
        请用二维数组输出如下图形
            0 0 0 0 0 0
            0 0 1 0 0 0
            0 2 0 3 0 0
            0 0 0 0 0 0
        */
        //什么是二维数组:
        //解读
        //1. 从定义形式上看 int[][]
        //2. 可以这样理解,原来的一维数组的每个元素是一维数组, 就构成二维数组
    	int[][] arr = { {0, 0, 0, 0, 0, 0},
    					{0, 0, 1, 0, 0, 0}, 
    					{0, 2, 0, 3, 0, 0}, 
    					{0, 0, 0, 0, 0, 0} };
        //关于二维数组的关键概念
        //(1)
        System.out.println("二维数组的元素个数=" + arr.length);
        //(2) 二维数组的每个元素是一维数组, 所以如果需要得到每个一维数组的值
        // 还需要再次遍历
        //(3) 如果我们要访问第 (i+1)个一维数组的第 j+1 个值 arr[i][j];
        // 举例 访问 3, =》 他是第 3 个一维数组的第 4 个值 arr[2][3]
        System.out.println("第 3 个一维数组的第 4 个值=" + arr[2][3]); //3
        
        //输出二维图形
        for(int i = 0; i < arr.length; i++) {//遍历二维数组的每个元素
            //遍历二维数组的每个元素(数组)
            //解读
            //1. arr[i] 表示 二维数组的第 i+1 个元素 比如 arr[0]:二维数组的第一个元素
            //2. arr[i].length 得到 对应的 每个一维数组的长度
            for(int j = 0; j < arr[i].length; j++) {
            	System.out.print(arr[i][j] + " "); //输出了一维数组
        	}
        	System.out.println();//换行
        }
    }
}

使用方式2: 动态初始化

  • 先声明:类型 数组名[][]; TwoDimensionalArray02.java
  • 再定义(开辟空间) 数组名 =new 类型[大小][大小]
  • 赋值(有默认值,比如int 类型的就是0)

使用方式3: 动态初始化-列数不确定

public class TwoDimensionalArray03 {
    //编写一个 main 方法
    public static void main(String[] args) {
        /*
        看一个需求:动态创建下面二维数组,并输出
        i = 0: 1
        i = 1: 2 2
        i = 2: 3 3 3 一个有三个一维数组, 每个一维数组的元素是不一样的
        */
        //创建 二维数组,一个有 3 个一维数组,但是每个一维数组还没有开数据空间
        int[][] arr = new int[3][];
        for(int i = 0; i < arr.length; i++) {//遍历 arr 每个一维数组
            //给每个一维数组开空间 new
            //如果没有给一维数组 new ,那么 arr[i]就是 null
            arr[i] = new int[i + 1];
            //遍历一维数组,并给一维数组的每个元素赋值
            for(int j = 0; j < arr[i].length; j++) {
                arr[i][j] = i + 1;//赋值
            }
        }
        System.out.println("=====arr 元素=====");
        //遍历 arr 输出
        for(int i = 0; i < arr.length; i++) {
            //输出 arr 的每个一维数组
            for(int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();//换行
        }
    }
}

使用方式4:静态初始化

定义 类型 数组名[] [] = {{值 1,值 2..},{值 1,值 2..},{值 1,值 2..}}

使用即可 [ 固定方式访问 ]

比如:  int[] [] arr = {{1,1,1}, {8,8,9}, {100}};

解读

  1. 定义了一个二维数组 arr
  2. arr 有三个元素(每个元素都是一维数组)
  3. 第一个一维数组有 3 个元素 , 第二个一维数组有 3 个元素, 第三个一维数组有 1 个元素

案例:

intarr[][]={{4,6},{1,4,5,7},{-2}};遍历该二维数组,并得到和

public class TwoDimensionalArray05 {
    //编写一个 main 方法
    public static void main(String[] args) {
        /*
        int arr[][]={{4,6},{1,4,5,7},{-2}}; 遍历该二维数组,并得到和
        思路
        1. 遍历二维数组,并将各个值累计到 int sum
        */
        int arr[][]= {{4,6},{1,4,5,7},{-2}};
        int sum = 0;
        for(int i = 0; i < arr.length; i++) {
            //遍历每个一维数组
            for(int j = 0; j < arr[i].length; j++) {
            sum += arr[i][j];
            }
        }
        System.out.println("sum=" + sum);
    }
}

二维数组的应用案例----杨辉三角

1)使用二维数组打印一个10行杨辉三角YangHui.java

public class YangHui {
    //编写一个 main 方法
    public static void main(String[] args) {
        /*
        使用二维数组打印一个 10 行杨辉三角
        1
        1 1
        1 2 1
        1 3 3 1
        1 4 6 4 1
        1 5 10 10 5 1
        规律
        1.第一行有 1 个元素, 第 n 行有 n 个元素
        2. 每一行的第一个元素和最后一个元素都是 1
        3. 从第三行开始, 对于非第一个元素和最后一个元素的元素的值. arr[i][j]
        arr[i][j] = arr[i-1][j] + arr[i-1][j-1]; //必须找到这个规律
        */
        int[][] yangHui = new int[12][];
        for(int i = 0; i < yangHui.length; i++) {//遍历 yangHui 的每个元素
            //给每个一维数组(行) 开空间
            yangHui[i] = new int[i+1];
            //给每个一维数组(行) 赋值
            for(int j = 0; j < yangHui[i].length; j++){
                //每一行的第一个元素和最后一个元素都是 1
                if(j == 0 || j == yangHui[i].length - 1) {
                    yangHui[i][j] = 1;
                } else {//中间的元素
                    yangHui[i][j] = yangHui[i-1][j] + yangHui[i-1][j-1];
                }
            }
        }
        //输出杨辉三角
        for(int i = 0; i < yangHui.length; i++) {
            for(int j = 0; j < yangHui[i].length; j++) {//遍历输出该行
                System.out.print(yangHui[i][j] + "\t");
            }
            System.out.println();//换行. 
        }
    }
}

二维数组使用细节和注意事项

1)一维数组的声明方式有: int[] x或者int x[]

2)二维数组的声明方式有: int[][] y 或者int[] y[] 或者 int y[][]

3)二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同。比如:map[][]是 一个二维数组
int map[][]={{1,2},{3,4,5}} 由map[0]是一个含有两个元素的一维数组,map[1]是一个含有三个元素的一维数组构成,我们也称为列数不等 的二维数组

下一篇

Java-面向对象编程(基础部分)-CSDN博客

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐