尚硅谷 java 2023(基础语法)笔记

一、变量与运算符

1、HelloWorld的编写和执行

class HelloChina{
    public static void main(String[] args){
        System.out.println("hello,world!!你好,中国!");
    }
}

总结:
1. Java程序编写和执行的过程:
步骤1:编写。将Java代码编写在.java结尾的源文件中
步骤2:编译。针对于.java结尾的源文件进行编译操作。 格式:javac 源文件名.java
步骤3:运行。针对于编译后生成的字节码文件,进行解释运行。 格式: java 字节码文件名


2. 针对于步骤1的编写进行说明。

class HelloChina{
    public static void main(String[] args){
        System.out.println("hello,world!!你好,中国!");
    }
}

其中,
① class:关键字,表示"类",后面跟着类名。
② main()方法的格式是固定的。务必记住!表示程序的入口
  public static void main(String[] args)  

如果非要有些变化的话,只能变化String[] args结构。可以写成:方式1:String args[]   方式2:String[] a

args:全程是arguments,简写成args

③ Java程序,是严格区分大小写的。

④ 从控制台输出数据的操作:
System.out.println() : 输出数据之后,会换行。
System.out.print() : 输出数据之后,不会换行。


⑤ 每一行执行语句必须以;结束。


3. 针对于步骤2的编译进行说明。

① 如果编译不通过。可以考虑的问题:
问题1:查看编译的文件名、文件路径是否书写错误
问题2:查看代码中是否存在语法问题。如果存在,就可能导致编译不通过。

② 编译以后,会生成1个或多个字节码文件。每一个字节码文件对应一个Java类,并且字节码文件名与类名相同。


4. 针对于步骤3运行进行说明。

① 我们是针对于字节码文件对应的Java类进行解释运行的。
要注意区分大小写!

② 如果运行不通过。可以考虑的问题:
问题1:查看解释运行的的类名、字节码文件路径是否书写错误
问题2:可能存在运行时异常。(放到第9章中具体讲解)


5. 一个源文件中可以声明多个类,但是最多只能有一个类使用public进行声明。
且要求声明为public的类的类名与源文件名相同。

2、 单行注释和多行注释 

/*
这是多行注释。

我们可以声明多行注释的信息!


1. Java中的注释的种类:
单行注释 、 多行注释 、 文档注释(Java特有)

2. 单行注释、多行注释的作用:
① 对程序中的代码进行解释说明
② 对程序进行调试

3. 注意:
① 单行注释和多行注释中声明的信息,不参与编译。换句话说,编译以后声明的字节码文件中不包含单行注释和
多行注释中的信息。
② 多行注释不能嵌套使用

4. 文档注释:
文档注释内容可以被JDK提供的工具 javadoc 所解析,生成一套以网页文件形式体现的该程序的说明文档。

*/
/**
这是我的第一个Java程序。很开森!^_^

@author shkstart
@version 1.0

*/
public class CommentTest{
	/**
	这是main()方法。格式是固定的。(文档注释)
	*/
	/*
	这是main()方法。格式是固定的。(多行注释)
	*/
	public static void main(String[] args){
		//这是输出语句
		System.out.println("hello,world!!");
		//System.out.println("hello,world!!")
	}
}

3、两个案例的具体实现

案例一:

class PersonalInfo{
	public static void main(String[] args) {
	    System.out.println("姓名:斯内克");
		System.out.println(); //换行的操作
		System.out.println("性别:男");
		System.out.println("家庭住址:北京市");
	}
}

 案例二

class StarPrintTest {
	public static void main(String[] args) {
		System.out.println("*    *");
		System.out.println("*\t\t*");
		System.out.println("*\n\n*");
	}
}

4、标识符

/*
测试标识符的使用

1. 什么是标识符?Java中变量、方法、类等要素命名时使用的字符序列,称为标识符。

技巧:凡是自己可以起名字的地方都叫标识符。比如:类名、方法名、变量名、包名、常量名等

2. 标识符的命名规则 (必须要遵守!!否则,编译不通过)
> 由26个英文字母大小写,0-9 ,_或 $ 组成
> 数字不可以开头。
> 不可以使用关键字和保留字,但能包含关键字和保留字。
> Java中严格区分大小写,长度无限制。
> 标识符不能包含空格。

3.标识符的命名规范(建议遵守。如果不遵守,编译和运行都能正常执行。只是容易被人鄙视)
> 包名:多单词组成时所有字母都小写:xxxyyyzzz。
  例如:java.lang、com.atguigu.bean
  
> 类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz
  例如:HelloWorld,String,System等
  
> 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz
  例如:age,name,bookName,main,binarySearch,getName
  
> 常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ
  例如:MAX_VALUE,PI,DEFAULT_CAPACITY

说明:大家在定义标识符时,要注意“见名知意”
*/

class IdentifierTest{
	public static void main(String[] args){
		
		int abc = 12;
		int age = 12; //age :标识符


		char gender = '男';

		char c1 = '女';
		
		//不推荐的写法
		//int myage = 12;

		//System.out.println(myage);

		int myAge = 12;
		
	}

	public static void main1(String[] args){
		
	}
}


class _a$bc{
}

/*
class 1abc{
}
*/

class Public{
}

class publicstatic{
}

class BiaoShiFuTest{
}

5、变量的基本使用

/*
测试变量的基本使用

1. 变量的理解:内存中的一个存储区域,该区域的数据可以在同一类型范围内不断变化

2. 变量的构成包含三个要素:数据类型、变量名、存储的值

3. Java中变量声明的格式:数据类型 变量名 = 变量值

4. Java中的变量按照数据类型来分类:
    基本数据类型(8种):
        整型:byte \ short \ int \ long 
        浮点型:float \ double 
        字符型:char
        布尔型:boolean

    引用数据类型:
        类(class)
        数组(array)
        接口(interface)

        枚举(enum)
        注解(annotation)
        记录(record)

5. 定义变量时,变量名要遵循标识符命名的规则和规范。

6. 说明:
① 变量都有其作用域。变量只在作用域内是有效的,出了作用域就失效了。
② 在同一个作用域内,不能声明两个同名的变量
③ 定义好变量以后,就可以通过变量名的方式对变量进行调用和运算。
④ 变量值在赋值时,必须满足变量的数据类型,并且在数据类型有效的范围内变化。

*/

class VariableTest {
	public static void main(String[] args) {
		
		
		//定义变量的方式1:
		char gender; //过程1:变量的声明
		gender = '男'; //过程2:变量的赋值(或初始化)

		gender = '女';
		
		//定义变量的方式2:声明与初始化合并
		int age = 10;


		System.out.println(age);
		System.out.println("age = " + age);
		System.out.println("gender = " + gender);

		//在同一个作用域内,不能声明两个同名的变量
		//char gender = '女';

		gender = '男';
		
		//由于number前没有声明类型,即当前number变量没有提前定义。所以编译不通过。
		//number = 10;

		byte b1 = 127;
		//b1超出了byte的范围,编译不通过。
		//b1 = 128;

	}

	public static void main123(String[] args) {
		//System.out.println("gender = " + gender);

		char gender = '女';
		
	}
}

6、整形数据类型的使用

① 声明long类型变量时,需要提供后缀。后缀为'l'或'L'

② 开发中,大家定义整型变量时,没有特殊情况的话,通常都声明为int类型。
 

class VariableTest1 {
	public static void main(String[] args) {
		
		//1.测试整型变量的使用
		// byte(1字节=8bit) \ short(2字节) \ int(4字节) \ long(8字节) 

		byte b1 = 12;
		byte b2 = 127;
		//编译不通过。因为超出了byte的存储范围
		//byte b3 = 128;

		short s1 = 1234;

		int i1 = 123234123;
		//① 声明long类型变量时,需要提供后缀。后缀为'l'或'L'
		long l1 = 123123123L;

		//② 开发中,大家定义整型变量时,没有特殊情况的话,通常都声明为int类型。
}
}

7、浮点类型的使用与练习

//2.测试浮点类型变量的使用
        //float \ double
        double d1 = 12.3;
        //① 声明long类型变量时,需要提供后缀。后缀为'f'或'F'
        float f1 = 12.3f;
        System.out.println("f1 = " + f1);

        //② 开发中,大家定义浮点型变量时,没有特殊情况的话,通常都声明为double类型,因为精度更高。

        //③ float类型表数范围要大于long类型的表数范围。但是精度不高。

        //测试浮点型变量的精度
        //结论:通过测试发现浮点型变量的精度不高。如果在开发中,需要极高的精度,需要使用BigDecimal类替换浮点型变量。
        //测试1
        System.out.println(0.1 + 0.2);

        //测试2:
        float ff1 = 123123123f;
        float ff2 = ff1 + 1;
        System.out.println(ff1);
        System.out.println(ff2);
        System.out.println(ff1 == ff2);

class VariableTest1 {
	public static void main(String[] args) {
		
		//2.测试浮点类型变量的使用
		//float \ double
		double d1 = 12.3;
		//① 声明long类型变量时,需要提供后缀。后缀为'f'或'F'
		float f1 = 12.3f;
		System.out.println("f1 = " + f1);

		//② 开发中,大家定义浮点型变量时,没有特殊情况的话,通常都声明为double类型,因为精度更高。

		//③ float类型表数范围要大于long类型的表数范围。但是精度不高。

		//测试浮点型变量的精度
		//结论:通过测试发现浮点型变量的精度不高。如果在开发中,需要极高的精度,需要使用BigDecimal类替换浮点型变量。
		//测试1
		System.out.println(0.1 + 0.2);

		//测试2:
		float ff1 = 123123123f;
		float ff2 = ff1 + 1;
		System.out.println(ff1);
		System.out.println(ff2);
		System.out.println(ff1 == ff2);
		
	}
}

案例1:定义圆周率并赋值为3.14,现有3个圆的半径分别为1.2、2.5、6,求它们的面积。

class FloatDoubleExer {
	public static void main(String[] args) {

		//定义圆周率变量
		double pi = 3.14;

		//定义三个圆的半径
		double radius1 = 1.2;
		double radius2 = 2.5;
		int radius3 = 6;

		//计算面积
		double area1 = pi * radius1 * radius1;
		double area2 = pi * radius2 * radius2;
		double area3 = pi * radius3 * radius3;

		//输出
		System.out.println("圆1的半径为:" + radius1 + ",面积为:" + area1);
		System.out.println("圆2的半径为:" + radius2 + ",面积为:" + area2);
		System.out.println("圆3的半径为:" + radius3 + ",面积为:" + area3);
	}
}

案例2:小明要到美国旅游,可是那里的温度是以华氏度为单位记录的。它需要一个程序将华氏温度(80度)转换为摄氏度,并以华氏度和摄氏度为单位分别显示该温度。

class FloatDoubleExer1 {
	public static void main(String[] args) {
		
		double hua = 80.0;

		double she = (hua - 32) / 1.8;

		System.out.println("华氏度" + hua + "℉ 对应的摄氏度为" + she + "℃");

	}
}

8、字符类型的使用

class VariableTest2 {
	public static void main(String[] args) {
		
		//1.字符类型:char(2字节)

		//表示形式1:使用一对''表示,内部有且仅有一个字符
		char c1 = 'a';
		char c2 = '中';
		char c3 = '1';
		char c4 = '%';
		char c5 = 'γ';
		
		//编译不通过
		//char c6 = '';
		//char c7 = 'ab';

		//表示形式2:直接使用Unicode值来表示字符型常量。
		char c8 = '\u0036';
		System.out.println(c8);

		//表示形式3:使用转义字符
		char c9 = '\n';
		char c10 = '\t';
		System.out.println("hello" + c10 + "world");

		//表示形式4:使用具体字符对应的数值(比如ASCII码)
		char c11 = 97;
		System.out.println(c11);//a

		char c12 = '1';
		char c13 = 1;
}
}

9、布尔类型的使用

布尔类型:boolean
① 只有两个取值:true 、 false

② 常使用在流程控制语句中。比如:条件判断、循环结构等

③ 了解:我们不谈boolean类型占用的空间大小。但是,真正在内存中分配的话,使用的是4个字节。

class VariableTest2 {
	public static void main(String[] args) {

//2. 布尔类型:boolean
		//① 只有两个取值:true 、 false
		boolean bo1 = true;
		boolean bo2 = false;
		
		//编译不通过
		//boolean bo3 = 0;
		//② 常使用在流程控制语句中。比如:条件判断、循环结构等
		boolean isMarried = true;
		if(isMarried){
			System.out.println("很遗憾,不能参加单身派对了");
		}else{
			System.out.println("可以多谈几个女朋友或男朋友");
		}
		//③ 了解:我们不谈boolean类型占用的空间大小。但是,真正在内存中分配的话,使用的是4个字节。

}
}

10、基本数据类型间的自动类型提升规则

测试基本数据类型变量间的运算规则。

1. 这里提到可以做运算的基本数据类型有7种,不包含boolean类型。
2. 运算规则包括:
        ① 自动类型提升
        ② 强制类型转换

3. 此VariableTest3.java用来测试自动类型提升

规则:当容量小的变量与容量大的变量做运算时,结果自动转换为容量大的数据类型。

    byte 、short 、char ---> int  --->  long  ---> float ---> double

    特别的:byte、short、char类型的变量之间做运算,结果为int类型。

说明:此时的容量小或大,并非指占用的内存空间的大小,而是指表示数据的范围的大小。
     long(8字节) 、 float(4字节)
 


class VariableTest3 {
	public static void main(String[] args) {
		
		int i1 = 10;
		int i2 = i1;

		long l1 = i1;

		float f1 = l1;


		byte b1 = 12;
		int i3 = b1 + i1;

		//编译不通过
		//byte b2 = b1 + i1;
		
		//**********************************************
		//特殊的情况1:byte、short之间做运算
		byte b3 = 12;
		short s1 = 10;
		//编译不通过
		//short s2 = b3 + s1;
		i3 = b3 + s1;

		byte b4 = 10;
		//编译不通过
		//byte b5 = b3 + b4;

		//特殊的情况2:char
		char c1 = 'a';
		//编译不通过
		//char c2 = c1 + b3;
		int i4 = c1 + b3;


		//**********************************************
		//练习1:
		long l2 = 123L;
		long l3 = 123; //理解为:自动类型提升 (int--->long)

		//long l4 = 123123123123; //123123123123理解为int类型,因为超出了int范围,所以报错。
		long l5 = 123123123123L;//此时的123123123123L就是使用8个字节存储的long类型的值
		
		//练习2:
		float f2 = 12.3F;
		//编译不通过
		//float f3 = 12.3; //不满足自动类型提升的规则(double --> float)。所以报错

		//练习3:
		//规定1:整型常量,规定是int类型。
		byte b5 = 10;
		//byte b6 = b5 + 1;
		int ii1 = b5 + 1;
		//规定2:浮点型常量,规定是double类型。
		double dd1 = b5 + 12.3;

		//练习4:说明为什么不允许变量名是数字开头的。为了“自洽”
		/*
		int 123L = 12;
		long l6 = 123L;
		*/
	}
}

11、基本数据类型变量间的强制类型转换规则

规则:
1. 如果需要将容量大的变量的类型转换为容量小的变量的类型,需要使用强制类型转换
2. 强制类型转换需要使用强转符:()。在()内指明要转换为的数据类型。
3. 强制类型转换过程中,可能导致精度损失。

class VariableTest4 {
	public static void main(String[] args) {
		
		double d1 = 12;//自动类型提升
		
		//编译失败
		//int i1 = d1;

		int i2 = (int)d1;
		System.out.println(i2);


		long l1 = 123;
		//编译失败
		//short s1 = l1;
		short s2 = (short)l1;
		System.out.println(s2);


		//练习
		int i3 = 12;
		float f1 = i3;//自动类型提升
		System.out.println(f1); //12.0

		float f2 = (float)i3; //编译可以通过。只不过可以省略()而已。
		
		//精度损失的例子1:
		double d2 = 12.9;
		int i4 = (int)d2;
		System.out.println(i4);

		//精度损失的例子2:
		int i5 = 128;
		byte b1 = (byte)i5;
		System.out.println(b1); //-128


		//实际开发举例:
		byte b2 = 12;
		method(b2);

		long l2 = 12L;
		//编译不通过
		//method(l2);
		method((int)l2);
	}


	public static void method(int num){   //int num = b2;自动类型提升
		System.out.println("num = " + num);
	}
}

12、String类的基本使用

基本数据类型与String的运算

一、关于String的理解
1. String类,属于引用数据类型,俗称字符串。
2. String类型的变量,可以使用一对""的方式进行赋值。
3. String声明的字符串内部,可以包含0个,1个或多个字符。

二、String与基本数据类型变量间的运算
1. 这里的基本数据类型包括boolean在内的8种。
2. String与基本数据类型变量间只能做连接运算,使用"+"表示。
3. 运算的结果是String类型。
 

class StringTest {
	public static void main(String[] args) {
		String str1 = "Hello World!";
		System.out.println("str1");
		System.out.println(str1);


		String str2 = ""; 
		String str3 = "a";//char c1 = 'a';


		//测试连接运算
		int num1 = 10;
		boolean b1 = true;
		String str4 = "hello";

		System.out.println(str4 + b1);

		String str5 = str4 + b1;
		String str6 = str4 + b1 + num1;
		System.out.println(str6);//hellotrue10
		
		//思考:如下的声明编译能通过吗?不能
		//String str7 = b1 + num1 + str4;

		//如何将String类型的变量转换为基本数据类型?
		String str8 = "abc";//不能考虑转换为基本数据类型的。

		int num2 = 10;
		String str9 = num2 + ""; //"10"
		//编译不通过
		//int num3 = (int)str9;

		//如何实现呢?使用Integer类。暂时大家了解。
		int num3 = Integer.parseInt(str9);
		System.out.println(num3 + 1);
		
	}
}

13、String类的课后练习


要求填写自己的姓名、年龄、性别、体重、婚姻状况(已婚用true表示,单身用false表示)、联系方式等等。
 

class StringExer {
	public static void main(String[] args) {
		
		String name = "李进";
		int age = 24;
		char gender = '男';
		double weight = 130.5;
		boolean isMarried = false;
		String phoneNumber = "13012341234";

		String info = "name = " + name + ",age = " + age + ",gender = " + gender + ",weight = " + 
			weight + ",isMarried = " + isMarried + ",phoneNumber = " + phoneNumber;

		System.out.println(info);
	}
}

14、算术运算符的使用

*
测试运算符的使用1:算术运算符的使用


1. +  -  +  -  *  /  %  (前)++  (后)++  (前)--  (后)--  +


除法

//除法: /
		int m1 = 12;
		int n1 = 5;
		int k1 = m1 / n1;
		System.out.println(k1);//2

		System.out.println(m1 / n1 * n1);//10

取模

//取模(或取余): %
		int i1 = 12;
		int j1 = 5;
		System.out.println(i1 % j1); //2

		//开发中,经常用来判断某个数num1能整除另外一个数num2。  num1 % num2 == 0
		//比如:判断num1是否是偶数: num1 % 2 == 0
		
		//结论:取模以后,结果与被模数的符号相同
		int i2 = -12;
		int j2 = 5;
		System.out.println(i2 % j2); //-2

		int i3 = 12;
		int j3 = -5;
		System.out.println(i3 % j3); //2

		int i4 = -12;
		int j4 = -5;
		System.out.println(i4 % j4); //-2
		

a++和++a

//(前)++ :先自增1,再运算
		//(后)++ :先运算,后自增1
		int a1 = 10;
		int b1 = ++a1;
		System.out.println("a1 = " + a1 + ",b1 = " + b1); //a1 = 11,b1 = 11

		int a2 = 10;
		int b2 = a2++;
		System.out.println("a2 = " + a2 + ",b2 = " + b2); //a2 = 11,b2 = 10

		//练习1:
		int i = 10;
		//i++;
		++i;
		System.out.println("i = " + i);//11

		//练习2:
		short s1 = 10;
		//方式1:

		//编译不通过
		//s1 = s1 + 1;

		//s1 = (short)(s1 + 1);
		//System.out.println(s1);

		//方式2:
		s1++;
		System.out.println(s1);

		//*******************************
		//(前)-- :先自减1,再运算
		//(后)-- :先运算,再自减1
		//略
		
		//结论:++ 或 -- 运算,不会改变变量的数据类型!

		//+ :连接符,只适用于String与其他类型的变量间的运算,而且运算的结果也是String类型。

15、赋值运算符的使用

//说明 += 的使用
		int m1 = 10;
		m1 += 5; //类似于m1 = m1 + 5;
		System.out.println(m1);

		byte by1 = 10;
		by1 += 5; //by1 = by1 + 5操作会编译报错。应该写为: by1 = (byte)(by1 + 5);
		System.out.println(by1);


		int m2 = 1;
		m2 *= 0.1; // m2 = (int)(m2 * 0.1)
		System.out.println(m2);

		//练习1:如何实现变量的值增加2。
		//方式1:
		int n1 = 10;
		n1 = n1 + 2;
		

		//方式2:推荐
		int n2 = 10;
		n2 += 2;

		//错误的写法:
		//int n3 = 10;
		//n3++++;

		//练习2:如何实现变量的值增加1。
		//方式1:
		int i1 = 10;
		i1 = i1 + 1;
		

		//方式2:
		int i2 = 10;
		i2 += 1;

		//方式3:推荐
		int i3 = 10;
		i3++; //++i3;

16、比较运算符的使用

比较运算符

1.  ==  !=  >   <   >=   <=  instanceof

2. 说明
① instanceof 在面向对象的多态性的位置讲解。
② ==  !=  >   <   >=   <= 适用于基本数据类型。(细节:>   <   >=   <=不适用于boolean类型)
  运算的结果为boolean类型。
③ 了解: ==  !=  可以适用于引用数据类型
④ 区分:== 与 = 
 

class CompareTest {
	public static void main(String[] args) {
		int m1 = 10;
		int m2 = 20;
		boolean compare1 = m1 > m2;
		System.out.println(compare1);

		int n1 = 10;
		int n2 = 20;
		System.out.println(n1 == n2);//false
		System.out.println(n1 = n2);//20

		boolean b1 = false;
		boolean b2 = true;
		System.out.println(b1 == b2);//false
		System.out.println(b1 = b2);//true

	}
}

17、逻辑运算符的使用

测试运算符的使用4:逻辑运算符

1.  & &&  |  ||  ! ^
2. 说明:
① 逻辑运算符针对的都是boolean类型的变量进行的操作
② 逻辑运算符运算的结果也是boolean类型。
③ 逻辑运算符常使用条件判断结构、循环结构中

区分:& 和 &&
        1、相同点:两个符号表达的都是"且"的关系。只有当符号左右两边的类型值均为true时,结果才为true。

        2、执行过程:
            1)如果符号左边是true,则& 、&& 都会执行符号右边的操作
            2)如果符号左边是false,则 & 会继续执行符号右边的操作
                                       && 不会执行符号右边的操作
        3、开发中,我们推荐使用&& 

boolean b1 = true;
		b1 = false;

		int num1 = 10;

		if(b1 & (num1++ > 0)){
			System.out.println("床前明月光");
		}else{
			System.out.println("我叫郭德纲");
		}
		
		System.out.println("num1 = " + num1);

		//

		boolean b2 = true;
		b2 = false;

		int num2 = 10;

		if(b2 && (num2++ > 0)){
			System.out.println("床前明月光");
		}else{
			System.out.println("我叫郭德纲");
		}
		
		System.out.println("num2 = " + num2);

区分:| 和 ||
        
        1、相同点:两个符号表达的都是"或"的关系。只要符号两边存在true的情况,结果就为true.

        2、执行过程:
            1)如果符号左边是false,则| 、|| 都会执行符号右边的操作
            2)如果符号左边是true,则 | 会继续执行符号右边的操作
                                      || 不会执行符号右边的操作
        3、开发中,我们推荐使用||

boolean b3 = false;
		b3 = true;

		int num3 = 10;

		if(b3 | (num3++ > 0)){
			System.out.println("床前明月光");
		}else{
			System.out.println("我叫郭德纲");
		}
		
		System.out.println("num3 = " + num3);

		//

		boolean b4 = false;
		b4 = true;

		int num4 = 10;

		if(b4 || (num4++ > 0)){
			System.out.println("床前明月光");
		}else{
			System.out.println("我叫郭德纲");
		}
		
		System.out.println("num4 = " + num4);

18、位运算符的使用

测试运算符的使用5:位运算符

1. <<   >>   >>>   &  |  ^  ~

2. 说明:

① <<   >>   >>>   &  |  ^  ~ :针对数值类型的变量或常量进行运算,运算的结果也是数值
② 
<< : 在一定范围内,每向左移动一位,结果就在原有的基础上 * 2。(对于正数、负数都适用)
>> : 在一定范围内,每向右移动一位,结果就在原有的基础上 / 2。(对于正数、负数都适用)

3. 面试题:高效的方式计算2 * 8 ? 

2 << 3 或 8 << 1

class BitTest {
	public static void main(String[] args) {
		int num1 = 7;
		System.out.println("num1 << 1 : " + (num1 << 1));
		System.out.println("num1 << 2 : " + (num1 << 2));
		System.out.println("num1 << 3 : " + (num1 << 3));
		System.out.println("num1 << 28 : " + (num1 << 28));
		System.out.println("num1 << 29 : " + (num1 << 29));//过犹不及

		int num2 = -7;
		System.out.println("num2 << 1 : " + (num2 << 1));
		System.out.println("num2 << 2 : " + (num2 << 2));
		System.out.println("num2 << 3 : " + (num2 << 3));

		System.out.println(~9);
		System.out.println(~-10);

	}
}

案例2:如何交换两个int型变量的值?String呢?

class BitExer {
	public static void main(String[] args) {
		
		int m = 10;
		int n = 20;

		System.out.println("m = " + m + ",n = " + n);

		//交换两个变量的值
		//方式1:声明一个临时变量。(推荐)
		//int temp = m;
		//m = n;
		//n = temp;

		//方式2:优点:不需要定义临时变量。  缺点:难、适用性差(不适用于非数值类型)、可能超出int的范围
		//m = m + n; //30 = 10 + 20;
		//n = m - n; //10 = 30 - 20;
		//m = m - n; //20 = 30 - 10;

		//方式3:优点:不需要定义临时变量。  缺点:真难、适用性差(不适用于非数值类型)
		m = m ^ n;
		n = m ^ n;//(m ^ n) ^ n ---> m
		m = m ^ n;


		System.out.println("m = " + m + ",n = " + n);
		

	}
}

19、条件运算符的使用

条件运算符

1. (条件表达式)? 表达式1 : 表达式2

2. 说明:
① 条件表达式的结果是boolean类型。
② 如果条件表达式的结果是true,则执行表达式1。否则,执行表达式2。
③ 表达式1 和 表达式2 需要是相同的类型或能兼容的类型。

④ 开发中,凡是可以使用条件运算符的位置,都可以改写为if-else。
          反之,能使用if-else结构,不一定能改写为条件运算符。
  
  建议,在二者都能使用的情况下,推荐使用条件运算符。因为执行效率稍高。

class ConditionTest {
	public static void main(String[] args) {
		
		String info = (2 > 10)? "表达式1" : "表达式2";
		System.out.println(info);

		double result = (2 > 1)? 1 : 2.0;
		System.out.println(result);

		//练习1:获取两个整数的较大值
		int m = 10;
		int n = 20;

		int max = (m > n)? m : n;
		System.out.println("较大值为:" + max);

		//练习2:获取三个整数的最大值
		int i = 20;
		int j = 30;
		int k = 23;

		int tempMax = (i > j)? i : j;
		int finalMax = (tempMax > k)? tempMax : k;
		System.out.println(finalMax);

		//合并以后的写法:不推荐
		int finalMax1 = (((i > j)? i : j) > k)? ((i > j)? i : j) : k;
		System.out.println(finalMax1);
	}
}

练习

今天是周2,10天以后是周几?

要求:控制台输出"今天是周2,10天以后是周x"。

class ConditionExer {
	public static void main(String[] args) {
		
		int week = 2;
		//week = 4;

		week += 10;

		week %= 7;

		System.out.println("今天是周2,10天以后是周" + ((week == 0)? "日" : week));

	}
}

二、流程控制

1、if-else的基本使用


分支结构1:if-else条件判断结构

1. 格式
格式1:
if(条件表达式){
      语句块;

格式2:"二选一"
if(条件表达式) { 
      语句块1;
}else{
      语句块2;
}

格式3:"多选一"
if (条件表达式1) {
      语句块1;
} else if (条件表达式2) {
      语句块2;
}
...
}else if (条件表达式n) {
     语句块n;
} else {
      语句块n+1;
}


案例1:成年人心率的正常范围是每分钟60-100次。体检时,如果心率不在此范围内,则提示需要做进一步的检查

class IfElseTest {
	public static void main(String[] args) {
		
		/*
		案例1:成年人心率的正常范围是每分钟60-100次。体检时,
		如果心率不在此范围内,则提示需要做进一步的检查。
		*/
		int heartBeats = 89;
		//错误的写法:if(60 <= heartBeats <= 100){

		if(heartBeats < 60 || heartBeats > 100){
			System.out.println("你需要做进一步的检查");
		}

		System.out.println("体检结束");

		//**********************************
		
	}
}

 案例2:定义一个整数,判断是偶数还是奇数

/*
        案例2:定义一个整数,判定是偶数还是奇数    
        */
        int num = 13;
        if(num % 2 == 0){
            System.out.println(num + "是偶数");
        }else{
            System.out.println(num + "是奇数");
        }

案例3: 

岳小鹏参加Java考试,他和父亲岳不群达成承诺:
如果:
成绩为100分时,奖励一辆跑车;
成绩为(80,99]时,奖励一辆山地自行车;
当成绩为[60,80]时,奖励环球影城一日游;
其它时,胖揍一顿。

说明:默认成绩是在[0,100]范围内

结论:
1. 如果多个条件表达式之间没有交集(理解是互斥关系),则哪个条件表达式声明在上面,哪个声明在下面都可以。
   如果多个条件表达式之间是包含关系,则需要将范围小的条件表达式声明在范围大的条件表达式的上面。否则,范围小的条件表达式不可能被执行。

class IfElseTest1 {
	public static void main(String[] args) {
		
		int score = 61;

		//方式1:
		/*
		if(score == 100){
			System.out.println("奖励一辆跑车");
		}else if(score > 80 && score <= 99){
			System.out.println("奖励一辆山地自行车");
		}else if(score >= 60 && score <= 80){
			System.out.println("奖励环球影城一日游");
		}else{
			System.out.println("胖揍一顿");
		}
		*/
		
		//方式2:
		score = 88;

		if(score == 100){
			System.out.println("奖励一辆跑车");
		}else if(score > 80){
			System.out.println("奖励一辆山地自行车");
		}else if(score >= 60){
			System.out.println("奖励环球影城一日游");
		}else{
			System.out.println("胖揍一顿");
		}

		//特别的:
		if(score == 100){
			System.out.println("奖励一辆跑车");
		}else if(score > 80){
			System.out.println("奖励一辆山地自行车");
		}else if(score >= 60){
			System.out.println("奖励环球影城一日游");
		}
		/*else{
			System.out.println("胖揍一顿");
		}
		*/
		
	}
}

2、if-else的嵌套使用

测试if-else的嵌套使用

案例:
由键盘输入三个整数分别存入变量num1、num2、num3,对它们进行排序(使用 if-else if-else),并且从小到大输出。

拓展:你能实现从大到小顺序的排列吗?

1. 从开发经验上讲,没有写过超过三层的嵌套if-else结构。
2. 如果if-else中的执行语句块中只有一行执行语句,则此执行语句所在的一对{}可以省略。但是,不建议省略

class IfElseTest2 {
	public static void main(String[] args) {
		
		int num1 = 30;
		int num2 = 21;
		int num3 = 44;

		//int num1 = 30,num2 = 21,num3 = 44;

		if(num1 >= num2){
			if(num3 >= num1)
				System.out.println(num2 + "," + num1 + "," + num3);
			else if(num3 <= num2)
				System.out.println(num3 + "," + num2 + "," + num1);
			else
				System.out.println(num2 + "," + num3 + "," + num1);	
				//System.out.println(num2 + "," + num3 + "," + num1);	
				
		}else{ // num1 < num2
			if(num3 >= num2){
				System.out.println(num1 + "," + num2 + "," + num3);
			}else if(num3 <= num1){
				System.out.println(num3 + "," + num1 + "," + num2);
			}else{
				System.out.println(num1 + "," + num3 + "," + num2);
			}
		}

	}
}

3、使用Scanner类从键盘获取数据

如何从键盘获取不同类型(基本数据类型、String类型)的变量:使用Scanner类。

1. 使用Scanner获取不同类型数据的步骤
步骤1:导包 import java.util.Scanner;
步骤2:提供(或创建)一个Scanner类的实例
步骤3:调用Scanner类中的方法,获取指定类型的变量 (nextXxx())
步骤4:关闭资源,调用Scanner类的close()

2. 案例:小明注册某交友网站,要求录入个人相关信息。如下:

请输入你的网名、你的年龄、你的体重、你是否单身、你的性别等情况。


3. Scanner类中提供了获取byte \ short \ int \ long \float \double \boolean \ String类型变量的方法。
   注意,没有提供获取char类型变量的方法。需要使用next().charAt(0)

//步骤1:导包 import java.util.Scanner;
import java.util.Scanner;
class ScannerTest {
	public static void main(String[] args) {
		
		//步骤2:提供(或创建)一个Scanner类的实例
		Scanner scan = new Scanner(System.in);
		
		System.out.println("欢迎光临你来我往交友网");
		System.out.print("请输入你的网名:");
		//步骤3:调用Scanner类中的方法,获取指定类型的变量
		String name = scan.next();

		System.out.print("请输入你的年龄:");
		int age = scan.nextInt();

		System.out.print("请输入你的体重:");	
		double weight = scan.nextDouble();


		System.out.print("你是否单身(单身:true;不单身:false):");
		boolean isSingle = scan.nextBoolean();

		System.out.print("请输入你的性别(男\\女):"); 
		char gender = scan.next().charAt(0);

		System.out.println("网名:" + name + ",年龄: " + age + ",体重:" + weight + ",是否单身:" + isSingle + 
			",性别:" + gender);

		System.out.println("注册完成,欢迎继续进入体验!");

		//步骤4:关闭资源,调用Scanner类的close()
		scan.close();
	}
}

4、如何获取一个随机数

如何获取一个随机数?

1. 可以使用Java提供的API:Math类的random() 
2. random()调用以后,会返回一个[0.0,1.0)范围的double型的随机数

3. 需求1:获取一个[0,100]范围的随机整数?
   需求2:获取一个[1,100]范围的随机整数?

4. 需求:获取一个[a,b]范围的随机整数?
   (int)(Math.random() * (b - a + 1)) + a

class RandomTest {
	public static void main(String[] args) {
		
		double d1 = Math.random();

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


		int num1 = (int)(Math.random() * 101);  //[0.0,1.0) --> [0.0,101.0) --->[0,100]
		System.out.println("num1 = " + num1);

		int num2 = (int)(Math.random() * 100) + 1; //[0.0,1.0) --> [0.0,100.0) --->[0,99] ---> [1,100]


	}
}

5、switch-case的基本使用

分支结构之switch-case的使用

1. 语法格式

switch(表达式){
    
    case 常量1:
        //执行语句1
        //break;
    case 常量2:
        //执行语句2
        //break;
    ...
    default:
        //执行语句2
        //break;
}

2.执行过程:
根据表达式中的值,依次匹配case语句。一旦与某一个case中的常量相等,那么就执行此case中的执行语句。
执行完此执行语句之后,
        情况1:遇到break,则执行break后,跳出当前的switch-case结构
        情况2:没有遇到break,则继续执行其后的case中的执行语句。 ---> case 穿透
                ...
               直到遇到break或者执行完所有的case及default中的语句,退出当前的switch-case结构

3. 说明:
① switch中的表达式只能是特定的数据类型。如下:byte \ short \ char \ int \ 枚举(JDK5.0新增) \ String(JDK7.0新增)
② case 后都是跟的常量,使用表达式与这些常量做相等的判断,不能进行范围的判断。
③ 开发中,使用switch-case时,通常case匹配的情况都有限。
④ break:可以使用在switch-case中。一旦执行此break关键字,就跳出当前的switch-case结构
⑤ default:类似于if-else中的else结构。
           default是可选的,而且位置是灵活的。

4. switch-case 与if-else之间的转换
① 开发中凡是可以使用switch-case结构的场景,都可以改写为if-else。反之,不成立
② 开发中,如果一个具体问题既可以使用switch-case,又可以使用if-else的时候,推荐使用switch-case。
  为什么?switch-case相较于if-else效率稍高。

class SwitchCaseTest{
	public static void main(String[] args){
		
		int num = 1;
		switch(num){
			
			case 0:
				System.out.println("zero");
				break; 
			case 1:
				System.out.println("one");
				break; //结束当前的switch-case结构
			case 2:
				System.out.println("two");
				break; 
			case 3:
				System.out.println("three");
				break; 
			default:
				System.out.println("other");
				//break; 
		}

		//另例:
		String season = "summer";
        switch (season) {
            case "spring":
                System.out.println("春暖花开");
                break;
            case "summer":
                System.out.println("夏日炎炎");
                break;
            case "autumn":
                System.out.println("秋高气爽");
                break;
            case "winter":
                System.out.println("冬雪皑皑");
                break;
            /*default:
                System.out.println("季节输入有误");
                break;
			*/
        }

		//错误的例子:编译不通过
		/*
		int number = 20;
		switch(number){
			case number > 0:
				System.out.println("正数");
                break;
			case number < 0:
				System.out.println("负数");
                break;
			default:
				System.out.println("零");
                break;
		}
		*/
	}
}

6、switch-case的课后练习

案例:编写程序:从键盘上输入2023年的“month”和“day”,要求通过程序输出输入的日期为2023年的第几天。

import java.util.Scanner;

class SwitchCaseTest2 {
	public static void main(String[] args) {
		//1.使用Scanner,从键盘获取2023年的month、day
		Scanner input = new Scanner(System.in);

		System.out.println("请输入2023年的月份:");
		int month = input.nextInt();//阻塞式方法

		System.out.println("请输入2023年的天:");
		int day = input.nextInt();

		//假设用户输入的数据是合法的。后期我们在开发中,使用正则表达式进行校验。

		//2. 使用switch-case实现分支结构
		int sumDays = 0;//记录总天数
		//方式1:不推荐。存在数据的冗余
		/*
		switch(month){
			case 1:
				sumDays = day;
				break;
			case 2:
				sumDays = 31 + day;
				break;
			case 3:
				sumDays = 31 + 28 + day;
				break;
			case 4:
				sumDays = 31 + 28 + 31 + day;
				break;
			//...
			case 12:
				sumDays = 31 + 28 + ... + 30 + day;
				break;
		
		}
		*/
		//方式2:
		switch(month){
			case 12:
				sumDays += 30;
			case 11:
				sumDays += 31;
			case 10:
				sumDays += 30;
			case 9:
				sumDays += 31;
			case 8:
				sumDays += 31;
			case 7:
				sumDays += 30;
			case 6:
				sumDays += 31;
			case 5:
				sumDays += 30;
			case 4:
				sumDays += 31;
			case 3:
				sumDays += 28; //28:2月份的总天数
			case 2:
				sumDays += 31; //31:1月份的总天数
			case 1:
				sumDays += day;
				//break;
		}
		

		System.out.println("2023年" + month + "月" + day + "日是当前的第" + sumDays + "天");
		
		
		input.close();//为了防止内存泄漏
	}
}

7、for循环结构的基本使用

循环结构之一:for循环

1. Java中规范了3种循环结构:for、while、do-while
2. 凡是循环结构,就一定会有4个要素:
① 初始化条件
② 循环条件 ---> 一定是boolean类型的变量或表达式
③ 循环体
④ 迭代部分

3. for循环的格式

for(①;②;④){
    ③
}

执行过程:① - ② - ③ - ④ - ② - ③ - ④ - ... - ②

class ForTest {
	public static void main(String[] args) {
		//需求1:题目:输出5行HelloWorld
		/*
		System.out.println("HelloWorld");
		System.out.println("HelloWorld");
		System.out.println("HelloWorld");
		System.out.println("HelloWorld");
		System.out.println("HelloWorld");
		*/

		for(int i = 1;i <= 50;i++){
			System.out.println("HelloWorld");
		}
		
		//此时编译不通过。因为i已经出了其作用域范围。
		//System.out.println(i);

		//需求2:
		int num = 1;
        for(System.out.print("a");num < 3;System.out.print("c"),num++){
            System.out.print("b");

        }

		//输出结果:abcbc

		System.out.println();//换行

		//需求3:遍历1-100以内的偶数,并获取偶数的个数,获取所有的偶数的和
		int count = 0;//记录偶数的个数

		int sum = 0;//记录所有偶数的和

		for(int i = 1;i <= 100;i++){

			if(i % 2 == 0){
				System.out.println(i);
				count++;
				sum += i; //sum = sum + i;
			}	
		}

		System.out.println("偶数的个数为:" + count);
		System.out.println("偶数的总和为:" + sum);
		
	}
}

题目:输出所有的水仙花数,所谓水仙花数是指一个3位数,其各个位上数字立方和等于其本身。
例如: 153 = 1*1*1 + 3*3*3 + 5*5*5

class ForTest1 {
	public static void main(String[] args) {
		
		//遍历所有的3位数
		for(int i = 100;i <= 999;i++){
			
			//针对于每一个三位数i,获取其各个位上数值
			int ge = i % 10;
			int shi = i / 10 % 10;  //或 int shi = i % 100 / 10
			int bai = i / 100;

			//判断是否满足水仙花数的规则
			if(i == ge * ge * ge + shi * shi * shi + bai * bai * bai){
				System.out.println(i);
			}

		}
	}
}

8、for循环结构的课后练习

案例:输入两个正整数m和n,求其最大公约数和最小公倍数。

比如:12和20的最大公约数是4,最小公倍数是60。

约数:12为例,约数有1,2,3,4,6,12
           20为例,约数有1,2,4,5,10,20

倍数:12为例,倍数有12,24,36,48,60,72,....
           20为例,倍数有20,40,60,80,....

说明:
1. 我们可以在循环结构中使用break。一旦执行break,就跳出(或结束)当前循环结构。
2. 如何结束一个循环结构?
    方式1:循环条件不满足。(即循环条件执行完以后是false)
    方式2:在循环体中执行了break 

class ForTest2 {
	public static void main(String[] args) {

		int m = 12;
		int n = 20;

		//获取m和n中的较小值
		int min = (m < n)? m : n;

		//需求1:最大公约数
		//方式1:
		int result = 1;
		for(int i = 1;i <= min;i++){
			if(m % i == 0 && n % i == 0){
				//System.out.println(i);
				result = i;
			}

		}

		System.out.println(result);

		//方式2:推荐
		for(int i = min;i >= 1;i--){
			if(m % i == 0 && n % i == 0){
				System.out.println("最大公约数为:" + i);
				break;//一旦执行,就跳出当前循环结构。
			}
		}

		//需求2:最小公倍数
		int max = (m > n)? m : n;
		for(int i = max;i <= m * n;i++){
			if(i % m == 0 && i % n == 0){
				System.out.println("最小公倍数为:" + i);
				break;
			}
		}
	}
}

 9、do-while 循环的使用及课后练习

循环结构之一:do-while循环


1. 凡是循环结构,就一定会有4个要素:
① 初始化条件
② 循环条件 ---> 一定是boolean类型的变量或表达式
③ 循环体
④ 迭代部分

2. do-while的格式


do{
    ③
    ④
}while(②);

执行过程:① - ③ - ④ - ② - ③ - ④ - .... - ②

3. 说明:
1) do-while循环至少执行一次循环体。
2) for、while、do-while循环三者之间是可以相互转换的。
3) do-while循环结构,在开发中,相较于for、while循环来讲,使用的较少。
 

class DoWhileTest {
	public static void main(String[] args) {
		
		//需求:遍历100以内的偶数,并输出偶数的个数和总和
		int i = 1;
		int count = 0;//记录偶数的个数
		int sum = 0;//记录偶数的总和

		do{
			if(i % 2 == 0){
				System.out.println(i);
				count++;
				sum += i;
			}

			i++;

		}while(i <= 100);
		
		System.out.println("偶数的个数为:" + count);
		System.out.println("偶数的总和为:" + sum);

		//***************************
		int num1 = 10;
		while(num1 > 10){
			System.out.println("while:hello");
			num1--;
		}

		int num2 = 10;
		do{
			System.out.println("do-while:hello");
			num2--;
		}while(num2 > 10);
	}
}

题目:模拟ATM取款

声明变量balance并初始化为0,用以表示银行账户的余额,下面通过ATM机程序实现存款,取款等功能。

=========ATM========
   1、存款
   2、取款
   3、显示余额
   4、退出
请选择(1-4):

import java.util.Scanner;
class DoWhileTest1 {
	public static void main(String[] args) {
		
		//1. 定义balance的变量,记录账户余额
		double balance = 0.0;

		boolean flag = true; //控制循环的结束

		Scanner scan = new Scanner(System.in);//实例化Scanner

		do{
			//2. 声明ATM取款的界面
			System.out.println("=========ATM========");
			System.out.println("   1、存款");
			System.out.println("   2、取款");
			System.out.println("   3、显示余额");
			System.out.println("   4、退出");
			System.out.print("请选择(1-4):");

			//3. 使用Scanner获取用户的选择
			
			int selection = scan.nextInt();
			switch(selection){
				//4. 根据用户的选择,决定执行存款、取款、显示余额、退出的操作
				case 1:
					System.out.print("请输入存款的金额:");
					double money1 = scan.nextDouble();
					if(money1 > 0){
						balance += money1;
					}
					break;
				case 2:
					System.out.print("请输入取款的金额:");
					double money2 = scan.nextDouble();
					
					if(money2 > 0 && money2 <= balance){
						balance -= money2;
					}else{
						System.out.println("输入的数据有误或余额不足");
					}


					break;
				case 3:
					System.out.println("账户余额为:" + balance);
					break;
				case 4 :
					flag = false;
					System.out.println("感谢使用,欢迎下次光临^_^");
					break;
				default:
					System.out.println("输入有误,请重新输入");
					//break;
			
			}
		
		
		}while(flag);

		
		//关闭资源
		scan.close();

		

	}
}

 9、无限循环的使用

"无限"循环结构的使用

1. 格式: while(true)  或  for(;;)

2.开发中,有时并不确定需要循环多少次,需要根据循环体内部某些条件,来控制循环的结束(使用break)。

3. 如果此循环结构不能终止,则构成了死循环!开发中要避免出现死循环。

class ForWhileTest {
	public static void main(String[] args) {
		/*
		for(;;){//while(true){
			System.out.println("I love you!");
		}
		*/
		
		//死循环的后面不能有执行语句。
		//System.out.println("end");

		
	}
}

案例:从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入为0时结束程序。
 

import java.util.Scanner;
class ForWhileTest1 {
	public static void main(String[] args) {
		
		Scanner scan = new Scanner(System.in);

		int positiveCount = 0;//记录正数的个数
		int negativeCount = 0;//记录负数的个数
		
		for(;;){//while(true){
			System.out.print("请输入一个整数(输入为0时结束程序):");
			int num = scan.nextInt(); //获取用户输入的整数

			if(num > 0){ //正数
				positiveCount++;
			}else if(num < 0){ //负数
				negativeCount++;
			}else{ //零
				System.out.println("程序结束");
				break;
			}
		
		
		}
		
		System.out.println("正数的个数为:" + positiveCount);
		System.out.println("负数的个数为:" + negativeCount);


		scan.close();
	}
}

 10、嵌套循环的使用

嵌套循环的使用

1. 嵌套循环:是指一个循环结构A的循环体是另一个循环结构B。
- 外层循环:循环结构A
- 内层循环:循环结构B

2. 说明:
1)内层循环充当了外层循环的循环体。
2)对于两层嵌套循环来说,外层循环控制行数,内层循环控制列数。
3)举例:外层循环执行m次,内层循环执行n次,则内层循环的循环体共执行m * n次
4)实际开发中,我们不会出现三层以上的循环结构,三层的循环结构都很少见。

class ForForTest {
	public static void main(String[] args) {
		
		//******
		for(int i = 1;i <= 6;i++){
			System.out.print('*');
		}

		System.out.println("\n##################");
		
		/*

		******
		******
		******
		******
		******

		*/
		
		for(int j = 1;j <= 5;j++){

			for(int i = 1;i <= 6;i++){
				System.out.print('*');
			}

			System.out.println();
		}
		
		/*
						i(第几行)		j(每一行中*的个数)
		*				1				1
		**				2				2
		***				3				3
		****			4				4
		*****			5				5

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

		/*
						i(第几行)		j(每一行中*的个数)		i + j = 7 --> j = 7 - i
		******			1				6
		*****			2				5
		****			3				4
		***				4				3
		**				5				2
		*				6				1
		
		*/

		for(int i = 1;i <= 6;i++){

			for(int j = 1;j <= 7 - i;j++){
				System.out.print("*");
			}
			
			System.out.println();
		}

	/*
						i(第几行)		j(每一行中-的个数)		k(每一行中*的个数)    2*i + j = 10 --->j = 10 - 2*i
--------*				1				8						1                     k = 2 * i - 1
------* * *				2				6						3
----* * * * *			3				4						5
--* * * * * * *			4				2						7
* * * * * * * * *		5				0						9



  * * * * * * * 
    * * * * * 
      * * * 
        * 
		
	*/

	//上半部分
	for(int i = 1;i <= 5;i++){
		// -
		for(int j = 1;j <= 10 - 2*i;j++){
			System.out.print("-");
		}


		// *
		for(int k = 1;k <= 2 * i - 1;k++){
			System.out.print("* ");
		}

		System.out.println();
	}




		

		


	}
}

11、关键字break和continue的使用

1. break和continue关键字的使用

                 使用范围             在循环结构中的作用                         相同点
break:       switch-case
                 循环结构中       结束(或跳出)当前循环结构       在此关键字的后面不能声明执行句。

continue:   循环结构中      结束(或跳出)当次循环               在此关键字的后面不能声明执行句。

        
2. 了解带标签的break和continue的使用

3. 开发中,break的使用频率要远高于continue。

class BreakContinueTest{
	public static void main(String[] args){
		
		for(int i = 1;i <= 10;i++){

			if(i % 4 == 0){
				//break;
				continue;
				
				//编译不通过
				//System.out.println("今晚上迪丽热巴要约我!");
			}
			
			System.out.print(i);
		
		}
		
		System.out.println();

		//*****************************
		label:for(int j = 1;j <= 4;j++){
		
			for(int i = 1;i <= 10;i++){

				if(i % 4 == 0){
					//break;
					//continue;	

					//了解
					//break label;
					//continue label;
				}
				
				System.out.print(i);			
			}
			System.out.println();
		
		}
	
	}
}

12、通过质数的输出体会算法的魅力

题目:找出100以内所有的素数(质数)?100000以内的呢?

质数:只能被1和它本身整除的自然数。比如:2,3,5,7,11,13,17,19,23,....
   
   ---> 换句话说,从2开始到这个自然数-1为止,不存在此自然数的约数。

class PrimeNumberTest {
	public static void main(String[] args) {
		
		/*
		方式1:
		for(int i = 2;i <= 100;i++){ //遍历100以内的自然数

			int number = 0; //记录i的约数的个数(从2开始,到i-1为止)
			
			//判定i是否是质数
			for(int j = 2;j < i;j++){
				
				if(i % j == 0){
					number++;
				}
			
			}

			if(number == 0){
				System.out.println(i);
			}
		
		
		}
		*/

		//方式2:
		boolean isFlag = true;

		for(int i = 2;i <= 100;i++){ //遍历100以内的自然数
			
			
			//判定i是否是质数
			for(int j = 2;j < i;j++){
				
				if(i % j == 0){
					isFlag = false;
				}
			
			}

			if(isFlag){//if(isFlag == true){
				System.out.println(i);
			}
			
			//重置isFlag
			isFlag = true;
		}

	}
}

遍历100000以内的所有的质数。体会不同的算法实现,其性能的差别

此PrimeNumberTest1.java是实现方式1

class PrimeNumberTest1 {
	public static void main(String[] args) {

		//获取系统当前的时间:
		long start = System.currentTimeMillis();
		
		boolean isFlag = true;

		int count = 0;//记录质数的个数

		for(int i = 2;i <= 100000;i++){ //遍历100000以内的自然数
			
			
			//判定i是否是质数
			for(int j = 2;j < i;j++){
				
				if(i % j == 0){
					isFlag = false;
				}
			
			}

			if(isFlag){
				count++;
			}
			
			//重置isFlag
			isFlag = true;
		}

		//获取系统当前的时间:
		long end = System.currentTimeMillis();

		System.out.println("质数的总个数为:" + count); //9592
		System.out.println("花费的时间为:" + (end - start)); //7209

	}
}

遍历100000以内的所有的质数。体会不同的算法实现,其性能的差别

此PrimeNumberTest2.java是方式2,针对于PrimeNumberTest1.java中算法的优化

class PrimeNumberTest2 {
	public static void main(String[] args) {

		//获取系统当前的时间:
		long start = System.currentTimeMillis();
		
		boolean isFlag = true;

		int count = 0;//记录质数的个数

		for(int i = 2;i <= 100000;i++){ //遍历100000以内的自然数
			
			
			//判定i是否是质数
			for(int j = 2;j <= Math.sqrt(i);j++){
				
				if(i % j == 0){
					isFlag = false;
					break;//针对于非质数有效果。
				}
			
			}

			if(isFlag){
				count++;
			}
			
			//重置isFlag
			isFlag = true;
		}

		//获取系统当前的时间:
		long end = System.currentTimeMillis();

		System.out.println("质数的总个数为:" + count); //9592
		System.out.println("花费的时间为:" + (end - start)); //7209 -->加上break:659 -->加上Math.sqrt():6

	}
}

 三、数组

1、数组的初始化、遍历、元素的默认初始值

1. 数组的理解(Array)

概念:是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。

简称:多个数据的组合

Java中的容器:数组、集合框架(第12章):在内存中对多个数据的存储。

2. 几个相关的概念
> 数组名
> 数组的元素(即内部存储的多个元素)
> 数组的下标、角标、下角标、索引、index(即找到指定数组元素所使用的编号)
> 数组的长度(即数组容器中存储的元素的个数)

3. 数组的特点:
> 数组中的元素在内存中是依次紧密排列的,有序的。
> 数组,属于引用数据类型的变量。数组的元素,既可以是基本数据类型,也可以引用数据类型。
> 数组,一旦初始化完成,其长度就确定了,并且其长度不可更改。
> 创建数组对象会在内存中开辟一整块`连续的空间`。占据的空间的大小,取决于数组的长度和数组中元素的类型。


4. 复习:变量按照数据类型的分类
4.1 基本数据类型:byte \ short \ int \ long ;float \ double ; char \ boolean
4.2 引用数据类型:类、数组、接口、枚举、注解、记录


5. 数组的分类
5.1 按照元素的类型:基本数据类型元素的数组;引用数据类型元素的数组
5.2 按照数组的维数来分:一维数组;二维数组;.....

6. 一维数组的使用(6个基本点)
> 数组的声明和初始化
> 调用数组的指定元素
> 数组的属性:length,表示数组的长度
> 数组的遍历
> 数组元素的默认初始化值
> 一维数组的内存解析(难)


7. 数组元素的默认初始化值的情况
注意:以数组的动态初始化方式为例说明。

> 整型数组元素的默认初始化值:0
> 浮点型数组元素的默认初始化值:0.0
> 字符型数组元素的默认初始化值:0 (或理解为'\u0000')
> boolean型数组元素的默认初始化值:false
> 引用数据类型数组元素的默认初始化值:null


8. 一维数组的内存解析
8.1 Java中的内存结构是如何划分的?(主要关心JVM的运行时内存环境)
> 将内存区域划分为5个部分:程序计数器、虚拟机栈、本地方法栈、堆、方法区

> 与目前数组相关的内存结构:   比如:int[] arr = new int[]{1,2,3};
    > 虚拟机栈:用于存放方法中声明的变量。比如:arr
    > 堆:用于存放数组的实体(即数组中的所有元素)。比如:1,2,3

8.2 举例:具体一维数组的代码的内存解析

package com.atguigu1.one;

/**
 * 一维数组的基本使用
 *
 * @author 尚硅谷-宋红康
 * @create 12:08
 */
 
public class OneArrayTest {
	
	public static void main(String args[]) {
		//1. 数组的声明与初始化
		//复习:变量的定义格式:数据类型 变量名 = 变量值
		int num1 = 10;
		int num2; //声明
		num2 = 20; //初始化

		//1.1 声明数组
		double[] prices;
		//1.2 数组的初始化
		//静态初始化:数组变量的赋值与数组元素的赋值操作同时进行。
		prices = new double[]{20.32,43.21,43.22};

//		String[] foods;
//		foods = new String[]{"拌海蜇","龙须菜","炝冬笋","玉兰片"};

		//数组的声明和初始化
		//动态初始化:数组变量的赋值与数组元素的赋值操作分开进行。
		String[] foods = new String[4];

		//其它正确的方式
		int arr[] = new int[4];
		int[] arr1 = {1,2,3,4}; //类型推断

		//错误的方式
//		int[] arr2 = new int[3]{1,2,3};
//		int[3] arr3 = new int[];

		//2. 数组元素的调用
		//通过角标的方式,获取数组的元素
		//角标的范围从0开始,到数组的长度-1结束
		System.out.println(prices[0]);
		System.out.println(prices[2]);
//		System.out.println(prices[4]); //报异常:ArrayIndexOutOfBoundsException

		foods[0] = "拌海蜇";
		foods[1] = "龙须菜";
		foods[2] = "炝冬笋";
		foods[3] = "玉兰片";
//		foods[4] = "酱茄子"; //报异常:ArrayIndexOutOfBoundsException

		//3. 数组的长度:用来描述数组容器中容量的大小
		//使用length属性表示
		System.out.println(foods.length);//4
		System.out.println(prices.length);//3


		//4. 如何遍历数组
//		System.out.println(foods[0]);
//		System.out.println(foods[1]);
//		System.out.println(foods[2]);
//		System.out.println(foods[3]);


		for(int i = 0;i < foods.length;i++){
			System.out.println(foods[i]);
		}
		
		

		for (int i = 0; i < prices.length; i++) {
			System.out.println(prices[i]);
		}

	}

}

 2、一维数组的课后练习

* 案例:输出英文星期几
 *
 * 用一个数组,保存星期一到星期天的7个英语单词,从键盘输入1-7,显示对应的单词
 * {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}

package com.atguigu1.one.exer2;

import java.util.Scanner;

/**
 * ClassName: ArrayExer02
 * Description:案例
 *
 * 案例:输出英文星期几
 *
 * 用一个数组,保存星期一到星期天的7个英语单词,从键盘输入1-7,显示对应的单词
 * {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}
 *
 * @Author 尚硅谷-宋红康
 * @Create 10:36
 * @Version 1.0
 */
public class ArrayExer02 {
    public static void main(String[] args) {
        //定义包含7个单词的数组
        String[] weeks = {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};

        //从键盘获取指定的数值,使用Scanner
        Scanner scan  = new Scanner(System.in);
        System.out.println("请输入数值(1-7):");
        int day = scan.nextInt();

        //针对获取的数据进行判断即可
        if(day < 1 || day > 7){
            System.out.println("你输入的数据有误。");
        }else{
            System.out.println(weeks[day - 1]);
        }

        scan.close();
    }
}

* 案例2:学生考试等级划分
 * <p>
 * 从键盘读入学生成绩,找出最高分,并输出学生成绩等级。
 * 成绩>=最高分-10    等级为’A’
 * 成绩>=最高分-20    等级为’B’
 * 成绩>=最高分-30    等级为’C’
 * 其余              等级为’D’

package com.atguigu1.one.exer3;

import java.util.Scanner;

/**
 * ClassName: ArrayExer03
 * Description:
 * 案例:学生考试等级划分
 * <p>
 * 从键盘读入学生成绩,找出最高分,并输出学生成绩等级。
 * 成绩>=最高分-10    等级为’A’
 * 成绩>=最高分-20    等级为’B’
 * 成绩>=最高分-30    等级为’C’
 * 其余              等级为’D’
 *
 * @Author 尚硅谷-宋红康
 * @Create 10:42
 * @Version 1.0
 */
public class ArrayExer03 {
    public static void main(String[] args) {
        //1. 从键盘输入学生的人数,根据人数,创建数组(动态初始化)
        Scanner scan = new Scanner(System.in);
        System.out.print("请输入学生人数:");
        int count = scan.nextInt();

        int[] scores = new int[count];

        //2. 根据提示,依次输入学生成绩,并将成绩保存在数组元素中
        System.out.println("请输入" + count + "个成绩");
        for (int i = 0; i < scores.length; i++) {
            scores[i] = scan.nextInt();
        }


        //3. 获取学生成绩的最大值
        int maxScore = scores[0];
        for (int i = 1; i < scores.length; i++) {
            if (maxScore < scores[i]) {
                maxScore = scores[i];
            }
        }

        System.out.println("最高分是:" + maxScore);

        //4. 遍历数组元素,根据学生成绩与最高分的差值,得到每个学生的等级,并输出成绩和等级
        for (int i = 0; i < scores.length; i++) {
            if (scores[i] >= maxScore - 10) {
                System.out.println("student " + i + " score is " + scores[i] +
                        " grade is A");
            } else if (scores[i] >= maxScore - 20) {
                System.out.println("student " + i + " score is " + scores[i] +
                        " grade is B");
            } else if (scores[i] >= maxScore - 30) {
                System.out.println("student " + i + " score is " + scores[i] +
                        " grade is C");
            } else {
                System.out.println("student " + i + " score is " + scores[i] +
                        " grade is D");
            }
        }

        scan.close();

    }
}

3、二维数组的初始化、遍历、元素的初始值 


1. 二维数组的理解

- 对于二维数组的理解,可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。
- 其实,从数组底层的运行机制来看,其实没有多维数组。
- 概念:数组的外层元素;数组的内层元素

2. 二维数组的使用(6个基本点)
> 数组的声明和初始化
> 调用数组的指定元素
> 数组的属性:length,表示数组的长度
> 数组的遍历
> 数组元素的默认初始化值
> 二维数组的内存解析(难)


3. 二维数组元素的默认初始化值
3.1 动态初始化方式1:(比如:int[][] arr = new int[3][4])

1)外层元素,默认存储地址值。
2)内层元素,默认与一维数组元素的不同类型的默认值规定相同。
    > 整型数组元素的默认初始化值:0
    > 浮点型数组元素的默认初始化值:0.0
    > 字符型数组元素的默认初始化值:0 (或理解为'\u0000')
    > boolean型数组元素的默认初始化值:false
    > 引用数据类型数组元素的默认初始化值:null


3.2 动态初始化方式2:(比如:int[][] arr = new int[3][])
1)外层元素,默认存储null
2)内层元素,不存在的。如果调用会报错(NullPointerException)
 

package com.atguigu2.two;

/**
 * 二维数组的基本使用(难点)
 *
 * @author 尚硅谷-宋红康
 * @create 13:08
 */
public class TwoArrayTest {
	public static void main(String[] args) {
		//1. 数组的声明与初始化
		//复习
		int[] arr1 = new int[]{1,2,3};
		//方式1:静态初始化:数组变量的赋值和数组元素的赋值同时进行
		int[][] arr2 = new int[][]{{1,2,3},{4,5},{6,7,8,9}};

		//方式2:动态初始化1:数组变量的赋值和数组元素的赋值分开进行
		String[][] arr3 = new String[3][4];
		//方式2:动态初始化2
		double[][] arr4 = new double[2][];

		//其它正确的写法:
		int arr5[][] = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
		int[] arr6[] = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
		int arr7[][] = {{1,2,3},{4,5},{6,7,8,9}}; //类型推断
		String arr8[][] = new String[3][4];

		//错误的写法
//		int[][] arr9 = new int[3][3]{{1,2,3},{4,5,6},{7,8,9}};
//		int[3][3] arr10 = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
//		int[][] arr11 = new int[][10];


		//2. 数组元素的调用
		//针对于arr2来说,外层元素{1,2,3}、{4,5}、{6,7,8,9} 内层元素:1,2,3,4,5,6,7,8,9
		//调用内层元素
		System.out.println(arr2[0][0]);//1
		System.out.println(arr2[2][1]);//7

		//调用外层元素
		System.out.println(arr2[0]);//[I@776ec8df

		//测试arr3,arr4
		arr3[0][1] = "Tom";
		System.out.println(arr3[0][1]);
		System.out.println(arr3[0]);//[Ljava.lang.String;@4eec7777

		arr4[0] = new double[4];
		arr4[0][0] = 1.0;

		//3. 数组的长度
		System.out.println(arr2.length);//3
		System.out.println(arr2[0].length);//3
		System.out.println(arr2[1].length);//2
		System.out.println(arr2[2].length);//4

		//4. 如何遍历数组
		for (int i = 0; i < arr2.length; i++) {
			for(int j = 0;j < arr2[i].length;j++){
				System.out.print(arr2[i][j] + "\t");
			}
			System.out.println();
		}



	}
}
package com.atguigu2.two;

/*
 * 二维数组的基本使用(难点) (承接TwoArrayTest.java)
 * 
 *  @author 尚硅谷-宋红康
 *  @create 13:18
 * 
 */

public class TwoArrayTest1 {
	public static void main(String[] args) {

		//5. 数组元素的默认初始化值
		//以动态初始化方式1说明:
		int[][] arr1 = new int[3][2];
		//外层元素默认值:
		System.out.println(arr1[0]);//[I@776ec8df
		System.out.println(arr1[1]);//[I@4eec7777
		//内层元素默认值:
		System.out.println(arr1[0][0]); //0


		boolean[][] arr2 = new boolean[3][4];
		//外层元素默认值:
		System.out.println(arr2[0]);//[Z@3b07d329
		//内层元素默认值:
		System.out.println(arr2[0][1]);//false

		String[][] arr3 = new String[4][2];
		//外层元素默认值:
		System.out.println(arr3[0]); //[Ljava.lang.String;@41629346
		//内层元素默认值:
		System.out.println(arr3[0][1]);//null

		//********************************
		//以动态初始化方式2说明:
		int[][] arr4 = new int[4][];
		//外层元素默认值:
		System.out.println(arr4[0]);//null
		//内层元素默认值:
		System.out.println(arr4[0][0]);//报错


//		String[][] arr5 = new String[5][];
//		//外层元素默认值:
//		System.out.println(arr5[0]);//null
//		//内层元素默认值:
//		System.out.println(arr5[0][0]);//报错

		//6. 数组的内存解析


	}
}

 4、数组-常见算法操作:特征值计算、数组赋值与复制

案例1:定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,总和,平均值,
并输出出来。

要求:所有随机数都是两位数:[10,99]
提示:求[a,b]范围内的随机数: (int)(Math.random() * (b - a + 1)) + a;

public class ArrayExer01 {
    public static void main(String[] args) {
        //1. 动态初始化方式创建数组
        int[] arr = new int[10];
        //2. 通过循环给数组元素赋值
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int)(Math.random() * (99 - 10 + 1)) + 10;
            System.out.print(arr[i] + "\t");
        }

        System.out.println();

        //3.1 求最大值
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(max < arr[i]){
                max = arr[i];
            }
        }
        System.out.println("最大值为:" + max);

        //3.2 求最小值
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(min > arr[i]){
                min = arr[i];
            }
        }
        System.out.println("最小值为:" + min);


        //3.3 求总和
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        System.out.println("总和为:" + sum);

        //3.4 求平均值
        int avgValue = sum / arr.length;
        System.out.println("平均值为:" + avgValue);


    }
}

案例2:评委打分

分析以下需求,并用代码实现:

(1)在编程竞赛中,有10位评委为参赛的选手打分,分数分别为:5,4,6,8,9,0,1,2,7,3

(2)求选手的最后得分(去掉一个最高分和一个最低分后其余8位评委打分的平均值)

public class ArrayExer02 {
    public static void main(String[] args) {

        int[] scores = {5,4,6,8,9,0,1,2,7,3};
        //声明三个特征值
        int sum = 0;
        int max = scores[0];
        int min = scores[0];

        for (int i = 0; i < scores.length; i++) {
            sum += scores[i]; //累加总分
            //用于获取最高分
            if(max < scores[i]){
                max = scores[i];
            }
            //用于获取最低分
            if(min > scores[i]){
                min = scores[i];
            }
        }

        int avg = (sum - max - min) / (scores.length - 2);
        System.out.println("去掉最高分和最低分之后,平均分为:" + avg);


    }
}

案例3:使用二维数组打印一个 10 行杨辉三角。

   提示:
   1. 第一行有 1 个元素, 第 n 行有 n 个元素
   2. 每一行的第一个元素和最后一个元素都是 1
   3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
   yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];

public class YangHuiTest {
    public static void main(String[] args) {

        //1. 创建二维数组
        int[][] yangHui = new int[10][];

        //2.使用循环结构,初始化外层数组元素
        for(int i = 0;i < yangHui.length;i++){
            yangHui[i] = new int[i + 1];
            //3. 给数组的元素赋值
            //3.1 给数组每行的首末元素赋值为1
            yangHui[i][0] = yangHui[i][i] = 1;
            //3.2 给数组每行的非首末元素赋值
            //if(i >= 2){
                for(int j = 1;j < yangHui[i].length - 1;j++){ //j从每行的第2个元素开始,到倒数第2个元素结束
                    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();
        }


    }
}

案例3:复制、赋值

使用简单数组
(1)创建一个名为ArrayTest的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
(3)显示array1的内容。
(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
(5)打印出array1。

思考:array1和array2是什么关系?
【answer】array1和array2是两个变量,共同指向了堆空间中的同一个数组结构。即二者的地址值相同。

拓展:修改题目,实现array2对array1数组的复制

public class ArrayExer04_1 {
    public static void main(String[] args) {
        //(1)创建一个名为ArrayExer04的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
        int[] array1,array2;
        //(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
        array1 = new int[]{2,3,5,7,11,13,17,19};
        //(3)显示array1的内容。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
        //(4)复制array1数组给array2,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
        array2 = new int[array1.length];
        for (int i = 0; i < array1.length; i++) {
            array2[i] = array1[i];
        }

        System.out.println();
        System.out.println(array1);
        System.out.println(array2);

        for (int i = 0; i < array2.length; i++) {
            if(i % 2 == 0){
                array2[i] = i;
            }
        }

        System.out.println();//换行
        //(5)打印出array1。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
    }
}

案例4:复制、赋值

使用简单数组
(1)创建一个名为ArrayTest的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
(3)显示array1的内容。
(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
(5)打印出array1。

思考:array1和array2是什么关系?
【answer】array1和array2是两个变量,共同指向了堆空间中的同一个数组结构。即二者的地址值相同。

拓展:修改题目,实现array2对array1数组的复制

public class ArrayExer04_1 {
    public static void main(String[] args) {
        //(1)创建一个名为ArrayExer04的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
        int[] array1,array2;
        //(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
        array1 = new int[]{2,3,5,7,11,13,17,19};
        //(3)显示array1的内容。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
        //(4)复制array1数组给array2,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
        array2 = new int[array1.length];
        for (int i = 0; i < array1.length; i++) {
            array2[i] = array1[i];
        }

        System.out.println();
        System.out.println(array1);
        System.out.println(array2);

        for (int i = 0; i < array2.length; i++) {
            if(i % 2 == 0){
                array2[i] = i;
            }
        }

        System.out.println();//换行
        //(5)打印出array1。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
    }
}

 5、数组-常见算法操作:数组的反转、扩容、与缩容

案例:
定义数组:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
如何实现数组元素的反转存储?你有几种方法。

public class ArrayExer05 {
    public static void main(String[] args) {
        int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};

        //遍历
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
        System.out.println();

        //反转操作
        //方式1:
//        for(int i = 0;i < arr.length/2;i++){
//            //交互arr[i] 与 arr[arr.length - 1 - i]位置的元素
//            int temp = arr[i];
//            arr[i] = arr[arr.length - 1 - i];
//            arr[arr.length - 1 - i] = temp;
//        }


        //方式2:
        for(int i = 0,j = arr.length - 1;i < j;i++,j--){
            //交互arr[i] 与 arr[j]位置的元素
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }

        //方式3:不推荐
//        int[] newArr = new int[arr.length];
//        for(int i = arr.length - 1;i >= 0;i--){
//            newArr[arr.length - 1 - i] = arr[i];
//        }

//        arr = newArr;

        //遍历
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}


案例1:数组的扩容:

现有数组 int[] arr = new int[]{1,2,3,4,5};
现将数组长度扩容1倍,并将10,20,30三个数据添加到arr数组中,如何操作?

public class ArrayExer01_1 {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5};

        //扩容1倍容量
//        int[] newArr = new int[arr.length * 2];
        //或
        int[] newArr = new int[arr.length << 1];

        //将原有数组中的元素复制到新的数组中
        for (int i = 0; i < arr.length; i++) {

            newArr[i] = arr[i];
        }

        //将10,20,30三个数据添加到新数组中
        newArr[arr.length] = 10;
        newArr[arr.length + 1] = 20;
        newArr[arr.length + 2] = 30;

        //将新的数组的地址赋值给原有的数组变量
        arr = newArr;

        //遍历arr
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}

案例:数组的缩容:

现有数组 int[] arr={1,2,3,4,5,6,7}。现需删除数组中索引为4的元素。

public class ArrayExer01_2 {
    public static void main(String[] args) {
        int[] arr={1,2,3,4,5,6,7};

        int deleteIndex = 4;

        //方式1:不新建数组
//        for(int i = deleteIndex;i < arr.length - 1;i++){
//            arr[i] = arr[i + 1];
//        }
//
//        //修改最后元素,设置为默认值
//        arr[arr.length - 1] = 0;


        //方式2:新建数组,新的数组的长度比原有数组的长度少1个
        int[] newArr = new int[arr.length - 1];
        for (int i = 0; i < deleteIndex; i++) {
            newArr[i] = arr[i];
        }

        for(int i = deleteIndex;i < arr.length - 1;i++){
            newArr[i] = arr[i + 1];
        }

        arr = newArr;

        //遍历arr数组
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }

    }
}

6、数组-常见算法操作:查找、冒泡排序、快速排序

排序算法的衡量标准:① 时间复杂度(最重要) ② 空间复杂度 ③ 稳定性
Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n<sup>2</sup>)<Ο(n<sup>3</sup>)<…<Ο(2<sup>n</sup>)<Ο(n!)<O(n<sup>n</sup>)

排序的分类:内部排序(内存中排序);外部排序(外部存储设备+内存)

案例1:线性查找

定义数组:int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67};
查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。

public class LinearSearchTest {
    public static void main(String[] args) {

        int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67};

        int target = 5;
//        target = 15;

        //查找方式:线性查找
        //方式1:
//        boolean isFlag = true;
//        for(int i = 0;i < arr1.length;i++){
//            if(target == arr1[i]){
//                System.out.println("找到了" + target + ",对应的位置为:" + i);
//                isFlag = false;
//                break;
//            }
//        }
//
//        if(isFlag){
//            System.out.println("不好意思,没有找到此元素");
//        }

        //方式2:
        int i = 0;
        for(;i < arr1.length;i++){
            if(target == arr1[i]){
                System.out.println("找到了" + target + ",对应的位置为:" + i);
                break;
            }

        }

顺序查找:
    > 优点:算法简单;
    > 缺点:执行效率低。执行的时间复杂度O(N)


案例2:二分法查找

定义数组:int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100};
查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。

public class BinarySearchTest {
    public static void main(String[] args) {

        int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100};

        int target = 5;
//        target = 17;

        int head = 0;//默认的首索引
        int end = arr2.length - 1;//默认的尾索引


        boolean isFlag = false;//判断是否找到了指定元素

        while(head <= end){

            int middle = (head + end) / 2;

            if(target == arr2[middle]){
                System.out.println("找到了" + target + ",对应的位置为:" + middle);
                isFlag = true;
                break;
            }else if(target > arr2[middle]){
                head = middle + 1;
            }else{//target < arr2[middle]
                end = middle - 1;
            }
        }

        if(!isFlag){
            System.out.println("不好意思,未找到");
        }
    }
}

二分法查找:
    > 优点:执行效率高。执行的时间复杂度O(logN)
    > 缺点:算法相较于顺序查找难一点;前提:数组必须有序

案例3:使用冒泡排序,实现整型数组元素的排序操作

比如:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};

public class BubbleSortTest {
    public static void main(String[] args) {
        int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};

        //遍历
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }

        //冒泡排序,实现数组元素从小到大排列
        for(int j = 0;j < arr.length - 1;j++){
            for (int i = 0; i < arr.length - 1 - j; i++) {
                if(arr[i] > arr[i + 1]){
                    //交互arr[i] 和 arr[i + 1]
                    int temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }

            }
        }

        System.out.println();
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}

> 冒泡排序:最简单,需要大家会手写。时间复杂度:O(n^2)

案例4:使用快速排序,实现整型数组元素的排序操作

比如:int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };

public class QuickSort {
	public static void main(String[] args) {
		int[] data = {9, -16, 30, 23, -30, -49, 25, 21, 30};
		System.out.println("排序之前:");
		for (int i = 0; i < data.length; i++) {
			System.out.print(data[i]+" ");
		}

		quickSort(data);//调用实现快排的方法

		System.out.println("\n排序之后:");
		for (int i = 0; i < data.length; i++) {
			System.out.print(data[i]+" ");
		}
	}

	public static void quickSort(int[] data) {
		subSort(data, 0, data.length - 1);
	}

	private static void subSort(int[] data, int start, int end) {
		if (start < end) {
			int base = data[start];
			int low = start;
			int high = end + 1;
			while (true) {
				while (low < end && data[++low] - base <= 0)
					;
				while (high > start && data[--high] - base >= 0)
					;
				if (low < high) {
					//交换data数组[low]与[high]位置的元素
					swap(data, low, high);
				} else {
					break;
				}
			}
			//交换data数组[start]与[high]位置的元素
			swap(data, start, high);

			//经过代码[start, high)部分的元素 比[high, end]都小

			//通过递归调用,对data数组[start, high-1]部分的元素重复刚才的过程
			subSort(data, start, high - 1);
			//通过递归调用,对data数组[high+1,end]部分的元素重复刚才的过程
			subSort(data, high + 1, end);
		}
	}

	private static void swap(int[] data, int i, int j) {
		int temp = data[i];
		data[i] = data[j];
		data[j] = temp;
	}
}

> 快速排序:最快的,开发中默认选择的排序方式;掌握快速排序的实现思路;时间复杂度:O(nlogn)

7、数组-Arrays工具类的使用与数组中常见的异常

数组工具类Arrays的使用 (熟悉)

1. Arrays类所在位置: 处在java.util包下

2. 作用:
java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。

public class ArraysTest {
	public static void main(String[] args) {
		//1. boolean equals(int[] a,int[] b):比较两个数组的元素是否依次相等
		int[] arr1 = new int[]{1,2,3,4,5};
		int[] arr2 = new int[]{1,2,3,4,5};
		arr2 = new int[]{1,2,3,5,4};

		System.out.println(arr1 == arr2);

		boolean isEquals = Arrays.equals(arr1,arr2);
		System.out.println(isEquals);//true ---> false


		//2. String toString(int[] a):输出数组元素信息。
		System.out.println(arr1); //[I@776ec8df

		System.out.println(Arrays.toString(arr1));


		//3.void fill(int[] a,int val):将指定值填充到数组之中。
		Arrays.fill(arr1,10);

		System.out.println(Arrays.toString(arr1));

		//4. void sort(int[] a):使用快速排序算法实现的排序
		int[] arr3 = new int[]{34,54,3,2,65,7,34,5,76,34,67};
		Arrays.sort(arr3);

		System.out.println(Arrays.toString(arr3));

		//5. int binarySearch(int[] a,int key):二分查找
		//使用前提:当前数组必须是有序的
		int index = Arrays.binarySearch(arr3,15);
		if(index >= 0){
			System.out.println("找到了,索引位置为:" + index);
		}else{
			System.out.println("未找到");
		}



	}
}

1. 数组的使用中常见的异常小结

> 数组角标越界的异常:ArrayIndexOutOfBoundsException
> 空指针的异常:NullPointerException


2. 出现异常会怎样?如何处理?
> 一旦程序执行中出现了异常,程序就会终止执行。
> 针对异常提供的信息,修改对应的代码,避免异常再次出现。

角标yue'jie

public class Test {
    public static void main(String[] args) {
// 1. 数组角标越界的异常:
        int[] arr = new int[10];
        //角标的有效范围:0、1、2、...、9
		System.out.println(arr[10]);
		System.out.println(arr[-1]);

    }
}

 空指针异常

public class Test {
    public static void main(String[] args) {
// 2. 空指针异常:
        //情况1:
		int[] arr1 = new int[10];

		arr1 = null;

		System.out.println(arr1[0]);//NullPointerException
    }
}
public class Test {
    public static void main(String[] args) {
//情况2:
		int[][] arr2 = new int[3][];

//		arr2[0] = new int[10];//此行代码不存在时,下一行代码出现NullPointerException

		System.out.println(arr2[0][1]); //NullPointerException


    }
}

public class Test {
    public static void main(String[] args) {

        //情况3:
		String[] arr3 = new String[4];
		System.out.println(arr3[0].toString());//NullPointerException
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/261561.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【java】java学习笔记

1. 快速入门 // Hello类 public class Hello {// main方法public static void main(String[] args) {System.out.println("hello world!");} } 在控制台输入以下命令&#xff0c;对.java文件&#xff08;源文件&#xff09;进行编译操作&#xff0c;生成Hello.clas…

提前预判和确认再做 现货白银投资的两种思路

在现货白银投资中&#xff0c;对于交易的步骤长期有两种看法。一种是提前预判行情并提前布局。另外一种是等待行情启动再做布局。这种两种方法要怎么选呢&#xff1f;笔者将从自己的角度出发&#xff0c;对这个问题进行讨论。 我们来看一下前一种的投资者&#xff0c;他们喜欢提…

个人或企业为啥要搭建及自己的知识付费平台才有前景?

在知识经济的时代&#xff0c;知识的传播和变现显得愈发重要。许多个人或企业选择将自己的知识、技能和经验通过课程的形式进行传播&#xff0c;以实现知识的价值。然而&#xff0c;在使用其他平台进行课程销售的过程中&#xff0c;他们常常面临着一些问题和挑战。 首先&#…

基于FPGA的简易BPSK和QPSK

1、框图 2、顶层 3、m_generator M序列的生成&#xff0c;输出速率为500Kbps 4、S2P是串并转换模块 将1bit的m序列转换到50M时钟下的2bit M序列数据&#xff08;就有4个象限&#xff09;&#xff1b; 5、my_pll是生成256M的时钟作为载波&#xff0c;因为sin和cos信号的…

linux 性能优化-内存优化

CPU 管理一样&#xff0c;内存管理也是操作系统最核心的功能之一。内存主要用来存储系统和应 用程序的指令、数据、缓存等。 1.内存原理 1.1.内存映射 1.1.1.日常生活常说的内存是什么? 我的笔记本电脑内存就是 8GB 的这个内存其实是物理内存物理内存也称为主存&#xff0…

【分享】Word技巧之锁定部分区域

在编辑Word文档过程中&#xff0c;如果部分内容已经确定好&#xff0c;但又担心不小心做了改动&#xff0c;我们可以将这部分内容锁定起来&#xff0c;使之无法编辑更改&#xff0c;不清楚的小伙伴一起来看看如何设置吧。 首先&#xff0c;打开Word文档后&#xff0c;用鼠标选…

Opencv 入门三(视频滑动条窗口)

视频滑动条窗口源码如下&#xff1a; #include "opencv2\highgui\highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <fstream> using namespace std; int g_slider_position 0; // 滑动条的位置 …

Vue3-24-组件-异步组件的介绍

什么是异步组件 个人理解 &#xff1a;异步组件 就是在用到这个组件的时候再进行加载&#xff0c;而不是 一上来就全部加载完成。即用即取的一个思想。异步组件中使用到的方法 &#xff1a; defineAsyncComponent () 方法 &#xff1a; 返回一个Promise 对象; 我们在开发过程中…

Java 线程管理中的锁

Monitor 概念 Java 对象头 Mark Word: Monitor (锁) Monitor 被翻译为监视器或管程 每个 Java 对象都可以关联一个 Monitor 对象&#xff0c;如果使用 synchronized 给对象上锁&#xff08;重量级&#xff09;之后&#xff0c;该对象头的Mark Word 中就被设置指向 Monitor 对…

uniapp整合echarts(目前性能最优、渲染最快方案)

本文echarts示例如上图,可扫码体验渲染速度及loading效果,下文附带本小程序uniapp相关代码 实现代码 <template><view class="source

python flask+vue实现前后端图片上传

python flaskvue实现前后端图片上传 vue代码如下&#xff1a; <template><div><input type"file" change"handleFileChange"/><button click"uploadFile">上传</button><br><img :src"imageUrl&…

深度相机—TOF、RGB双目、结构光原理及优势对比

烟台致瑞图像视觉技术2021-03-18 15:14 目前的深度相机根据其工作原理可以分为三种&#xff1a;TOF、RGB双目、结构光。 一、TOF TOF是Time of flight的简写&#xff0c;直译为飞行时间的意思。所谓飞行时间法3D成像&#xff0c;是通过给目标连续发送光脉冲&#xff0c;然后…

sourcetree 无效的源路径 细节提示:系统找不到指定的文件

工具–>选项–>git 直接下拉到底 点击红框&#xff0c;重新下载一个内嵌git就可以了 我感觉是因为改变了原有git安装路径的问题

2023 英特尔On技术创新大会直播 |探索视觉AI的无限可能

2023 英特尔On技术创新大会直播 | 探索视觉AI的无限可能 前言一未来的 AI&#xff1a;释放视觉 AI 真正潜力二AI技术突破、视觉Al挑战及前沿研究创新三全尺度视觉学习全尺度视觉学习示例1.GridConv 实现三维人体姿态估计更高准确率2.KW 预训练及迁移模型性能3.无数据增强稠密对…

大数据时代,如何基于机密虚拟化技术构建数据安全的“基石”

云布道师 2023 年 10 月 31 日-11 月 2 日&#xff0c;2023 云栖大会在中国杭州云栖小镇举行&#xff0c;阿里云弹性计算产品专家唐湘华、阿里云高级安全专家刘煜堃、蚂蚁集团高级技术专家肖俊贤三位嘉宾在【云服务器 & 计算服务】专场中共同带来题为《大数据时代&#xf…

使用MybatisPlus置空某些指定字段

当前的MybatisPlus默认会对空实体内的字段不置空&#xff0c;所以才引出了此种方法&#xff0c;很方便简单&#xff1a; 使用 Wrappers.lambdaUpdate方法就可以解决&#xff0c;方法的源码如下&#xff1a;条件为entity内的值&#xff0c;使用lambdaUpdate去set空的值 举个例子…

ETLCloud与简道云结合,实现企业信息同步

ETLCloud介绍 ETLCloud是一个集离线数据集成ETL、ELT、CDC实时数据集成、编排调度、数据服务API为一体的数据集成平台(DataOps)&#xff0c;一站式满足企业的各种最为复杂的数据集成场景。提供私有化部署能力和云原生架构&#xff0c;满足企业不同发展阶段的业务需求。 提供开放…

【蓝桥杯一对一保奖辅导】国奖学姐蓝桥杯经验分享

目录 写在前面有关报名费如何准备&#xff1f;看书 /练习 /分类 /总结比赛技巧与指导 写在前面 蓝桥杯对于计算机专业相关的同学来说是非常值得参加的。 蓝桥杯相对于ACM比赛而言获奖难度较小&#xff0c;只要掌握技巧&#xff0c;拿到 省一甚至国奖是比较容易的&#xff0c;但…

每日一题,二维平面

给你 二维 平面上两个 由直线构成且边与坐标轴平行/垂直 的矩形&#xff0c;请你计算并返回两个矩形覆盖的总面积。 每个矩形由其 左下 顶点和 右上 顶点坐标表示&#xff1a; 第一个矩形由其左下顶点 (ax1, ay1) 和右上顶点 (ax2, ay2) 定义。 第二个矩形由其左下顶点 (bx1, …

LVM系统逻辑卷

1.lvm的来源 我们在工作中经常遇到服务器存储数据的分区磁盘空间不够的情况&#xff0c;尤其是当我们的业务是视频的时候&#xff0c;大批量用户上传和下载视频&#xff0c;磁盘空间需要不停的调整。如果我们作为运维每天的工作就是加硬盘是不是有点扯&#xff0c;而且换硬盘的…
最新文章