当前位置:   article > 正文

Java学习笔记----第一部分:java基础编程(尚硅谷宋红康老师)_尚硅谷java笔记

尚硅谷java笔记

java知识学习

第一部分:Java基础编程

一、Java语言概述

1. Java基础图解:

请添加图片描述

2. 软件开发介绍:

2.1 软件开发:

软件,即一系列按照特定顺序组织的计算机数据和指令的集合。有系统软件和应用软件之分。

2.2 人机交互方式:

图形化界面(Graphical User Interface GUI):

  • 这种方式简单直观,使用者易于接受,容易上手操作。
    命令行方式(Command Line Interface CLI):
  • 需要有一个控制台,输入特定的指令,让计算机完成一些操作。较为麻烦,需要记录住一些命令。
2.3 常用DOS命令:

(1)常用命令:

  • md :创建目录
  • rd: 删除目录
  • cd : 进入指定目录
  • cd… : 退回到上一级目录
  • cd \: 退回到根目录
  • del : 删除文件
  • exit: 退出 dos 命令行
  • 补充:echo javase>1.doc

(2)常用快捷键:

  • ← → :移动光标
  • ↑ ↓:调阅历史操作命令
  • Delete和Backspace:删除字符

2. 计算机编程语言介绍:

2.1 语言分类:

(1)第一代语言:

机器语言:

  • 指令以二进制代码形式存在;

(2)第二代语言

汇编语言:

  • 使用助记符表示一条机器指令;

(3)第三代语言:

高级语言:

  • C、Pascal、Fortran面向过程的语言
  • C++面向过程/面向对象
  • Java跨平台的纯面向对象的语言
  • .NET跨语言的平台
  • Python、Scala…

3. Java语言概述:

3.1 各领域的应用:
  • 企业级应用
  • Android平台应用
  • 大数据平台开发
3.2 主要诞生:
  • Java语言是易学的
  • Java语言是强制面向对象的
  • Java语言是分布式的
  • Java语言是健壮的
  • Java语言是安全的
  • Java语言是体系结构中立的
  • Java语言是编译型的
  • Java是性能略高的
  • Java语言是原生支持多线程的

4. 运行机制及运行过程:

4.1 Java语言的特点:

(1)特点一:面向对象

两个基本概念:类、对象
三大特性:封装、继承、多态

(2)特点二:健壮性

程序在遇到意外错误或异常时能够正常运行而不崩溃的能力。换句话说,一个健壮的Java程序能够处理意外情况或错误,保持正常运行。

(3)特点三:跨平台性

  • write once,run anywhere;
  • 原理:JVM(Java虚拟机);
  • 理解:Java的源码可以在不同的操作系统(Windows、Linux、OS…)上运行;
4.2 Java两种核心机制:

(1)Java虚拟机 (Java Virtal Machine):

JVM(Java虚拟机)是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令,管理数据、内存、寄存器;

(1)垃圾收集机制 (Garbage Collection):

  • 它是自动释放程序不再使用的内存的机制。它可以防止内存泄漏,并确保程序的高效运行。垃圾收集器定期检查程序的内存,识别不再使用的对象,然后释放它们占用的内存。这个过程是自动的,不需要程序员进行显式的操作。
  • 但是在C语言中需要自己手动的释放内存,容易方法内存泄漏;

5. Java语言环境搭建:

5.1 JDK、JRE、JVM介绍:

(1)JDK(Java Development Kit Java开发工具包):

JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了 JRE。 所以安装了JDK,就不用在单独安装JRE了。

(2)JRE(Java Runtime Environment Java运行环境):

包括Java虚拟机(JVM :Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。

(3)jdk、JRE、JVM之间关系:

请添加图片描述

JDK=JRE+开发工具集(例如javac/Javac编译工具等)
JRE= JVM+Java SE标准类库

5.2 JDk与JRE下载和安装:
(1)JDK下载:

①官网:Oracle.com
请添加图片描述
②进入products(进入后拉到底部)——>java(进入后拉到底部)——>oracleJDK:
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

(2)JDk安装:

建议:安装路径不要有中文或者空格等特殊符号

  • ①步骤如下:(以jdk17.0.6为例)
    在这里插入图片描述

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

注意:一台电脑上可以安转多个不同版本的JDK

5.3 Java环境配置:

注意:

  • 环境配置决定jdk使用版本
  • path :windows系统执行命令时要搜寻的路径
(1)配置步骤:

①步骤一:

  • 打开【此电脑】的属性页面,在【系统】窗口中选择【高级系统配置】在【高级】窗口中选择【环境变量】进行配置:

请添加图片描述
②步骤二:

在系统变量(s)创建(W)-----> (输入变量名、和设置变量值)-----> 确定

在这里插入图片描述
③步骤三:

将新建的变量JAVA_HOME 添加到path路径下:

  • path :windows系统执行命令时要搜寻的路径;

在这里插入图片描述
在这里插入图片描述
④环境配置补充:
请添加图片描述

6. 开发体验——helloWorld:

6.1 编写、编译和运行:

(1)编写:

public class HelloWorld{   //注意:当修饰符为public时,文件名必须与类型相同
	public static void main(String [] args){
		System.out.println("hello world!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5

(2)编译和运行:

  • ①步骤:

将 Java 代码编写到扩展名为 .java 的文件中。
通过 javac 命令对该 java 文件进行编译

  • 代码:javac XxxYyy.java (此时文件不区分大小写,因为在Windows下不区分大小写)
    通过 java 命令对生成的 class 文件进行运行
  • 代码:java XxxYyy (XxxYyy:类名)
  • ②图解:
    请添加图片描述

7. 常见问题及解决方法:

(1)总结:

学习编程最容易犯的错是语法错误。Java要求你必须按照语法规则编写代码。
如果你的程序违反了语法规则,例如:忘记了分号、大括号、引号,或者拼错了单词,
java编译器都会报语法错误。尝试着去看懂编译器会报告的错误信息。

8. 注释(Comment):

分类:单行注释、多行注释、文档注释

8.1 单行和多行注释:

(1)单行注释:

//这是一个int类型的变量
int m;
  • 1
  • 2

(2)多行注释格式:

/*
 这是一句多行注释
*/
  • 1
  • 2
  • 3

(3)作用:

对所写程序进行解释说明,增强可读性。方便自己和他人;
调试所写的代码;

(4)特点:

单行注释和多行注释,注释了的内容不参与编译;
换言之,编译以后生成的,class结尾的字节码文件中不包含注释掉的信息;

(5)注意:

多行注释不能嵌套使用;

8.2 文档注释:

(1)文档注释格式: /** */

/**
  @author 指定java程序的作者
  @version 指定源文件的版本 
*/
  • 1
  • 2
  • 3
  • 4

(2)特点:

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

  • ①操作方式:(类必须是public)

前提:在源文件(.java文件)中使用了文档注释

//举例代码
public class Test{
	public static void main(String[] args) {
		System.out.println("Hello World!");
	}
	/**
		这是一个我说的方法....
	*/
	public static void say(String language){
		System.out.println("我正在用"+language+"交谈....");
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述

  • ②生成的文件:

点击打开产生的day01目录 ------> 双击(源文件名).html文件

在这里插入图片描述

在这里插入图片描述

9. Java API文档:

9.1 文档解释:

API (Application Programming Interface,应用程序编程接口)是 Java 提供的基本编程接口。
Java语言提供了大量的基础类,因此 Oracle 也为这些基础类提供了相应的 API文档,用于告诉开发者如何使用这些类,以及这些类里包含的方法。

网址:http://www.oracle.com/technetwork/java/javase/downloads/index.html
Additional Resources-Java SE 8 Documentation下载

请添加图片描述

在这里插入图片描述

9.2 API基本组成:

请添加图片描述
(1)API文档:

API文档打开之后,点击显示 ------> 索引 -----> 查找自己想查找的结构
例如:Scanner类

  • 在API文章中,会存在属性、构造器和方法三部分-----> 找到这些类成员可以点击查看(方法)内部结构

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

10. 编程风格:

(1)正确注释和注释风格:

使用文档注释来注释整个类或整个方法。
如果注释方法中的某一个步骤,使用单行或多行注释。

(2)正确的缩进和空白:

使用一次tab操作,实现缩进。
运算符两边习惯性各加一个空格。比如:2 + 4 * 5。

(3)书写代码块的风格:

Java API 源代码选择了行尾风格

请添加图片描述

11. 常用java开发工具:

(1)文本编辑工具:

记事本;
UltraEdit;
EditPlus;(开始将会使用一段时间)
TextPad;
NotePad;

(2)Java集成开发环境:

ntegrated Development Environment:IDE

  • JBuilder
  • NetBeans
  • Eclipse (会使用一段时间)
  • MyEclipse
  • IntelliJ IDEA(以后将会常使用)

二、Java基本语法:

1. 关键字和保留字:

1.1 关键字(keyword)定义和特点:

(1)定义:

被Java语言赋予了特殊含义,用做专门用途的字符串(单词);

(2)特点: 官方地址

关键字中所有字母都为小写;

1.2 保留字(reserved word):

Java保留字:现有Java版本尚未使用,但以后版本可能会作为关键字使 用。自己命名标识符时要避免使用这些保留字 goto 、const;

2. 标识符(Identifier):

2.1 标识符定义:

Java 对各种变量、方法和类等要素命名时使用的字符序列称为标识符;

  • 技巧:凡是自己可以起名字的地方都叫标识符。

(1)定义标识符的规则:

  • 由26个英文字母大小写,0-9 ,_或 $ 组成 ;
  • 数字不可以开头。
  • 不可以使用关键字和保留字,但能包含关键字和保留字。
  • Java中严格区分大小写,长度无限制。
  • 标识符不能包含空格。

(2)定义标识符的规范:

**包名:**多单词组成时所有字母都小写:xxxyyyzzz
**类名、接口名:**多单词组成时,所有单词的首字母大写:XxxYyyZzz
**变量名、方法名:**多单词组成时;第一个单词首字母小写,第二个单词开始每个单词首字母大 :xxxYyyZzz
**常量名:**所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ

(3)注意:

在起名字时,为了提高阅读性,要尽量有意义,“见名知意”
java采用unicode字符集,因此标识符也可以使用汉字声明,但是不建议使用。

3. 变量:

3.1 变量解释:

(1)变量概念:

内存中的一个存储区域
该区域的数据可以在同一类型范围内不断变化;
变量是程序中最基本的存储单元。包含变量类型、变量名和存储的值;

请添加图片描述
(2)变量作用:

用于在内存中保存数据;

(3)变量使用注意:

Java中每个变量必须先声明,后使用。
使用变量名来访问这块区域的数据 ;
变量的作用域:其定义所在的一对**{ }**内 ’
变量只有在其作用域内才有效 ;
同一个作用域内,不能定义重名的变量;

(4)变量声明:

语法:<数据类型> <变量名称>
例如:int var;

(5)变量赋值:

语法:<变量名称> = <值>
例如:var = 10;

(6)变量声明与赋值:

语法: <数据类型> <变量名> = <初始化值>
例如:int var = 10;

3.2 变量分类:
(1)按数据类型分类:

请添加图片描述
①基本数据类型(primitive type):

  • 数值型:

整数类型:byte、short、int、long
浮点类型:float、double

  • 字符型:char
  • 布尔型:boolean

②应用数据类型 (reference type):

:class
接口:interface
数组:[ ]

(2)按声明位置分类:

在方法体外,类体内声明的变量称为成员变量。 在方法体内部声明的变量称为局部变量。

①成员变量:

实例变量(不以static修饰)
类变量(以static修饰)

②局部变量:

形参(方法、构造器中定义的变量)
方法局部变量(在方法内定义)
代码块局部变量(在代码块内定义)

③注意:二者在初始化值方面的异同:

同:都有生命周期(作用域),都需要先声明后使用。
异:局部变量除形参外,需显式初始化,才能进行运算,成员变量会有默认值。

3. 3 变量使用规则:
(1)基本数据类型:
  1. 数值型:
  • i. 整数类型:

(bit: 计算机中的最小存储单位。byte:计算机中基本存储单元。)

请添加图片描述

  • byte:1字节=8bit (-128-127)
byte b1=-128; //声明byte变量并赋值
byte b2=127;

//byte b3=128; //编译不通过,超出byte变量的容量大小;
  • 1
  • 2
  • 3
  • 4
  • short:2字节=16bit (-215—215-1)
short s1=332;  //声明short变量并赋值
short s2=333;
  • 1
  • 2
  • int:4字节=32bit(-231—231-1)
//声明并赋值
int i1=334;  //声明int变量并赋值

//先声明,后赋值
int i2;      //声明int变量
i2=44;        //int变量赋值;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • long:8字节=64bit(-263—263-1)
    注意:定义long变量时,其赋于值必须以“L”或“l”结尾;
//声明long类型数据,赋值时,必须使用L或者l后缀
long l1=333L;   //声明long变量并赋值;
long l2=847L;
  • 1
  • 2
  • 3

总结:java中整型默认常量是int,声明long常量其后需要加“L”或“l”

  • ii. 浮点型:

请添加图片描述

  • float:单精度[4字节= 32bit(-3.403E38 ~ 3.403E38)]
    注意:定义float变量时,其赋于值必须以“f”或“F”结尾;
float f1=23.23f; //声明float变量并赋值;

//float f2=23.23; //类型不匹配,编译不通过(浮点型变量的默认类型为double类型)
  • 1
  • 2
  • 3

-double:双精度(8字节 = 64bit)

//注意:初始化过程中不能超出其类型的最大存储范围
double d1=88.34;
  • 1
  • 2

总结:java中浮点型默认常量是double,声明float常量其后需要加“f”或“F”

  1. 字符型:
  • char: 一个字符=2字节
    使用:①一个字符、②一个转义字符、③直接使用Unicode值表示字符常量
//普通字符
char c1='a';
char c2='中';
char c3='3';

//转义字符
char c4='\t'; //\t是制表符
char c5='\n'; //\n:换行符

//使用Unicode码
char c6='\u0094';  //Unicode值(Unicode码包含ASCII码)
char c7=97;   //表示字符a;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

注意:

  • Unicode:一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一 无二的编码,使用 Unicode 没有乱码的问题。
  • UTF-8 是在互联网上使用最广的一种 Unicode 的实现方式。
  1. 布尔型:

boolean:boolean类型数据只允许取值true和false,无null;
boolean 类型用来判断逻辑条件,一般用于程序流程控制:

  • if条件控制语句;
  • 三目运算符:(表达式1>表达式2)? 取值1:取值2;
  • while循环控制语句;
  • do-while循环控制语句;
  • for循环控制语句;
//注意:boolean类型变量初始化,只能时true或者false
//boolean类型变量的默认值是false(属性,数组元素)
boolean b1 = true;
boolean b2 = false;
  • 1
  • 2
  • 3
  • 4
(2)引用数据类型:
  1. 类:class

字符串数据类型:String

  • 使用方式与基本数据类型一致。例如:String str = “abcd”( 或String str = new String(“abcd”); );
  • 一个字符串可以串接另一个字符串,也可以直接串接其他类型的数据;其连接得到的结果都为字符串类型。
  • 举例:
//其他数据类型变量与字符串类型变量进行连接时,其结果都为字符串;
String s1="str";
String s2="ing";

String s3=s1+s2;  
System.out.println(s3); //string

int i1=33;
String s4=s1+i1;
System.out.println(s4); //str33
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

注意:String类型变量与其它八种基本数据类型进行“+”操作,表示连接;

  1. 接口:interface(其后会介绍)
//接口的定义方式
public interface Test{ }
//接口需要其他类来实现(略)

  • 1
  • 2
  • 3
  • 4
  1. 数组:[ ](其后会介绍)
//一维数组的声明方式:
int [] arr = new int[3];  //动态赋值
//.......
  • 1
  • 2
  • 3
3.4 基本数据类型转换:
(1)自动类型提升转换:

容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为:

  • 注意:此时容量大小指:表示可数的范围大小;

请添加图片描述

  • ②注意:
  • byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。
  • boolean类型不能与其它数据类型运算。
  • 当把任何基本数据类型的值和字符串(String)进行连接运算时(+),基本数据类型的值将自动转化为字符串(String)类型。
  • ③代码演示:
 		byte b1=22;
        byte b2=21;
        short s1=33;
        char c1='a';
        
        //byte、short、char之间不会相互转换
        int i4=b1+b2;
        int i3=c1+s1; 
        int i2=b1+s1; 
        
        int i1=23;
        long l1=44l;
        float f1=32.3f;
        double d1=23.3;
        
        //自动类型提升:容量小的->容量大的
        i1=b1;
        i1=s1;
        i1=c1;
        long l2=i1;
        float f2=i1;
        double d2=f1;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
3. 5 强制类型转换:
  • 自动类型提升逆过程,表示容量大到容量小的;(此时容量大小指:表示可数的范围大小)
  • 使用时要加上强制转换符:(),但可能造成精度降低或溢出,格外要注意;
  • (1)格式:
  • 数据类型 变量名 = (数据类型)变量值;
int i1=33;
char c1=22;
long l1=33l;
float f1=44.3f;

char c2=(char)i1;
int i2=(int)l1;
int i3=(int)f1;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • (2)注意:
  • boolean类型不可以转换为其它的数据类型。
  • 字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可 以实现把字符串转换成基本类型。
String s="233";
int i1=Integer.parseInt(s);   //调用包装类中的parseInt()方法
  • 1
  • 2
3.6 变量之进制:
  • 所有数字在计算机底层都以二进制形式存在;

(1)对于整数,有四种表示方式:

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

原码:直接将一个数值换成二进制数。最高位是符号位 ;
负数的反码:是对原码按位取反,只是最高位(符号位)确定为1。
负数的补码:其反码加1。
计算机以二进制补码的形式保存所有的整数
正数的原码、反码、补码都相同 。
负数的补码是其反码+1

注意:补码—->原码(过程相反:补码—[除符号位其他位取反]—-> 反码—[+1]——>原码)
请添加图片描述

  • ② 进制之间的转换:(二进制作为转换的桥梁)
    请添加图片描述

二进制——>八进制或十六进制:

  • 将二进制的三位或四位转换为八进制或十六进制的一位,逆转换只需逆过程

请添加图片描述

4. 运算符:

  • 运算符的种类:算术、赋值、比较(关系)、逻辑、位、三元运算符
4.1 算术运算符:
  • 运算符号:+(负号)、-(正号)、+、-、/、%、++、–、+(字符串连接)

请添加图片描述
(1)算术运算符需要注意:

  • 取模时,模数的正负号取决于被模数。
  • %:如果对负数取模,可以把模数负号忽略不记,如:5%-2=1。 但被模数是负数则不可忽略。此外,取模运算的结果不一定总是整数;
  • (前)++:先自增一,后再运算;
  • (后)++:先运算,后自增一;
  • (前)–:先自减一,后再运算;
  • (后)–:先运算,后再自减一;
int num1=22;
int num2=num1++;   
System.out.println(num2);  //22
int num3=++num1;  
System.out.println(num3);  //23
  • 1
  • 2
  • 3
  • 4
  • 5
4.2 赋值运算符:

运算符号:=、-=、+=、*=、/=、%=

(1)注意:

  • 当“=”两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理。支持连续赋值;
  • +=、-=、+=、*=、/=、%=运算时,并不会改变其原来的数据类型;
int num1=10;
num1+=2;     //int型的12

byte b1=12;
// b1=b1+2;  //类型不匹配,编译不通过(由式子的右边为int类型)
b1+=2;      //编译通过,值为byte型14;

int num2=15;
num2%=2;       //int型的1;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
4.3 比较(关系)运算符:

运算符号:== 、!=、>、<、>=、<=、interface

请添加图片描述

  • 运算结果:都是boolean型,也就是要么是true,要么是false。
  • >、<、>=、<=:只能使用在数值类型数据之间。
  • ==、!=:既可以使用在数值类型数据之间,也可以使用在引用数据类型之间;

(1)代码演示:

//创建两个对象:account1 和 account2
Account account1= new Account(100);   
Account account2= new Account(200);
boolean result= (account1==account2);   //false:地址值不同
  • 1
  • 2
  • 3
  • 4
int num1=23;
boolean b1=true;
if(b1==true){
  System.out.println(“结果为真”);
}else{
   System.out.println(“结果为假”);
}
if(num1>10){
  System.out.println(“结果为真”);
}else{
   System.out.println(“结果为假”);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
4.4 逻辑运算符:

运算符号:& 、&&、|、||、!、^

请添加图片描述
(1)注意:

  • ① 逻辑运算符所运算的对象为boolean型;
  • ② &(逻辑与)和&&(短路与)的异同点:
  • 两者运算结果一致;
  • 若左边结果为true,&和&&都会执行右边;
  • 若左边运算结果为false,&会继续执行右边,而&&不会继续执行右边运算;
int num1=12;
boolean b1=true;//b1=false
if(b1==true & ++num1>11){
  
}else{
  
}
System.out.println(num1);  //13(b1为true)  13(b1为false)

int num2=12;
boolean b2=true;//b2=false
if(b2==true && ++num2>11){
  
}else{
  
}
System.out.println(num2);  //13(b2为true时)  12(b2为false时)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • ③ |(逻辑或)和 ||(短路或)的异同点:
  • 两者运算结果一致;
  • 若左边结果为false,| 和 || 都会执行右边;
  • 若左边结果为true,| 会继续执行右边,而 || 不会继续执行右边运算;
int num3=10;
boolean b3=true;
if(b3==true | ++num3>9){
  
}else{
  
}
System.out.println(num3);  //11

int num4=10;
boolean b4=true;
if(b4==true || ++num4>9){
  
}else{
  
}
System.out.println(num4); //10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 注意:异或( ^ )与或( | )的不同之处是:当左右都为true时,结果为false。
4.5 位运算符:

运算符号:<<、>>、>>>、&、|、^、~:位运算是直接对整数的二进制进行的运算。

请添加图片描述
(1)位运算符操作的对象都是整型的数据:

  • ① <<(左移)
  • 在一定范围内,左移多少为,就是乘于2的多少次方;
  • 8<<2 ——> 8*22
  • ② >>(右移):
  • 在一定范围内,右移多少为,就是除以2的多少次方;
  • 8>>2 ——> 8/22
  • ③ 位运算的过程
    请添加图片描述

^(异或运算):
注意:

  • num3=num1^num2;
  • mum1=num3^num2;
4.6 三元运算符:

(1)格式:

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

  • 条件表达式为true时,则执行表达式1;否则执行表达式2;

(2)注意:

  • ① 表达式1和表达式2为同种类型;
  • ② 三元运算符与if-else的联系与区别:
  • 三元运算符可简化if-else语句 。
  • 三元运算符要求必须返回一个结果。
  • if后的代码块可有多个语句。
  • ③ 能使用三元运算符的就定可以使用if-else,反之不一定;
  • ④三元运算符与if-else都可以使用时,选择三元运算符;(原因:简洁并且效率高)

5. 程序流程控制:

5.1 顺序结构:
  • 程序从上到下逐行地执行,中间没有任何判断和跳转。

请添加图片描述

5.2 分支结构:
  • 根据条件,选择性地执行某段代码。有if…else和switch-case两种分支语句。
(1)分支语句一:if-else
  • ① 第一种:单分支
if(条件表达式){
  //执行语句;
}
  • 1
  • 2
  • 3
  • ② 第二种:双分支
if(条件表达式){
  //执行语句1;
}else{
  //执行语句2;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • ③ 第三种:多分支
if(条件表达式1){
  //执行语句1;
}else if(条件表达式2){
  //执行语句2;
}else if(条件表达式3){
  //执行语句3;
}else if(条件表达式4){
  //.............
  
}else{
   //执行语句n;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • ④ 注意:if-else使用说明
  • 条件表达式必须是布尔表达式(关系表达式或逻辑表达式)、布尔变量;
  • 语句块只有一条执行语句时,一对{ }可以省略,但建议保留;
  • if-else语句结构,根据需要可以嵌套使用
  • 当if-else结构是“多分支”时,最后的else是可选的,根据需要可以省略
  • 当多个条件是“互斥”关系时,条件判断语句及执行语句间顺序无所谓 ,当多个条件是“包含”关系时,“小上大下 / 子上父下”;
(2)键盘获取不同类型值(使用Scanner类)
  • ① 基本步骤:
  • 导包:import java.util.Scanner;
  • Scanner类的实例化:Scanner scanner = new Scanner(System.in);
  • 调用Scanner类的方法:**scanner.nextXxxx( ); ** ,来获取某一类型的值;
  • ② 说明:
  • 获取byte、short、int、long、float、double值,只需Scanner对象调用Scanner类的方法;格式:对象名.nextXxx( );
  • 获取String类型的值,只需对象名.next( ); 即可,注意,在键盘中我们不能直接获取char类型的值,而需要先获取String类型的值,在调用String类中的方法来获取char类型的值;格式:String对象名.charAt( 索引号);
(3)随机数产生:
  • ① 方式一:Math.random();
  • Math.random( ); ——> 所得double型变量数值的范围:[ 0.0 , 1.0)
  • 若需得到int型变量[a , b]范围的数:需要,(int)(Math.random( )*(b-a+1)+a)
  • ② 方式二:Random类
Random ran = new Random();
int num=ran.nexInt(number);  //此时生成的随机数为0~number-1
  • 1
  • 2
(4)分支语句二:switch-case
  • ① 格式:
switch(表达式){
  case 常量1:
    语句1;
    //break;
  case 常量2:
    语句2;
    //break;
  case 常量3:
    语句3;
    //break;
    .......
  default :
    //break;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • ② 使用说明:
  • switch(表达式)中表达式的值必须是下述几种类型之一:byte,short,char,int,枚举 (jdk 5.0),String (jdk 7.0);
  • case子句中的值必须是常量,不能是变量名或不确定的表达式值;
  • 同一个switch语句,所有case子句中的常量值互不相同;
  • break语句用来在执行完一个case分支后使程序跳出switch语句块;如果没有break,程序会顺序执行到switch结尾 ;
  • default子句是可任选的。同时,位置也是灵活的。当没有匹配的case时, 执行default;
(5)if-esle和switch-case语句对比:
  • 如果判断的具体数值不多,而且符合byte、short 、char、int、String、枚举等几 种类型。虽然两个语句都可以使用,建议使用swtich语句。因为效率稍高。
  • 其他情况:对区间判断,对结果为boolean类型判断,使用if,if的使用范围更广。 也就是说,使用switch-case的,都可以改写为if-else。反之不成立。
5.3 循坏结构:
  • 主要结构:while、do…while、for
  • 根据循环条件,重复性的执行某段代码。
  • 注意:JDK1.5提供了foreach循环,方便的遍历集合、数组元素。

循环四个组成部分:

  • ①初始化条件;
  • ②循环条件;——boolean型
  • ③循环体;
  • ④迭代条件;
(1)循环结构一:for循环
  • 语法格式:
for(①初始化条件; ②循环条件 ; ④迭代条件){
   ③循环体;
}
  • 1
  • 2
  • 3
  • 执行过程:
    ①——②——③——④——②——③——④——②——③——④…——②——③——④

  • 说明:(以下序号为循环组成部分代号)

  • ②循环条件部分为boolean类型表达式,当值为false时,退出循环 ;
  • ①初始化部分可以声明多个变量,但必须是同一个类型,用逗号分隔;
  • 可以有多个变量更新,用逗号分隔;
  • brake关键字:
  • 在循环中一旦执行到break关键字就跳出循环;
(2)循环结构二:while循环
  • 语法格式:
    ①初始化条件;
  while(②循环条件){
    ③循环体;
    ④迭代条件;
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 执行过程:
    ①——②——③——④——②——③——④——②——③——④……——②——③——④

  • 说明:

  • 注意不要忘记声明④迭代部分。否则,循环将不能结束,变成死循环。
  • for循环和while循环可以相互转换。
(3)循环结构三:do-while循环
  • 语法格式:
	①初始换条件;
  do{
    ③循环体;
    ④迭代条件;
  }while(②循环条件);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 执行过程:
    ①——③——④——②——③——④——②……——③——④——②

  • 说明:

  • do-while循环结构中的循环体至少执行一次;
(4)嵌套循环:
  • 将一个循环放在另一个循环体内,就形成了嵌套循环。其中, for ,while ,do…while均可以作为外层循环或内层循环。
  • 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的 循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开 始下一次的循环。
  • 设外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n次。
  • 外层循环表示行,内层循环表示列;
(5)特殊关键字使用:break和continue
  • ① break关键字使用:

break语句用于终止某个语句块的执行

	{ 
		 …… 
		break;
		 …… 
	}
  • 1
  • 2
  • 3
  • 4
  • 5

break语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块:

 label1: { …… 
​               label2: { …… 
​                      label3: { …… 
​                             break label2;  
​                                    …… 
​                                        } 
​                               } 
​                     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • ② continue关键字使用:
  • continue只能使用在循环结构中;
  • continue语句用于跳过其所在循环语句块的一次执行,继续下一次循环;
  • continue语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环;
public class ContinueTest {
  public static void main(String args[]){
    for (int i = 0; i < 10; i++) {
       if (i%2==0){
        continue;  //跳出当次循环
        } 
     System.out.print(i+" ") ;   // 1 3 5 7 9 
       }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • ③ break和continue关键字的说明:
  • break只能用于switch语句和循环语句中。
  • continue 只能用于循环语句中。
  • 二者功能类似,但continue是终止本次循环,break是终止本层循环。
  • break、continue之后不能有其他的语句,因为程序永远不会执行其后的语句。
  • 标号语句必须紧接在循环的头部。标号语句不能用在非循环语句的前面。
  • 很多语言都有goto语句,goto语句可以随意将控制转移到程序中的任意一条语句上,然后执行它。但使程序容易出错。Java中的break和continue是不同于goto的。
  • ④ 附加:return的使用:
  • return: 并非专门用于结束循环的,它的功能是结束一个方法。 当一个方法执行到一个return语句时,这个方法将被结束。
  • 与break和continue不同的是,return直接结束整个方法,不管这个return处于多少层循环之内;

三、数组

1. 数组的概述:

(1) 数组(Array):

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

(2) 数组的常见概念:

  • 数组名;
  • 下标(或索引);
  • 元素;
  • 数组长度;

(3) 数组介绍:

  • 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型
  • 创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址。
  • 数组的长度一旦确定,就不能修改。
  • 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
  • ① 数组的分类:
  • **按照维度:**一维数组、二维数组、三维数组、…。
  • **按照元素的数据类型分:**基本数据类型元素的数组、引用数据类型元素的数组(即对象数组)。

2. 一维数组的使用:

2.1 数组声明:
  • (1) 一维数组的声明方式:type var[ ]或 type[] var
int arr [];
int []arr1;
char []arr2;
double []b;
String []arr3;  //字符串类型变量数组(引用类型变量数组)
  • 1
  • 2
  • 3
  • 4
  • 5
2.2 数组的初始化:
(1) 动态初始化:
  • 数组声明且为数组元素分配空间与赋值的操作分开进行:
//例如:
int []arr=new int[4];
int [0]=1;
int [1]=2;
int [2]=3;
int [3]=4;

String [] names;
names= new String[3];
names[0]="于敏";
names[1]="钱学森";
names[2]="程开甲";
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
(2) 静态初始化:
  • 在定义数组的同时就为数组元素分配空间并赋值。
//例如:
int [] arrs= new int[]{1,2,3,4};
//int []arrs={1,2,3,4}

String []names= new String[]{"于敏","钱学森","程开甲"};
//String []names={"于敏","钱学森","程开甲"};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
2.3 数组元素的应用:

(1)定义并用运算符new为之分配空间后,才可以引用数组中的每个元素;
(2)数组元素的引用方式:数组名[数组元素下标]

  • 数组元素下标可以是整型常量或整型表达式。如a[3] , b[i] , c[6*i];
  • 数组元素下标从0开始;长度为n的数组合法下标取值范围: 0 —>n-1;如int a[]=new int[3]; 可引用的数组元素为a[0]、a[1]、a[2]。

(3)每个数组都有一个属性length指明它的长度,例如:a.length 指明数组a的长度(元素个数)。

  • 数组一旦初始化,其长度是不可变的;
2.4 数组元素的默认初始化值:
  • 数组是引用类型,它的元素相当于类的成员变量,因此数组一经分配空间,其中的每个元素也被按照成员变量同样的方式被隐式初始化。
public class Array{
  public static void main(String [] args){
    int []  arr= new int[3];
    System.out.println(arr[2]);  //arr[2]默认值为0
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 对于基本数据类型而言,默认初始化值各有不同;
  • 对于引用数据类型而言,默认初始化值为null(注意与0不同!)

请添加图片描述

2.5 一维数组内存解析:

栈(stack)和堆(heap)结构:

  • 栈: (stack):局部变量;
  • 堆:(heap):new出来的结构:对象、数组;

请添加图片描述
请添加图片描述

3. 多维数组使用:

3.1 多维数组的介绍:

(1)Java 语言里提供了支持多维数组的语法。
(2)如果说可以把一维数组当成几何中的线性图形, 那么二维数组就相当于是一个表格,像右图Excel 中的表格一样。
(3)对于二维数组的理解,我们可以看成是一维数组 array1又作为另一个一维数组array2的元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组。
(4)数组的length属性;(获取数组的长度,即一维数组的个数和一维数组中元素的个数)
(5) 二维数组值中数组元素的初始化值和一维数组类似;

  • byte、short、int、long——>0;
  • float、double——>0.0;
  • char——> 0 (ascll码中的’\u0000’);
  • boolean——> false;
  • 引用数据类型——> null或者地址;
3.2 二维数组初始化:(二维数组:数组中的数组)

(1)动态初始化:

  • ① 格式一:
int [][]arr= new int[3][2];
 //代码说明:
   //定义了名称为arr的二维数组
   //二维数组中有3个一维数组
   //每一个一维数组中有2个元素
   //一维数组的名称分别为arr[0], arr[1], arr[2]
   //给第一个一维数组1脚标位赋值为78写法是:arr[0][1] = 78;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • ② 格式二:
int [][]arr= new int [3][];
   //代码说明:
     // 二维数组中有3个一维数组。
    //每个一维数组都是默认初始化值null (注意:区别于格式1)
    
//可以对这个三个一维数组分别进行初始化
  arr[0] = new int[3]; 
  arr[1] = new int[1]; 
  arr[2] = new int[2];
  
   // 注意:
     // int[][]arr = new int[][3]; //非法
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

(2)静态初始化:

  • ① 格式三:
int [][]arr= new int[][]{{3,8,2},{2,7},{9,0,1,6}};
  //代码说明:
    //定义一个名称为arr的二维数组,二维数组中有三个一维数组
    //每一个一维数组中具体元素也都已初始化
    //第一个一维数组 arr[0] = {3,8,2};
    //第二个一维数组 arr[1] = {2,7};
    //第三个一维数组 arr[2] = {9,0,1,6};
    //第三个一维数组的长度表示方式:arr[2].length;

//注意特殊写法情况:
  //int[] x,y[]; x是一维数组,y是二维数组。
  //Java中多维数组不必都是规则矩阵形式
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
3.3 二维数组内存解析:
  • 栈(stack):存放局部变量;
  • 堆(heap):存放new出来的结构(数组、对象);
  • 方法区:静态域+常量池;

(1)举例一:

//举例代码:
int[][] arr1 = new int[4][];
arr1[1] = new int[]{1,2,3};
arr1[2] = new int[4];
arr1[2][1] = 30;
  • 1
  • 2
  • 3
  • 4
  • 5

请添加图片描述
(2)举例二:

//举例代码:
int[][] arr1 = new int[4][];
arr1[0] = new int[3];
arr1[1] = new int[]{1,2,3};
arr1[0][2] = 5;
arr1 = new int[2][];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

请添加图片描述

4. 数组中常见的算法:

  • 数组元素的赋值(杨辉三角、回形数等) ;
  • 求数值型数组中元素的最大值、最小值、平均数、总和等
  • 数组的复制、反转、查找(线性查找、二分法查找) ;
  • 数组元素的排序算法
4.1 数组元素的赋值:

(1)杨辉三角、回形数(略)等

  • ① 杨辉三角:
    在这里插入图片描述
//代码实现:
int [][]yanghui= new int[10][];
 	 //2.给数组元素赋值:
 	 for(int i=0;i<yanghui.length;i++) {
 		      //
 		     yanghui[i]= new int[i+1]; 
 		   //方式一:  
 		     //2.1:给首末尾元素赋值:
 		     	yanghui[i][0]=yanghui[i][i]=1;
 		     //2.2:给非首末元素赋值:
 		     		for(int j=1;j<yanghui[i].length-1;j++) {
 		     			yanghui[i][j]=yanghui[i-1][j-1]+yanghui[i-1][j];
 		     	}
 		    
 		   //方式二:
 		   /*
 		   	for(int j=0;j<yanghui[i].length;j++){
 		   		if(j==0 || i==j){
 		   			yanghui[i][j] = 1;  //给首末尾元素赋值;
 		   		}else{
 		   			yanghui[i][j]=yanghui[i-1][j-1]+yanghui[i-1][j];  //给非首末元素赋值
 		   		}
               } 	
             */  
 		 //3.遍历数组:
 		 for(int j=0;j<yanghui[i].length;j++) {
 			 System.out.print(yanghui[i][j]+" ");
 		 } 
 		 System.out.println();
 	 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
4.2 数组元素查找:
(1)线性查找:

注意:

  • 是将数组元素依次遍历下去,再查找是否有符合的元素;对于数值类型的变量而言,这样的查找效率非常低,而应该考虑二分查找的方式;
//代码演示:
int []array=new int []{1,2,3,5,4};
int dest=1;   //需要查找的元素
boolean isFlag=true;   //记录元素最终是否被查到的标签
for(int i=0;i<array.length;i++){   //遍历数组
  if(dest==array[i]){
    isFlag=false;
    System.out.println("找到了,索引为:"+i);
    break;
  }
}
if(isFlag){
  System.out.println("抱歉未找到");
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
(2)二分查找(折半查找):
  • 前提: 数组元素排好序;
  • 说明:是通过比较数组元素的中间值来进行查找元素的,这样大大的提高查找的效率;
  • 局限:只适用于数值数据类型;

代码演示:

int []arr= new int []{1,2,3,4,5,6,7};
boolean isFlag=true;
int dest=6;  //目的值
int head=0; //初始首索引
int end=arr.length-1;  //初始尾索引;
while(head<=end){
  int middle=(head+end)/2;
  //if条件分支中,进行数组元素的中间值和目的值进行比较
  if(dest=arr[middle]){   
    System.out.println("找到了,索引位置为:"+middle);
    isFlag=false;
    break;
  }else if(dest>arr[middle]){
    head=middle+1;
  }else{
    end=middle-1;
  }
}
if(isFlag){
  System.out.println("未找到");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
4.3 数组元素排序算法:
(1)排序算法的介绍:

① 排序解释:

  • 假设含有n个记录的序列为{R1,R2,…,Rn},其相应的关键字序列为 {K1,K2,…,Kn}。将这些记录重新排序为{Ri1,Ri2,…,Rin},使得相应的关键 字值满足条Ki1<=Ki2<=…<=Kin,这样的一种操作称为排序。
  • 通常来说,排序的目的是快速查找。

② 衡量排序算法的优劣:

  • 时间复杂度:分析关键字的比较次数和记录的移动次数;
  • 空间复杂度:分析排序算法中需要多少辅助内存;
  • 稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。

③ 排序算法分类:内部排序和外部排序:

  • 内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。
  • 外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。

④ 十大内部排序算法:

  • i. 选择排序:
    直接选择排序、堆排序

  • ii. 交换排序:
    冒泡排序快速排序

  • iii. 插入排序 :
    直接插入排序、折半插入排序、Shell排序

  • iv. 归并排序

  • v. 桶式排序

  • vi. 基数排序

  • ⑤ 算法介绍:
    算法的五大特征:
    请添加图片描述

  • 说明:满足确定性的算法也称为:确定性算法。现在人们也关注更广泛的概念,例如考虑各种非确定性的算法,如并行算法、概率算法等。另外,人们也关注并不要求终止的计算描述,这种描述有时被称为过程(procedure)。
4.4 排序算法的实现:
(1)交换排序(冒泡排序(掌握)、快速排序(了解)):

①冒泡排序:

  • 介绍:
  • 冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
  • 排序思想:
  • 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
  • 针对所有的元素重复以上的步骤,除了最后一个。
  • 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较为止。
  • 代码实现:
	//冒泡排序:
for(int i=0;i<array.length-1;i++) {  //1.需要比较的轮数:
  	for(int j=0;j<array.length-1-i;j++) {//2.每一轮中需要比较的次数:
  		if(array[j]>array[j+1]) {
			 int temp=array[j];
			 array[j]=array[j+1];
			 array[j+1]=temp;
  			  }
  		  }
  	  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

② 快速排序:

  • 介绍:
  • 快速排序(Quick Sort)由图灵奖获得者Tony Hoare发明,被列为20世纪十 大算法之一,是迄今为止所有内排序算法中速度最快的一种。冒泡排序的升 级版,交换排序的一种。快速排序的时间复杂度为O(nlog(n))。
  • 排序思想:
  • 从数列中挑出一个元素,称为基准(pivot)
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准 值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后, 该基准就处于数列的中间位置。这个称为分区(partition)操作。
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
  • 递归的最底部情形,是数列的大小是0或1,也就是永远都已经被排序好 了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代 (iteration)中,它至少会把一个元素摆到它最后的位置去。
  • 代码实现:
//交换数组元素的值
private static void swap(int[] data, int i, int j) {
		int temp = data[i];
		data[i] = data[j];
		data[j] = temp;
	}

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) {
					swap(data, low, high);
				} else {
					break;
				}
			}
			swap(data, start, high);
			
			subSort(data, start, high - 1);//递归调用
			subSort(data, high + 1, end);
		}
	}
	
	public static void quickSort(int[] data){
		subSort(data,0,data.length-1);
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 快速排序演示:
    请添加图片描述
    请添加图片描述
  • 举例:
    请添加图片描述
(2)插入排序(直接插入排序、希尔排序):

① 直接插入排序:

  • 排序思想:
  • 把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。

请添加图片描述

  • 代码实现:
//直接插入排序
for(int i=0;i<array.length-1;i++) {  //1.需要比较的轮数:
  	for(int j=i+1;j > 0;j--) {//2.每一轮中需要比较的次数:
  		if(array[j]< array[j-1]) {  //需要插入的元素是否小于有序元素
			 int temp=array[j];
			 array[j]=array[j-1];
			 array[j-1]=temp;
  		  }else{
  			    break;  //当无序中的元素大于有序元素的元素时,直接介绍比较
  			  }
  		  }
  	  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

② 希尔排序:

  • 排序思想:
  • 希尔排序的基本思想:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上有较大提高。

请添加图片描述

(3)选择排序(简单选择排序(掌握)、堆排序):

① 简单选择排序:

  • 排序思想
  • 在一组元素R[i]到R[n]中选择具有最小关键码的元素若它不是这组元素中的第一个元素,则将它与这组元素中的第一个元素对调。除去具有最小关键字的元素,在剩下的元素中重复第(1)、(2)步,直到剩余元素只有一个为止。

请添加图片描述

  • 代码演示:
//假定第一元素为最小;则将第一个元素依次和其后的元素进行比较,选出最小的元素,方法第一个元素处;以此循环,选出第二小的元素放于第二个元素处。
//注意:将该嵌套循环封装在方法中
for(int i=0;i<arr.length-1;i++){  //需要比较的轮数
  for(int j=i+1;j<arr.length;j++){  //每轮需要比较的次数
  	  if(arr[i]>arr[j]){  //该处元素依次和其后的元素进行比较
  	  	 int temp = arr[i];
  	  	 arr[i] = arr[j];
  	  	 arr[j] = temp;
  	  }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

② 堆排序:

  • 排序思想:

建立初始堆

  • 将排序码k1,k2k3,…,kn,表示成一棵完全二叉树,然后从第[n/2]个排序码(即树的最后一个非终端结点)开始筛选,使由该结点作根结点组成的子二叉树符合堆的定义,然后从第(n/2) -1个排序码重复刚才操作,直到第一个排序码止。这时候,该二叉树符合堆的定义,初始堆已经建立。

堆排序

  • 将堆中第一个结点(二叉树根结点)和最后一个结点的数据进行交换(k1与kn),再将k1~ kn-1重新建堆,然后k1和kn-1交换,再将k1~kn-2 重新建堆,然后k1,和kn-2交换,如此重复下去,每次重新建堆的元素个数不断减1,直到重新建堆的元素个数仅剩一个为止。这时堆排序已经完成,则排序码k1,k2,k3,…,kn已排成一个有序序列。
(4)归并排序:
  • 排序思想

是多次将了两个或两个以上的有序表合并成一个新的有序表。最简单的归并是直接将两个有序的子表合并成一个有序的表,即二路归并。

  • 二路归并排序:
  • 是将R[0……n-1]看成是n长度为1的有序序列,然后进行两两归并,得到[n/2]个长度为2(最后一个有序序列的长度可能为2)的有序序列,再进行两两归并,得到[n/4]个长度为4(最后一个有序序列的长度可能为4)的有序序列,……,直到得到长度为n的有序序列。

请添加图片描述

(5)排序算法性能对比:

请添加图片描述

  • 从平均时间而言:快速排序最佳。但在最坏情况下时间性能不如堆排序和归 并排序。
  • 从算法简单性看:由于直接选择排序、直接插入排序和冒泡排序的算法比较 简单,将其认为是简单算法。对于Shell排序、堆排序、快速排序和归并排序 算法,其算法比较复杂,认为是复杂排序。
  • 从稳定性看:直接插入排序、冒泡排序和归并排序时稳定的;而直接选择排 序、快速排序、 Shell排序和堆排序是不稳定排序。
  • 从待排序的记录数n的大小看:n较小时,宜采用简单排序;而n较大时宜采用改进排序。
(6)排序算法的选择:
  • 若n较小(如n≤50),可采用直接插入或直接选择排序。 当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插入,应选直接选择排序为宜。
  • 若文件初始状态基本有序(指正序),则应选用直接插入冒泡或随机的快速排序为宜;
  • n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或 归并排序

5. Arrays工具类的使用:

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

请添加图片描述
(1)代码演示:

	import java.util.Arrays;
	
	//工具类Arrays中方法的使用:  
	  int []arr=new int[] {1,23,3,4,5,5,8};
	  int []arr1=new int[] {-12,23,-88,3,78,98,4,-34,-13};
	  
	//1. boolean equals(int[] a,int[] b):判断两个数组是否相等。
	  	System.out.println(Arrays.equals(arr, arr1));
	  
	//2. String toString(int[] a):输出数组信息。
		  System.out.println(Arrays.toString(arr1));
		  System.out.println(Arrays.toString(arr));
	  
	//3. void fill(int[] a,int val) :将指定值填充到数组之中。
		  Arrays.fill(arr, 8);
		  System.out.println(Arrays.toString(arr));
	  
	//4. void sort(int[] a):对数组进行排序。
		  Arrays.sort(arr1);
		  System.out.println(Arrays.toString(arr1));
		  //[-88, -34, -13, -12, 3, 4, 23, 78, 98]
	  
	//5. int binarySearch(int[] a,int key):对排序后的数组进行二分法检索指定的值。
		  int number=Arrays.binarySearch(arr1, -88);  //值返回为负数,表示未找到;
		  System.out.println(number);  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

6. 数组使用中的常见异常:

(1)数组脚标越界异常(ArrayIndexOutOfBoundsException):

int[] arr = new int[2];
//System.out.println(arr[2]);    //运行不通过,数组角标越界
//System.out.println(arr[-1]);  //运行不通过,数组角标越界

//访问到了数组中的不存在的脚标时发生。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(2)空指针异常(NullPointerException):

//举例说明:
int[] arr = null;
//System.out.println(arr[0]);

int [] [] arr2 = new int [3][4];
arr[2] = null;
//arr[2].length;  //报异常

//arr引用没有指向实体,却在操作实体中的元素时。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

四、面向对象(上)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/573653

推荐阅读
相关标签