JavaSE——语法基础篇

一.概述

1.计算机组成部分

计算机主要分为硬件软件

  • 硬件是可看到的一些物理部分(一些电子元器件)。

常见的硬件:

1)CPU :Center Processing Unit 中央处理器------- 指令控制和数值计算(日常工作任务)。

2)内存:临时存储数据的存储设备---RAM------内存不通电的时候,数据也就不见了。

3)显卡GPU:Graphic Processing Unit 图形图像处理单元------计算图形数据(图形图像任务)。

4)存储设备:永久性存储设备ROM----- 任何数据存储形式都是二进制。(机械硬盘、固态硬盘、U盘 、光盘、移动硬盘 )

5)输入输出设备:

输入:键盘---字符数据、鼠标---定位数据、麦克风---声音数据、扫描仪---图形图像文本数据。

输出:显示器---图形图像数据 、扬声器---声音数据、打印机---图形图像文本数据。

 6)网络设备:

输入:互联网上下载数据。 

输出:本地上传数据到互联网。

  • 软件提供看不见的指令,这些指令控制硬件并且使得硬件完成特定的任务。

2.人机交互方式

如何与计算机打交道

1) 图形化界面:操作简单,表现直观,容易上手操作,步骤繁琐,占用空间大 。

2)命令行: CMD(Command )窗口---操作复杂,命令较多,不容易 上手,步骤简单,占用空间小,适合远程。

常用dos命令

c:-----进入C盘根目录、 d:----- 进入D盘根目录、 cd -----xxx 进入xxx目录、 dir -------查看当前目录下的文件和目录、 cd / ------进入到当前所在盘符根目录、cd .. -----返回上级目录 、cls -----清屏 、exit -----退出cmd

3.计算机语言

计算机由一系列物理硬件组成,之间的沟通方式就是电信号,高低电压-二进制数,所以和计算机之间交流,得通过二进制来做,早期的编程语言/命令都以二进制形式存在。

机器语言

据平台不同,表现形式也不同,为让计算机能够懂得人类,人类必须以二进制的形式向计算机输入数据。

汇编语言

使用一些单词(助记符),将一些常用的操作用单词表示,在程序中慢慢出现了人类的语言。这种代码计算机不懂,还得将这些助记符包括数据转换成对应的二进制给计算机进行计算。转换的工具------汇编器。汇编语言计算方式,还是计算机的计算方式。

高级编程语言

从20世纪50年代产生的高级编程语言:C语言----C++语言---Java语言---C#---Python

高级编程语言完全由单词,符号和数字组成,并且书写流程也是符号人类流程。计算机不能懂这段代码,还得将代码进行转换二进制提交给计算机。转换的形式-----编译,解释

  • 静态编译语言:C 、C++、 Java

1)静态:在定义变量时明确的数据类型区分。

2)编译:将源代码全部进行编译,生成一个可执行的二进制文件,计算机去执行这个二进制文件来运行程序。(翻译一本英文书)

  • 动态解释语言:Python、JS

1)动态:在定义变量时候没有明确的数据类型区分。 

2)解释:将源代码从头到尾,读一行,译一行, 运行一行。(同声传译)

4.软件的定义

软件

一系列按照特定顺序组织的计算机数据与指令的集合。

软件的分类

1)系统软件(操作系统):控制和管理底层硬件的一套指令,操作系统为用户提供最基本的计算机功能。

2)应用软件:基于系统软件之上的,为用户带了特定领域服务。

 软件开发

去编写上述软件。

软件开发的流程: 1. 需求分析 2. 编码实现 3. 测试编码 4. 上线运维 5. 更新迭代 6. 下线

软件岗位:移动端软件研发 Android IOS - 物联网 、Web前端研发 - 数据可视化工程师、 PC端研发 、后端研发

5. Java语言介绍

前身Oak(橡树),1994年詹姆斯高斯林和他的团队开发出来的嵌入式编程语言。随着互联网的发展,编程互联网应用程序开发语言(面向对象),到2010年Sun公司被Oracle 收购,Java属于Oralce的子产品。

Oracle公司主要业务: 数据库- Oralce数据库- 把民间产品MySQL也收购了、 Linux服务器操作系统Solaris(redhat Ubuntu 深度 SUSE)、 Java

Microso公司主要业务: SQL Server、 Windows/Windows Server、 C++/C#

Java技术架构

1)JavaSE Java Standard Edition Java标准版:桌面型应用程序

2)JavaEE Java Enterprise Edition Java企业版:服务器应用程序

3)JavaME Java Micro Edition Java微型版:嵌入式应用程序

Java最大的特点——跨平台

一个软件可以在多个平台上运行,而不用更改软件的内容。 是因JVM(Java Virtual Machine)Java虚拟机。 Java源代码文件后缀名为xxx.java 所编译出来的二进制文件后缀名为xxx.class ,JVM主要负责将java语言的字节码文件转换为本地操作系统指令的一个工具软件。 所以,最终是字节码文件在跨平台。

6.Java开发环境搭建

  • JRE(Java Runtime Environment)Java运行环境-仅仅想运行Java程序,JRE = JVM + 核心类库
  • JDK(Java Development Kit)Java开发工具包-想要开发一个Java程序,JDK = 开发工具 + JRE

jdk安装目录介绍

bin目录---binary-开发工具、 javac.exe-java编译工具 、 java.exe-java运行工具

db目录---支持数据库开发的一些工具包

include目录---一些链接底层的一些C头文件代码

jre目录---jdk自带的运行环境

lib目录---library 放的是一些第三方Java库

javafx-src.zip---javafx图形化界面开发的源码包

src.zip---Java本身的源代码包

7.运行Java程序

VSCode代码编辑器 

关联代码所在的文件夹---文件-打开文件夹-选择文件夹

 步骤一:新建Java源代码文件并写入类

点击新建文件,输入Java源代码文件名称和后缀名。

步骤二:编译该源代码文件

打开控制台窗口cmd,将目录切换到所选文件夹目录下 ,再输入 javac 类名.java 对源代码文件进行编译 ,如果没有任何输出,则表明编译成功,并生成同名的字节码文件 类.class 。

步骤三:运行该字节码文件

输入 java 类名 

注意:源代码文件名和类名必须一致

8.常见错误

语法错误

编译的过程中出现的一些错误

1)单词评写2)遗漏分号 3)使用中文符号的问题4) 大括号不匹配 5)遗漏关键字单词

运行错误

编译能够通过,在运行期间出现的问题

逻辑错误

代码的运行结果和自己认为的结果不一!

遗漏括号

遗漏分号

遗漏引号

非法使用中文符号

单词拼写错误

二.基本数据与运算

1.关键字

被高级编程语言赋予特殊含义的一些单词,关键字一般都是由小写字母组成,不能乱用。

定义数据类型:byte 、short 、int、 long、 float、 double、 char、 boolean、 void、 class、 interface

定义数据类型值:true、 false、 null

定义流程控制语句:if else、 switch、 case、 default、 while、 do for、 break 、continue、 return

定义访问权限修饰符:public、 protected、 private

定义继承关系:extends、 implements

定义实例对象:new 、this 、super、 instanceof

定义函数类型:static 、final、 abstract 、synchronized

处理异常:try、 catch、 finally、 throw、 throws

包:package、 import

其他的一些修饰:native 、assert 、volatile、transient

2.标识符

我们在程序中对变量、函数、类、接口、常量所定义的名称(自定义)。

标识符必须满足以下组成规则:

1) 标识符可以由数字、字母、下划线 _ 、美元符 $ 组成

2)标识符不能以数字开头,当然下划线和美元符其实是可以开头的,但不推荐

3)标识符不能是关键字

4)标识符也不能是Java内置类的名称

5)标识符可以为任意长度,但必须是一个连续的词

6)标识符严格区分大小写

起名尽量要有含义,在一些特殊的情况下(循环里特殊数学符号),可以使用i j k m n 之类的。

标识符命名的规范:

1)大驼峰式:主要针对类名,接口名。所有单词的首字母大写

2)小驼峰是:主要针对于变量名,函数名。除了第一个单词之外,其他单词首字母大写

3)常量规范:所有单词字母大写,单词与单词之间用下划线分隔

4)包名规范:所有单词字母小写,单词与单词之间用句号 . 分隔

myAge 变量名、 getMax() 函数名、 MyMoney 类名 接口名 、MAX_VALUE 常量名 、com.oupeng.java 包名

 3.注释

注解和说明程序的一些程序中的内置文本信息的,但这些内置文本不属于代码的范畴。 在对含有注释的源代码进行编译时,所生成的字节码中不含有注释。

注释主要有三种:

1) 单行注释

//注释内容 直到换行为止

2)多行注释

/* 注释内容 内部可以进行换行 */

3)文档注释

/* *注释内容 内部可以进行换行 */

文档注释可被编译器识别,生成相应 的程序说明书。对某一个类进行文档生成时,该类必须是public型

注释除了有解释说明程序的功能之外,还可以用来调试程序。,多行注释中,不能再出现多行注释 。

4.常量与进制

常量:在程序中直接出现的一些数据(字面量)

  • 整数常量
  • 小数常量
  • 字符常量:由一个字母、数字、符号被单引号( '' )标识的数据
  • 字符串常量:由若干个字母、数字、符号被双引号( "" )标识的数据
  • 布尔类型常量
  • null常量

二转十:

10010101的十进制是 128 + 16 + 4 + 1 = 149

十进制149 = 9 * 10^0 + 4 * 10^1 + 1 * 10^2

二进制1011 = 1 * 2^ 0 + 1 * 2^ 1 + 0 * 2 ^2 + 1 * 2 ^3 

一个二进制位称之为是一个比特 bit;八个比特称之为一个字节 byte;字节是计算机当中的最小计 数单元

1 byte = 8 bit、 1 kb = 1024 byte、 1 mk = 1024 kb 、1 gb = 1024 mb 、1 tb = 1024 gb

十转二 :

110101 = 1 + 4 + 16 + 32 = 53

二转八:

10010101--》 010-010-101 --》 0225 = 5 * 8^ 0 + 2 * 8^1 + 2 * 8 ^2 

二转十六 :

10010101 --》 1001-0101 --》 0x95 = 5 * 16 ^0 + 9 *16 ^1

二转六:

二进制转为十进制再转为六进制

负数的二进制:

-29的二进制,将正数部分的二进制先取反再加1 

5.变量

变化的量 ,变量的本质就是在内存中程序所处的进程中的一个临时存储区域 ,该区域的存储值有限制的, 变化必须是同类型的或向下兼容的,有其自身的物理内存地址-指针, 该区域中存储值的限制和数据的变化类型由数据类型来决定, 该区域中其空间的分配和空间的物理内存地址由计算机底层来决定。

数据类型

  •  基本数据类型:在变量的空间中存储数据

整型: byte 1字节 2^8 256 -128~127 -2^7 ~ 2^7 - 1、 short 2字节 2^16 65536 -32768~32767 -2^15 ~ 2^15 - 1、 int 4字节、 long 8字节

浮点型: float 4字节、 double 8字节

字符型: char 2字节、 布尔型 boolean 不确定

在常量中,整型常量默认int类型,小数常量默认是double类型 布尔类型,如是单一变量的话,在JVM中true被认为是1 false被认为是0 所以是4字节存 如果是布尔类型数组的话,在JVM中true和false被认为是byte类型 1字节。

  • 引用数据类型:数据是在堆内存中存储,变量仅仅存放的是数据在堆内存中的地址

字符串

数组

对象

在Java中,但凡存储在堆内存中的数据,统称为对象。

6.运算符

算术运算符

 +、-、*、/、%、

a++、++a、a--、--a

赋值运算符

+=、-=、*=、/=、%=

比较运算符

运算的结果为布尔类型

> 、 < 、>= 、 <= 、 != 、

逻辑运算符

& 单与、 | 单或、 ^ 异或、 ! 非、 && 双与、 || 双或

位运算符

& 位与、 | 位或、 ^ 位异或、 >> 右移、 << 左移

三目运算符 

数据类型 变量名 = 布尔表达式?值1:值2;

7.常见错误

未声明变量,未初始化变量而使用变

整型溢出问题 

取整错误

小数的问题:小数主要去的是近似值 想要得到一个0.5这个值的话 有可能会得到0.4999999

整数的问题:1/3 = 0.3333 * 3 = 0.99999 数学上1 超出预期的除法问题 /左右两边是整数,结果为整数,如果出现小数则结果为小数

额外冗余的输入对象

三.流程控制语句

1.if条件语句

单分支if语句

多分支if-else语句

多分支if-else-if语句

if(布尔表达式1){

语句组A;

}else if(布尔表达式2){

语句组B;

}else if(布尔表达式3){

语句组C;

}else {

语句组D;

}

 switch分支语句

与if分支语句一样,都是对条件的判断。switch一般用在条件较多的情况下,if语言可以对区间值或固定值进行判断,switch只能对固定值进行判断。

switch使用细节:

 1)switch所传入的变量,char,byte,short,int,String或者枚举类型

2)值1,值2,一直到值n,这几个值必须是同一个数据类型的

3)当变量匹配的相关case的值的时候,执行case中的语句,直到遇到break结束;如果该case语句 中没有break,则继续向下执行,直到遇到另外一个break结束

2.for循环语句

循环主要解决具有规律性的且具有重复性的代码问题,避免程序冗余。

循环四要素:

1)循环的初始化:循环的第1次执行从哪里开始

2)循环的继续条件:循环从当前轮是否向后执行下一轮

3)循环体:需要被循环执行的部分

4)循环的步长、周期---当前循环到下一轮循环之间的变化

循环问题:

1) 已知循环次数的 一般用for语句做 。

2)未知循环次数但是已知循环结束条件 一般用while语句做。

 for (1循环的初始化;2.循环的继续条件;4.循环的步长) {

3.循环体

}

3. while循环语句

1)while循环主要用于解决循环次数未知,但循环结束条件已知的情况。

2)while其实和for循环是可以相互转换的,是因为都逃不开循环四要素。

1.循环的初始化

while (2.循环继续条件) {

3.循环体

4.循环的步长、周期

}

4. break、continue跳转语句

break-----终止语句,终止的是break最近的一层循环 。

continue-----跳过语句,跳过本次循环开启下一轮循环 。

四.常用类

1.Math类

用于数学计算的一个工具类 ;对于工具类而言,里面大部分成员都是static(静态的)。

自带常量

1)static double E-----自然对数

2)static double PI-----圆周率

取整方法

1)static double ceil(double a)-----向上取整

2)static double floor(double a)-----向下取整

3)static long round(double a)-----四舍五入

三角函数

1)static double sin(double a)-----正弦函数-参数是弧度值

2)static double cos(double a)-----余弦函数

3)  static double tan(double a)-----正切函数

4)static double toDegrees(double a)-----弧度转角度

5)static double toRadians(double angles)-----角度转弧度

6)static double asin(double a)-----反正弦函数

7)static double acos(double a)-----反余弦函数

8)static double atan(double a)-----反正切函数

指数函数

1)static double pow(double a, double b)-----求a的b次幂

2)static double sqrt(double a)-----求a的平方

3)static double cbrt(double a)-----求a的立方

其他方法

1)static double abs(double a)-----求a的绝对值

2)static double hypot(double deltX, double deltY)-----返回两点间距离

3)static double max(a,b)-----返回a和b之间的最

4)static double min(a,b)-----返回a和b之间的最

5)static double random()-----返回 [0,1)之间的随机小数

public class Sample {
    public static void main(String[] args) {
        System.out.println(Math.E);
        System.out.println(Math.PI);
        System.out.println(Math.ceil(2.1));
        System.out.println(Math.ceil(2.8));
        System.out.println(Math.ceil(-2.1));
        System.out.println(Math.ceil(-2.8));
        System.out.println(Math.floor(2.1));
        System.out.println(Math.floor(2.8));
        System.out.println(Math.floor(-2.1));
        System.out.println(Math.floor(-2.8));
        System.out.println(Math.round(2.1));
        System.out.println(Math.round(2.8));
        System.out.println(Math.round(-2.1));
        System.out.println(Math.round(-2.8));
        System.out.println(Math.sin(Math.PI/6));
        System.out.println(Math.cos(Math.PI/3));
        System.out.println(Math.tan(Math.PI/4));
        System.out.println(Math.toDegrees(Math.PI/2));
        System.out.println(Math.toRadians(90));
        System.out.println(Math.cbrt(8));
        System.out.println(Math.hypot(0 - 1, 0 - 1));
    }
}

2.Scanner类

用于负责数据输入的类,底层是和IO流相关。

1)String next()-----获取遇到空格为止的一个字符串

2)String nextLine()------获取遇到回车为止的一个字符串

3)int nextInt()-----获取下一个整数 byte short long

4)double nextDouble()

5)boolean nextBoolean()

6)float nextFloat()

import java.util.Scanner;
public class Sample {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("输入一句话:");
        String line = input.nextLine();
        System.out.println(line);
        System.out.print("输入两个单词:");
        String word1 = input.next();
        String word2 = input.next();
        String word3 = input.next();
        System.out.println(word1);
        System.out.println(word2);
    }
}

3.Random类

用于产生随机数。

1)boolean nextBoolean():随机产生布尔类型值

2)double nextDouble():随机生成0.0~1.0之间的小数

3)double nextInt():随机生成一个整数0~2^32的整数

4)double nextInt(n):随机生成一个整数[0,n)的整数 

import java.util.Random;
public class Sample {
    public static void main(String[] args) {
        Random random = new Random();
        for (int i = 1; i <= 10; i++) {
            System.out.print(random.nextBoolean() + " ");
        }
        System.out.println();
        for (int i = 1; i <= 10; i++) {
            System.out.print(random.nextInt(2) + " ");
        }
        System.out.println();
        for (int i = 1; i <= 10; i++) {
            System.out.print(random.nextInt() + " ");
        }
        System.out.println();
     }
}

4.String类

String是个类,描述的是字符串。

在Java代码中,所有字符串常量(字符串字面量)都是 String类的一个实例对象。并且字符串一旦创建,则不可修改! 其长度,内容皆不可修改。所 以对字符串内容改变,不能在原地改,只能重新创建一个字符串。

获取相关

1)char charAt(int index)-----获取指定角标index处的字符

2)int indexOf(int ch)-----获取指定字符(编码)在字符串中第一次(从左到右)出现地方返回的是角标~~若是-1 ,表示不存在 。

3)  int lastIndexOf(int ch)-----获取指定字符(编码)在字符串中第一次(从右到左)出现地方返回的是角标

4)  int indexOf(String str)-----获取指定字符串在本字符串中第一次(从左到右)出现地方返回的是角标

5)  int lastIndexOf(String str)-----获取指定字符串在本字符串中第一次(从右到左)出现地方返回的是角标

6)  int length()-----获取字符串的长度(字符的个数)

7)String[] split(String regex)-----将字符串按照regex的定义进行切割(regex指正则表达式)

8)String substring(int beginIndex)-----截取一段子字符串,从beginIndex开始到结尾

9)  String substring(int beginIndex, int endIndex)-----截取一段子字符串,从beginIndex开始到 endIndex(不包含endIndex)

判断相关

1)int compareTo(String anotherString)-----按照字典顺序比较两个字符串的大小

2)boolean contains(String another)-----判断当前字符串是否包含指定字符串

3)another boolean equals(String another)-----比较当前字符串与指定字符串内容是否相同

4)boolean isEmpty()-----判断当前字符串是否为空~~length() == 0

5)boolean startsWith(String prefix)-----判断该字符串是否以prefix开头

6)boolean endsWith(String suix):判断该字符串是否以suix结尾

修改相关

1)String toLowerCase()-----将字符串中所有的英文字母全部变为小写

2)String toUpperCase()-----将字符串中所有的英文字母全部变为大写

3)String trim()-----删除字符串两端多余空格

4)String replace(char oldCh,char newCh)-----将字符串中oldCh字符替换成newCh字符

删除字符串中左右两端出现的空格,不用trim

public class Sample {
    public static void main(String[] args) {
        String str = " 123123123 12123 ";//去空格后"123123123 12123"
        int l = 0;
        int r = str.length() - 1;
        while (str.charAt(l) == ' ') {
           l++;
        }
        while (str.charAt(r) == ' ') {
           r--;
        }
        System.out.println("[" + str.substring(l,r + 1) + "]");
     }
}

在字符串"abcbcbcbcbcbc"中统计"bcb"出现的次数

1)贪心算法(5)

public class Sample {
    public static void main(String[] args) {
    //最好的算法KMP算法
    String s1 = "abcbcbcbcbcbc";
    String s2 = "bcb";
    int count = 0;
    for (int i = 0; i < s1.length() - s2.length() + 1; i++) {
       if (s1.charAt(i) == s2.charAt(0)) {
          if (s2.equals(s1.substring(i,i + s2.length()))) {
             count++;
          }
       }
    }
    System.out.println(count);
}

2)非贪心算法(3)

public class Sample {
    public static void main (string[] args) {
        String s1 = "abcbcbcbcbcbc";
        String s2 = "bcb";
        String temp = s1;
        int count = 0;
        while (true) {
            int index = temp.indexOf(s2);
            if (index == -1) {
                break;
            }
            count++;
            temp = temp.substring(index + s2.length());
         }
         System.out.println(count);
     }
}

查找两个字符串中最长的公共子串

public class Sample {
    public static void main(String[] args) {
        String s1 = "c is a program but is diffcult";
        String s2 = "Java is a program but is slow";
        for (int len = s2.length(); len > 0; len--) {
           for (int l = 0,r = len - 1; r < s2.length(); l++,r++) {
               String temp = s2.substring(l,r + 1);
               if (s1.contains(temp)) {
                  System.out.println(temp);
                  return;//直接结束程序
               }
           }
         }
     }
}

5.Character类

是char基本数据类型的包装类 。

1)  static boolean isDigit(char ch)-----判断字符是否是数字

2)  static boolean isLetter(char ch)-----判断字符是否是字母 

3)static boolean isLetterOrDigit(char ch)-----判断字符是否是数字或字母

4)static boolean isLowerCase(char ch)-----判断是否是小写字母

5)static boolean isUpperCase(char ch)-----判断是否是大写字母

6)static boolean isSpaceChar(char ch)-----判断是否空白字母(空格 、制表符、 回车)

将十六进制数字转为十进制

import java.util.Scanner;
public class Sample {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("输入一个十六进制的数字:");
        //0~9 A~F
        String hex = input.nextLine().toUpperCase();
        if (hex.length() == 0) {
           System.out.println("无任何输入!");
           return;//程序直接结束
        }
        for (int i = 0; i < hex.length(); i++) {
            char ch = hex.charAt(i);
            if (Character.isDigit(ch) || Character.isLetter(ch)) {
               if (Character.isLetter(ch) && (ch < 'A' || ch > 'F')) {
                  System.out.println("非法字符" + ch);
                  return;
                }
             } else {
                 System.out.println("非法字符" + ch);
                 return;
             }
         }
         int sum = 0;
         for (int i = hex.length() - 1; i >= 0; i--) {
             char ch = hex.charAt(i);
             if (Character.isDigit(ch)) {
                //'1' ? 1
                sum = sum + (int)Math.pow(16 , hex.length() - i - 1) * (ch - 48);
              } else {
                  //'A' - 65 + 10 -> 10
                  sum = sum + (int)Math.pow(16 , hex.length() - i - 1) * (ch - 55);
               }
          }
          System.out.println(sum);
     }
}

五.函数

1.函数的概念

何为函数

指一段具有独立功能的代码,减少代码冗余,提高程序的利用率和效率。

定义函数

  • 需要一个封闭的空间,将这段独立性的代码进行封装,用一对大括号
  • 需要对每一个封闭的空间进行命名,函数名
  • 函数所需要的一些原始数据
  • 函数所产生的一些结果数据

函数的语法格式

修饰符 函数类型 返回值类型 函数名(数据类型 数据1,数据类型 数据2,...) {

        独立功能的代码片段;

        return 函数的计算结果;

}

修饰符-----函数的访问权限,public private 默认 protected

函数类型------本地函数native,静态函数static,同步函数 synchronized

返回值类型------函数计算结果的数据类型,若函数没有返回值,则为void

函数名------函数的名称

参数列表------外界向函数传入的数据(实际参数),由这些参数变量进行接收(形式参数)

函数体-------具有独立功能的代码片段;

return------仅仅表示函数结束!若函数有返回值,则return后跟返回值;若没有返回值,则 return可以不写,但是是存在的(隐藏的在最后一行)

根据形参和返回值来看,函数分类

1)有参数有返回值

求三个数字当中的最大值 

public class Sample {
    public static void main(String[] args) {
        int max = getMax(1,2,3);
        System.out.println(max);
    }
    public static int getMax (int a , int b , int c) {
        /*
        if (a >= b && a >= c) {
            return a;
        }else if (b >= a && b >= c) {
            return b;
        }else {
            return c;
        }
        */
        if (a >= b && a >= c) {
            return a;
        }
        if (b >= a && b >= c) {
            return b;
        }
        if (c >= a && c >= b) {
            return c;
        }
        return -10000;
    }
}

2)有参数没返回值

将三个字符串的反转,并拼接打印

public class Sample {
    public static void main(String[] args) {
        print("123","456","789");
    }
    //123 456 789 =? 321654987
    public static void print(String s1 , String s2 , String s3) {
        System.out.println(reverse(s1) + reverse(s2) + reverse(s3));
    }
    public static String reverse(String s) {
        String res = "";
        for (int i = s.length() - 1; i >= 0; i--) {
            res += s.charAt(i);
        }
        return res;
    }
}

3)没参数有返回值

获取当前时间的字符串

public class Sample {
    public static void main(String[] args) {
        String currentTime = getTime();
        System.out.println(currentTime);
    }
    public static String getTime() {
        //获取总毫秒数
        long millis = System.currentTimeMillis();
        //计算总秒数
        long seconds = millis / 1000;
        //计算总分钟数
        long minutes = seconds / 60;
        //计算总小时数
        long hours = minutes / 60;
        //计算当前小时数
        long currentHours = hours % 24;
        //计算当前分钟数
        long currenrMinutes = minutes % 60;
        //计算当前秒数
        long currentSeconds = seconds % 60;
        return currentHours + ":" + currenrMinutes + ":" + currentSeconds;
    }
}

4)没参数没返回值

public class Sample {
    public static void main(String[] args) {
        getTime();
    }
    public static void getTime() {
        //获取总毫秒数
        long millis = System.currentTimeMillis();
        //计算总秒数
        long seconds = millis / 1000;
        //计算总分钟数
        long minutes = seconds / 60;
        //计算总小时数
        long hours = minutes / 60;
        //计算当前小时数
        long currentHours = hours % 24;
        //计算当前分钟数
        long currenrMinutes = minutes % 60;
        //计算当前秒数
        long currentSeconds = seconds % 60;
        System.out.println(currentHours + ":" + currenrMinutes + ":" + currentSeconds);
    }
}

总结定义函数时需要考虑: 

1)函数的运行有哪些未知的参数?

2)函数的运行结果有是什么?

3)明确参数和结果

4)明确内容和返回

5)函数到底要干什么?尽量将独立功能且重复性较高的代码片段提取出来

2.函数的运行原理

函数的运行是基于栈运行的,------一种先进后出的容器,栈是指JVM中的栈内存空间 。

每一个函数,叫做栈帧,栈帧中所包含的内容有函数的定义,参数列表,函数的执行内容代码 ;每一个函数要运行,就相当于这个栈帧进入到栈内存中(入栈) ;如果一个函数即将结束,将这个栈帧从栈顶移出(出栈);如果栈内存中有多个栈帧,运行的是最上面的栈帧,底下的栈帧暂停运行,直到该栈帧为栈顶元素。

比如:主函数先进栈,开始逐行运行,如果执行到第n行,调用另外一个函数A,则主函数在第n行 暂停运行,将另一个函数A的栈帧入栈,再继续逐行运行,直到函数A的内容执行完毕,函数A出栈,主函数接着从第n行继续向下执行,以此类推。

3.函数重载

同一个类中可以出现多个同名函数。

 区分同名函数是否是重载关系:

前提必须是同名,和返回值类型无关(返回值类型只和函 数的计算功能相关)和权限也没有关系,和形式参数的名称也无关!只和形式参数的数据类型有关 (数量,排列组合)

下列哪些是该函数的重载

 int show(int x, float y, char z) ------不算重载,数据类型都是int float char

void show(float b,int a,char c)------算重载,顺序不一样float int char

void show(int a,int b,int c):算重载,顺序不一样int int int double show():算重载,参数不一样

寻找重载函数的流程:

1)看是否有确切的参数定义匹配,int int 找 int int

2) 看是否有可兼容的参数定义匹配,int int找double double或int double或double int

3)如果可兼容的参数定义匹配较多,会报引用确定报错,引用不明确

4.函数的递归

指函数自身调用自身。 人用迭代,神用递归 但凡迭代能够解决的问题,递归都可以解决;递归能够解决的问题,迭代就不一定了。

相对而言,从内存的角度而言,函数如果过多的自我调用,势必会对内存不友好,占用过多 。通常来讲,同样的问题用递归写要比用迭代写代码量较少。

写递归时,一定要先确定递归结束条件-递归边界

递归使用情况:迭代的,数学归纳法的问题

六.数组

1.数组的概念及定义

数组主要用于解决大量数据计算与存储的问题

比如:输入100个数字,统计其中的最大值和最小值并计算平均值,创建100个变量,会有一堆ifelse语句,比较麻烦。

数组是Java提供的一种最简单的数据结构,可以用来存储一个元素 个数固定 类型相同 的有序集。

数组在内存中的情况

栈-----主要用于运行函数的内存,堆------主要用于存储数据对象的内存

每一个数组而言,都是存在堆内存当中,每一个数组都是一个对象

1)数组本质上就是在堆内存中一系列地址连续且空间大小相等的存储空间(变量),每一个存 储空间用来存储数据(基本,引用)

2)数组是在堆内存中存储,称之为是一个对数对象,并且在堆内存中存储的数据都有 默认初始化 的流程。所以数组创建之初,每一个存储空间里面都会被JVM初始化该数据类型对应的零值。

3)数组的地址是连续的,所以通过公式:An=A1+(n-1)*d可以快速访问到其他的元素,所以对于 数组而言查找元素比较快的。将元素的真实物理地址转换成对应的角标获取元素。

4)调用数组------通过一个变量存储该数组在堆内存当中的首元素的地址。

5)当数组一旦定义出来,其长度不可变,存储空间的内容是可变的,所以在定义数组的时候,要么把长度固定,要么直接输入相关的元素。

数组的定义方式

//创建一个指定长度且指定数据类型的一维数组,名称为数组名,虽然没有指定元素,但是会有默认值

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

//创建一个指定元素且指定数据类型的一维数组,名称为数组名,虽然有指定元素,还是有默认初始化这个步骤

 数据类型[] 数组名 = new 数据类型[]{数据1,数据2,...,数据n};

数据类型[] 数组名 = {数据1,数据2,...,数据n};

常用数组操作

1)数组遍历问题

public class Sample {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5,6,7,8,9};
        //String str str.length()-函数
        //int[] arr arr.length-属性
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i] * 10;
            System.out.println(arr[i]);
        }
        //通过角标遍历 可以在遍历的过程中对指定的元素进行修改
        //foreach遍历 主要针对的是一些可迭代对象 Iterable
        /*
        for (数据类型 变量名 : 可迭代容器) {
        }
        */
        for (int num : arr) {
            //num -> arr[i]
            num = num / 10;
            System.out.println(num);
        }
        //这种遍历方式 只能获取元素,不能修改元素
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

2)数组最值问题

public class Sample {
    public static void main(String[] args) {
        int[] arr = new int[]{3,6,8,2,9,4,5,1,7};
        int min = arr[0];
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < min) {
               min = arr[i];
             }
            if (arr[i] > max) {
               max = arr[i];
             }
        }
        System.out.println(max);
        System.out.println(min);
     }
}

3)数组扩容问题

public class Sample {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5};
        arr = add(arr,6);
        arr = add(arr,6);
        arr = add(arr,6);
        arr = add(arr,6);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
     }
     //在指定的数组arr中添加元素element
    public static int[] add(int[] arr, int element) {
        int[] newArr = new int[arr.length + 1];
        for (int i = 0; i < arr.length; i++) {
            newArr[i] = arr[i];
        }
        newArr[newArr.length - 1] = element;
        return newArr;
    }
}

4)选择排序算法

public class Sample {
    //选择排序
    public static void main(String[] args) {
        int[] arr = {8,9,2,6,7,1,4,5,3};
        for (int i = 0; i < arr.length - 1; i++) { //-1 n个数字没有第n轮
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[i] > arr[j]) {
                   swap(arr,i,j);
                }
            }
         }
         print(arr);
     }
     //[1, 2, 3, 4, 5]
     public static void print(int[] arr) {
         System.out.print("[");
         for (int i = 0; i < arr.length;i++) {
             System.out.print(arr[i]);
             if (i == arr.length - 1) {
                System.out.println("]");
             } else {
                System.out.print(", ");
             }
          }
      }
      public static void swap(int[] arr, int i, int j) {
          int temp = arr[i];
          arr[i] = arr[j];
          arr[j] = temp;
      }
}

5)冒泡排序算法

public class Sample {
    //冒泡排序
    public static void main(String[] args) {
        int[] arr = {8,9,2,6,7,1,4,5,3};
        for (int i = 0; i < arr.length - 1; i++) { //-1 n个数字只有n-1轮
            for (int j = i + 1; j < arr.length; j++) { //-1 避免重复比较
                if (arr[j] > arr[j + 1]) {
                   swap(arr,j,j+1);
                }
            }
        }
        print(arr);
     }
     public static void print(int[] arr) {
         System.out.print("[");
         for (int i = 0; i < arr.length;i++) {
             System.out.print(arr[i]);
             if (i == arr.length - 1) {
                System.out.println("]");
             } else {
                System.out.print(", ");
             }
          }
      }
      public static void swap(int[] arr, int i, int j) {
          int temp = arr[i];
          arr[i] = arr[j];
          arr[j] = temp;
      }
}

6)插入排序算法

public class Sample {
    //插入排序
    public static void main(String[] args) {
        int[] arr = {8,9,2,6,7,1,4,5,3};
        for (int i = 1; i < arr.length; i++) {
            int e = arr[i];
            int j = 0;
            for (j = i; j > 0 && arr[j - 1] > e; j--) {
                arr[j] = arr[j - 1];
            }
            arr[j] = e;
        }
        print(arr);
     }
     public static void print(int[] arr) {
         System.out.print("[");
         for (int i = 0; i < arr.length;i++) {
             System.out.print(arr[i]);
             if (i == arr.length - 1) {
                System.out.println("]");
             } else {
                System.out.print(", ");
             }
          }
      }
}

7)计数排序算法

public class Sample {
    //计数排序
    public static void main(String[] args) {
        int[] arr = {-2,9,-1,12,8,-3,6,7,4,5,2,1,0,8,6,7,4,-3,-2,-1,-1,7};
        int min = arr[0];
        int max = arr[0];
        //O(n)
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < min) {
               min = arr[i];
            }
            if (arr[i] > max) {
               max = arr[i];
            }
         }
         int[] temp = new int[max - min + 1];
         //对应关系 index = number - min number = index + min
         //O(n)
         for (int i = 0; i < arr.length; i++) {
             temp[arr[i] - min]++;
         }
         //temp[index] 表示index对应的数字number出现的次数
         int k = 0;
         //O(n)
         for (int index = 0; index < temp.length; index++) {
             while (temp[index] != 0) {
                   arr[k] = index + min;
                   k++;
                   temp[index]--;
             }
         }
         print(arr);
     }
     public static void print(int[] arr) {
         System.out.print("[");
         for (int i = 0; i < arr.length;i++) {
             System.out.print(arr[i]);
             if (i == arr.length - 1) {
                System.out.println("]");
             } else {
                 System.out.print(", ");
             }
          }
      }
}

8)基数排序算法

import java.util.LinkedList;
public class Sample {
    //基数排序
    public static void main(String[] args) {
        int[] arr = {102,203,321,13,12,78,96,34,37,28,6,8,5,6};
        //先找到最大值 决定轮数
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > max) {
               max = arr[i];
            }
        }
        int radex = (max + "").length();
        //创建十个桶 每一个桶是LinkedList
        LinkedList<Integer>[] queues = new LinkedList[10];
        for (int i = 0; i < queues.length; i++) {
            queues[i] = new LinkedList<Integer>();
        }
        //进行数字分类和规整
        //r=0个位 r=1十位 r=2百位...
        for (int r = 0; r < radex; r++) {
           //先按照r进行分类
            for (int i = 0; i < arr.length; i++) {
                int index = getIndex(arr[i],r);//获取数字的r位 返回该数字要去的桶的角标0~9
                queues[index].offer(arr[i]);
             }
             //然后在重新规整到arr里
             int k = 0;
             for (int index = 0; index < queues.length; index++) {
                 while(!queues[index].isEmpty()) {
                      arr[k++] = queues[index].poll();
                 }
             }
          }
          print(arr);
     }
     public static int getIndex(int number, int r) {
         //123 r=0
         //123 r=1
         //123 r=2
         int index = 0;
         for (int i = 0; i <= r; i++) {
             index = number % 10;
             number /= 10;
         }
         return index;
      }
      public static void print(int[] arr) {
          System.out.print("[");
          for (int i = 0; i < arr.length;i++) {
              System.out.print(arr[i]);
              if (i == arr.length - 1) {
                 System.out.println("]");
              } else { 
                  System.out.print(", ");
              }
          }
      }
}

9)二分查找算法

有一个前提,所查找的数据集必须是有序的(升序,降序)

public class Sample {
    //二分查找
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6,7,8,9};
        int min = 0;
        int max = arr.length - 1;
        int mid = (min + max) / 2;
        int key = 10;
        while (arr[mid] != key) {
              if (key < arr[mid]) {
                 max = mid - 1;
              }
              if (arr[mid] < key) {
                 min = mid + 1;
              }
              if (min > max) {
                 mid = -1;
                 break;
              }
              mid = (min + max) / 2;
         }
        System.out.println(mid);
     }
}

10)可变长参数列表

public class Sample {
    public static void main(String[] args) {
        show(1);
        show(1,2,3);
        show("hehe","lala","haha","xixi","heihei");
    }
    public static void show(int ... nums) {
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();
     }
     public static void show(String ... strs) {
         for (int i = 0; i < strs.length; i++) {
             System.out.print(strs[i] + " ");
         }
         System.out.println();
     }
}

2.二维数组

在表现形式上就是一个表格,在操作表格的时候以行列来操作

  0 1
0 0,0 0,1
1 1,0 1,1
2 2,0 2,1

二维数组的本质:一个一维数组,只不过该一维数组里面的元素是另一个一维数组

二维数组的定义 

public class Sample {
    public static void main(String[] args) {
        //数据类型[][] 矩阵名 = new 数据类型[row][col];
        int[][] matrix = new int[3][2];
        /*
        数据类型[][] 矩阵名 = new 数据类型[][] {
            {...},
            {...},
            {...}
        };
        数据类型[][] 矩阵名 = {
            {...},
            {...},
            {...}
        };
        */
        int[][] matrix2 = {
            {1,2,3},
            {4,5,6},
            {7,8,9}
        };
        for (int i = 0; i < matrix2.length; i++) {
            for (int j = 0; j < matrix2[i].length; j++) {
                System.out.print(matrix2[i][j] + " ");
            }
            System.out.println();
        }
        int[][] matrix3 = {
            {1},
            {1,2,3},
            {1,2,3,4},
            {7,6,5,4,3,2,1}
        };
        for (int i = 0; i < matrix3.length; i++) {
            for (int j = 0; j < matrix3[i].length; j++) {
                System.out.print(matrix3[i][j] + " ");
            }
            System.out.println();
        }
    }
}


 

Guess you like

Origin blog.csdn.net/weixin_49811734/article/details/112583639