流程控制
用户交互Scanner
-
java.util.Scanner工具包来获取用户的输入
-
基本语法:
Scanner s = new Scanner(System.in);
通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前需要用hasNext()与hasNextLine()判断是否还有输入的数据。
-
next()
-
一定要读取到有效字符后才可以结束输入
-
对输入有效字符前遇到的空白,next()方法会自动将其去掉
-
只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
-
next()不能得到带有空格的字符串
-
-
nextLine():
-
以Enter为结束符,返回的是输入回车前的所有字符
-
可以获得空白
-
package scanner;
import java.util.Scanner;
public class Demo2 {
public static void main(String[] args) {
Scanner scanner =new Scanner(System.in);
int i = 0;
float f = 0.0f;
System.out.println("请输入整数:");
//如果。。。那么
if (scanner.hasNextInt()) {
i = scanner.nextInt();
System.out.println("整数数据:" + i);
}else{
System.out.println("输入的不是整数数据!");
}
System.out.println("请输入小数:");
//如果。。。那么
if (scanner.hasNextFloat()) {
f = scanner.nextFloat();
System.out.println("小数数据:" + f);
}else{
System.out.println("输入的不是小数数据!");
}
}
}
-
练习题
package scanner;
import java.util.Scanner;
public class Demo3 {
public static void main(String[] args) {
//输入多个数字求其总和与平均数,每输入一个数字用回车确认,通过输入非数字结束输入并输出执行结果
Scanner scanner = new Scanner(System.in);
//和
double sum = 0;
//计算输入多少数字
int m = 0;
System.out.println("请输入数据:");
//通过循环判断是否还有输入,并在里面对每一次进行求和统计
while (scanner.hasNextDouble()){
double x= scanner.nextDouble();
m = m+1;//m++:自增运算符
sum = sum +x;
System.out.println("你输入了第"+m+"个数据,然后当前结果sum=" +sum);
}
System.out.println(m + "个数的和为:" + sum);
System.out.println(m + "个数的平均值为:" + (sum/m));
scanner.close();
}
}
顺序结构
-
java的基本结构就是顺序结构,是若干个依次执行的处理步骤组成,是任何一个算法都离不开的一种基本算法结构
选择结构(重点)
-
if单选择结构
-
判断一个东西是否可行
if(布尔表达式){ //如果布尔表达式为ture执行的语句 }
-
-
if双选择结构
if-else结构 if(布尔表达式){ //如果表达式值为ture }else{ //如果表达式值为false }
-
if多选择结构
存在多级判断 if(1){ //1值为true执行 }else if(2){ //2值为ture执行 }else if(3){ //3值为ture执行 }else{ //以上都不是ture执行此代码 }
-
嵌套的if结构
-
可以在另一个if或者else if 语句中使用if 或者else if语句
-
if(布尔表达式1){ //如果为ture执行 if(布尔表达式2){ //如果为ture执行代码 } }
-
-
switch多选择结构
-
switch case语句判断一个变量与一系列值中某一个值是否相等,每个值为一个分支。
-
变量类型:
-
byte,short,int或者char
-
从Java SE 7开始
-
switch支持字符串String类型
-
同时case标签必须为字符串常量或者字面量
-
-
case穿透现象:每个case后面加上break语句,不然就全部输出了
-
package struct;
public class SwichDemo1 {
public static void main(String[] args) {
//JDK7新特性表达式结果可以是字符串!
//字符的本质还是数字
//反编译 java->class文件->反编译(IDEA)
//看源码:在工程结构当中看class文件位置考到java文件夹中查看
//每一个字符都有自己对应的hasCode,通过此来比较
char grade = 'C';
switch(grade){
case 'A':
System.out.println("优秀");
break;
case 'B':
System.out.println("良好");
break;
case 'C':
System.out.println("及格");
break;
case 'D':
System.out.println("良好");
break;
default:
System.out.println("未知");
}
}
}
循环结构
-
while 循环
-
while(布尔表达式){ //循环内容 }
-
只要布尔表达式为ture,循环就一直执行
-
大多数情况下让循环停止下来,需要一个让表达式失效的方式来结束循环
-
少部分情况需要循环一直执行,比如服务器的请求响应监听
-
要避免无限循环
-
-
do...while 循环
-
对于while语句来说不满足条件则不能进入循环,有时候需要即使不满足条件也要执行一次
-
do...while至少会执行一次
-
do{ //代码语句 }while(布尔表达式);
-
while与do...while的区别:
-
while先判断后执行,dowhile先执行后判断
-
dowhile保证循环体至少执行一次
-
-
-
for循环
-
使得循环结构变得更加简单
-
支持迭代的一种通用结构,最有效,最灵活的循环结构
-
for循环执行的次数是在执行前就确定的
-
语法格式
for(初始化;布尔表达式;更新){ //代码语句 }
-
package struct; public class ForDemo1 { public static void main(String[] args) { int a = 1; while(a<=100){//条件判断 System.out.println(a);//循环体 a+=2;//迭代 } System.out.println("while循环结束!"); //初始化//条件判断//迭代 for (int i=1;i<=100;i++){//快捷键:100.for System.out.println(i); } System.out.println("for循环结束!"); //死循环:for(; ; ){} } }
-
package struct; //99乘法表 public class ForDemo5 { public static void main(String[] args) { //1.先打印第一页 //2.把固定的1用一个循环包起来 //3.去掉重复项 //4.调整样式 for (int j = 1; j <=9; j++) { for (int i = 1; i <= j; i++) { System.out.print(j + "*" + i + "=" + (j* i) +"\t"); } System.out.println(); } } }
-
-
在Java5中引入一种主要用于数组的增强型for循环
package struct;
public class ForDemo6 {
public static void main(String[] args) {
int[] numbers = {10,20,30,40,50};//定义一个数组
for (int i = 0; i<5;i++){
System.out.println(numbers[i]);
}
System.out.println("===================");
//遍历数组的元素
for (int x:numbers){ //简化的增强型for循环
System.out.println(x);
}
}
}
break&continue
-
break在任何循环语句的主体部分,用于强行退出循环,不执行循环中剩余的语句(也可在switch语句中使用)
-
continue语句在循环语句中,用于终止某次循环,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
-
关于goto关键字
-
goto关键字:带标签的break和continue
-
“标签”是指后面跟一个冒号的标识符,例如:label:
-
用到标签的地方是在循环语句之前,由于break和continue只中断当前循环,若随同标签使用就会中断存在标签的地方。
-
练习
package struct;
//打印三角形
public class TestDemo1 {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
for (int j = 5; j >= i; j--) {
System.out.print(" ");
}
for (int j = 1; j <= i; j++) {
System.out.print("*");
}
for (int j = 1; j < i; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
方法
何谓方法
-
system.out.println():system是类,out是一个输出对象,println是方法
-
java方法是语句的集合,在一起执行一个功能
-
方法是解决一类问题的步骤的有序组合
-
方法包含于类或者对象中
-
方法在程序中被创建,在其他地方被引用
-
-
设计方法的原则:实现某个功能的语句块的集合,方法的原子性:一个方法只完成一个功能,利于后期的扩展。
方法的定义及调用
-
java方法类似于其他语言的函数,是一段用来完成特定功能的代码片段
-
修饰符:告诉编译器该如何调用该方法,定义该方法的访问类型
-
返回值类型:方法可能会返回值,无返回值时是关键字void
-
方法名:方法的实际名称
-
参数类型:当方法被调用的时候传递值给参数,这个值被称为实参或变量,参数列表是指方法的参数类型,顺序和参数的个数,参数可选,可以不包含任何参数。
-
形式参数:在方法被调用的时候用于接收外界输入的数据,用来定义作用的。
-
实参:调用方法时实际传给方法的数据
-
-
方法体:包含具体的语句,定义该方法的功能。
-
修饰符 返回值类型 方法名(参数类型 参数名){ ... 方法体 ... return 返回值; }
-
调用方法:对象名.方法名(实参列表)
-
Java根据方法是否返回值来选择
-
返回一个值时,方法调用通常被当作一个值
-
方法返回值是void,方法调用一定是一条语句
System.out.println("hello,liu");
-
package method;
public class Demo1 {
//main方法
public static void main(String[] args) {//void不用返回值,空
int sum = add(1,2);
System.out.println(sum);
int max = max(10,10);
System.out.println(max);
}
***********************************************
//创建加法:static是变成类
public static int add(int a,int b){
return a+b;
}
//创建比较法
public static int max(int c,int d){
int result = 0;
if (c==d){
System.out.println("c==d");
return 0;
}
if (c>d){
result = c;
}else {
result = d;
}
return result;
}
}
方法重载
-
重载是在一个类中,有相同的函数名称,但形参不同
-
规则:
-
方法名必须相同
-
参数列表必须不同(个数不同,类型不同或者参数排列顺序不同)
-
方法的返回类型可以相同也可以不同
-
仅仅返回类型不同不足以成为方法的重载
-
//创建比较法
public static int max(int c, int d) {
int result = 0;
if (c == d) {
System.out.println("c==d");
return 0;
}
if (c > d) {
result = c;
} else {
result = d;
}
return result;
}
//重载
public static int max(double c, double d) {
int result = 0;
if (c == d) {
System.out.println("c==d");
return 0;
}
if (c > d) {
result = (int)c;
} else {
result =(int)d;
}
return result;
}
命令行传参
-
希望运行一个程序时候再传递给它消息,要靠命令行参数给main()函数实现
package method;
public class Demo2 {
public static void main(String[] args) {
//args.length 数组长度,遍历每一个数组的参数
for (int i = 0; i < args.length; i++) {
System.out.println("args["+ i +"]:" +args[i]);//fori
//args[i]数组里的参数
}
}
}
可变参数
-
不定向参数
-
在方法声明中,在指定类型后加一个省略号(...)
-
一个方法只能指定一个可变参数,它必须是方法的最后一个参数,任何普通参数必须在它之前声明
package method;
//排序算法
public class Demo4 {
public static void main(String[] args) {
//调用可变参数的方法
printMax(28,3,5,6,45.6);
printMax(new double[]{1,2,3});
}
public static void printMax(double...numbers){//不确定参数长度
if (numbers.length == 0){
System.out.println("No argument passed");
return;
}
double result = numbers[0];
//排序
for (int i = 1; i < numbers.length; i++) {
if (numbers[i]>result){
result = numbers[i];
}
}
System.out.println("the max value is:"+result);
}
}
递归(面试笔试重点)
-
A方法调用A方法,自己调用自己
-
将一个大规模复杂的问题转换为一个与原问题相似的规模小的问题来解决,在于用有限的语句来定义对象的无限集合。
-
递归结构包括:
-
递归头:什么时候不调用自身方法,如果没有头,将陷入死循环
-
递归体:什么时候需要调用自身方法。
-
package method;
//递归:实现阶乘
public class Demo5 {
public static void main(String[] args) {
System.out.println(f(4));
}
public static int f(int n){
if (n==1){
return 1;
}else{
return n*f(n-1);
}
}
}
-
边界条件:边界
-
前阶段
-
返回阶段:n*(n-1)
数组
数组概述
-
定义:是相同类型数据的有序集合
-
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
-
每一个数据称为一个数组元素,每个数组元素可以通过一个下标来访问它(下标从0开始)
数组声明创建
-
首先必须声明数组变量,才能在程序中使用数组,语法:
dataType[] arrayRefVar;//首选的方法 类型 变量名
或
dataType arrayRefVar[];//效果相同,但不是首选
-
java语言使用new操作符来创建数组,语法:
dataType[] arrayRefVar = new dataType[arraySize];
int[] nums = new int[10];
-
数组的元素通过索引访问的,数组索引从0开始
-
获取数组长度;
array.length
-
内存分析
-
堆
-
存放new的对象和数组
-
可以被所有的线程共享,不会存放别的对象引用
-
-
栈
-
存放基本变量类型(包含这个基本类型的具体数值)
-
引用对象的变量(会存放这个引用在堆里面的具体位置)
-
-
方法区
-
可以被所有的线程共享
-
包含了所有的class和static变量
-
-
-
流程图
-
三种初始化
-
静态初始化
int[] = a = {1,2,3}; Man[].mans = {new Man(1,1),new Man(2,2)};
-
动态初始化
int[] a = new int[2]; a[0] = 1; a[1] = 2;
-
数组的默认初始化
-
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
-
-
package array;
public class Demo2 {
public static void main(String[] args) {
//静态初始化:创建 + 赋值
int[] a = {1,2,3,4,5,6,7};
//动态初始化:包含默认初始化:一经分配空间就是有值为0
int[] b = new int[10];
b[0]= 1;
System.out.println(b[2]);//没有初始化的都是0
}
}
-
数组的四个基本特点
-
长度确定,大小不可改变
-
元素必须相同类型
-
数组元素可以是任何数据类型
-
数组变量属引用类型,可以看成是对象,数组中的每个元素相当于该对象的成员变量,
数组本身就是对象,java中对象是在堆中的,数组对象本身是在堆中的
-
-
数组边界
-
合法区间:[0,length-1],越界就会报错
-
错误:ArrayIndexOutOfBoundException
-
数组使用
-
for-Each循环
public static void main(String[] args) { int[] arrays = {1,2,3,4,5}; //打印全部数组元素 for (int i = 0; i < arrays.length; i++) { System.out.println(arrays[i]); } System.out.println("=========="); //增强型的for循环 array.for for (int array : arrays) { System.out.println(array); } }
-
数组作方法入参
-
数组作返回值
package array;
public class Demo4 {
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};
printArray(arrays);
int[] reverse = reverse(arrays);
printArray(reverse);
}
//打印数组元素
public static void printArray(int[] arrays){
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i]+" ");
}
}
//反转数组
public static int[] reverse(int[] arrays){
int[] result = new int[arrays.length];//动态初始化法
for (int i = 0,j=result.length-1; i <arrays.length ; i++,j--) {
result[j]=arrays[i];
}
return result;
}
}
多维数组
-
可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
-
二维数组
int a[][] = new int[2][5];
-
解析:以上二维数组a可以看成一个两行五列的数组
-
多维数组的使用:
package array;
//多维数组:数组嵌套数组
public class Demo5 {
public static void main(String[] args) {
int[][] a = {{1,2},{2,3},{4,5}};
//System.out.println(a[1][1]);
// System.out.println(a[2][0]);
printArray(a[0]);
//3行两列的矩阵
/*1 2 从(0,0)位置开始
2 3
4 5
*/
}
//打印数组元素
public static void printArray(int[] arrays){
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i]+" ");
}
}
}
Arrays类
-
数组的工具类java.util.Arrays
-
API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作
-
查看JDK帮助文档
-
Arrays类中的方法都是static修饰的静态方法,直接使用类名进行调用
-
具有以下常用功能:
-
给数组赋值:通过fill方法
-
对数组排序:通过sort方法,按升序
-
比较数组:通过equals方法比较数组中元素值是否相等
-
查找数组元素:通过binarySearch方法对排序好的数组进行二分查找法操作
-
package array;
import java.util.Arrays;//输入Arrays.
//排序
public class Demo6 {
public static void main(String[] args) {
int[] a = {1,2,3,4,3424,54673,6,84};
//System.out.println(a);
//打印数组元素
//System.out.println(Arrays.toString(a));//系统自带工具类
//printArray(a);//自己写的打印
Arrays.sort(a);//排序;升序
System.out.println(Arrays.toString(a));
//数组里的元素全部被0填充
// Arrays.fill(a,0);
//System.out.println(Arrays.toString(a));
//数组填充,2-4之间的数字被0填充
Arrays.fill(a,2,4,0);
System.out.println(Arrays.toString(a));
}
//自己写打印工具类
public static void printArray(int[] a){
for (int i = 0; i < a.length; i++) {
if (i==0) {
System.out.print("[");
}
if (i==a.length-1) {
System.out.print(a[i] + "]");
}else {
System.out.print(a[i]+" ");
}
}
}
}
冒泡排序
-
代码两层循环,外层冒泡轮数,里层依次比较(两两之间互相比较)
-
嵌套循环,时间复杂度O(n2)
package array;
//冒泡排序
//1.比较数组中两个相邻的元素,如果第一个数比第二个数大,交换位置
//2.每一次比较产生一个最大或者最小的数字
//3.下一轮少一次排序
//4.依次循环,直到结束
import java.util.Arrays;
public class Demo7 {
public static void main(String[] args) {
int[] a = {1,25,7,5,8,2,3,45};
int[] sort = sort(a);
System.out.println(Arrays.toString(sort));//由大到小排
}
public static int[] sort(int[] array){//用int[]返回接收
int temp = 0;//临时变量
//外层循环,判断要走多少次;
for (int i = 0; i < array.length; i++) {
boolean flag = false; //通过falg标识位减少没有意义的比较
//内层循环,比较判断两个数,如果第一个数比第二个数大,交换位置
for (int j = 0; j < array.length-1-i ; j++) {
if (array[j+1]<array[j]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
flag = true;
}
}
if (flag==false){
break;
}
}
return array;
}
}
稀疏数组
-
分析:二维数组的很多值是默认的0,记录很多无意义的数据
-
解决:稀疏数组
-
当一个数组中大部分元素为0或者为同一值的数组时可以用稀疏数组来保存该数组
-
记录数组一共几行几列,有多少个不同值
-
把具有不同值的元素和行、列及值记录在一个小规模的数组中,从而缩小程序的规模
-
数组下标 | 行 | 列 | 值 |
---|---|---|---|
[0] | 4 | 3 | 4 |
[1] | 0 | 2 | 14 |
[2] | 0 | 3 | 5 |
[3] | 2 | 2 | 6 |
[4] | 3 | 2 | 7 |
package array;
//稀疏数组
public class Demo8 {
public static void main(String[] args) {
//1.创建一个二维数组11*11 0:没有棋子 1:黑棋 2:白棋
int[][] array1 = new int[11][11];
array1[1][2] = 5;
array1[2][3] = 9;
//输出原始的数组
System.out.println("输出原始数组");
//遍历两个数组
for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
System.out.println("===============");
//转换为稀疏数组保存
//获取有效值的个数
int sum = 0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (array1[i][j]!=0){
sum++;
}
}
}
System.out.println("有效值的个数:"+sum);
System.out.println("=====================");
//创建一个稀疏数组的数组
int[][] array2 = new int[sum+1][3];
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;//有效值的个数
//遍历二维数组,将非0的值存放稀疏数组中
int count = 0;//计数
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j]!=0){
count++;
array2[count][0] = i;//第count行第一个位置存横坐标
array2[count][1] = j;//第count行第2个位置存纵坐标
array2[count][2] = array1[i][j];//存它的值
}
}
}
//输出稀疏数组
System.out.println("稀疏数组");
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i][0]+"\t"+array2[i][1]+"\t"+array2[i][2]+"\t");
}
System.out.println("还原");
//1.读取稀疏数组
int[][] array3 = new int[array2[0][0]][array2[0][1]];//行数和列数
//2.给其中的元素还原它的值
for (int i = 1; i < array2.length; i++) {
array3[array2[i][0]][array2[i][1]] = array2[i][2];//横纵坐标赋值
}
System.out.println("====================");
//3.打印
for (int[] ints : array3) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
}
}