引用一位师兄的思维导图,源地址,本篇内容7,9,10
程序流程控制 知识要点:
判断结构 选择结构 循环结构
if和switch for和while的异同continue,break,return
无限循环最简单形式及其应用
编程思想:累加思想 计数器思想
函数和数组 知识要点:
函数的定义 特点 应用 重载
数组常见操作 多维数组
判断结构 三种格式
if //if else //if elseif else
if语句特点:
a,每一种格式都是单条语句。
b,第二种格式与三元运算符的区别:三元运算符运算完要有值出现。好处是:可以写在其他表达式中。
c,条件表达式无论写成什么样子,只看最终的结构是否是true 或者 false;
注://if else不一定有结果,三元运算符 :<表达式1>?<表达式2>:<表达式3>一定有一个结果
return a==b
选择结构
switch语句
格式:
switch(表达式)
{
case取值1:
执行语句;
break;
case取值2:
执行语句;
break;
…...
default:
执行语句;
break;
}
switch语句特点:
a,switch语句选择的类型只有四种:byte,short,int , char。
b,case之间与default没有顺序。先执行第一个case,没有匹配的case执行default。
c,结束switch语句的两种情况:遇到break,执行到switch语句结束。
d,如果匹配的case或者default没有对应的break,那么程序会继续向下执行,运行可以执行的语句,直到遇到break或者switch结尾结束。
循环结构
while语句格式:
while(条件表达式)
{
执行语句;
}
dowhile语句格式:
do
{
执行语句;
}while(条件表达式);
for(初始化表达式;循环条件表达式;循环后的操作表达式)
{
执行语句;
}
注:
a,for里面的连个表达式运行的顺序,初始化表达式只读一次,判断循环条件,为真就执行循环体,然后再执行循环后的操作表达式,接着继续判断循环条件,重复找个过程,直到条件不满足为止。
b,while与for可以互换,区别在于for为了循环而定义的变量在for循环结束就是在内存中释放。而while循环使用的变量在循环结束后还可以继续使用。
c,最简单无限循环格式:while(true) , for(;;),无限循环存在的原因是并不知道循环多少次,而是根据某些条件,来控制循环。
break(跳出), continue(继续)
break语句:应用范围:选择结构和循环结构。
continue语句:应用于循环结构。
注:a,这两个语句离开应用范围,存在是没有意义的。
b,这个两个语句单独存在下面都不可以有语句,因为执行不到。
c,continue语句是结束本次循环继续下次循环。
d,标号的出现,可以让这两个语句作用于指定的范围。
if和switch的应用
if的特点:
1,对具体的值进行判断。 例如星期123
2,对区间判断。
3,对运算结果是boolean类型的表达式进行判断。
switch 不常用,功能性较差,书写繁琐
1,对具体的值进行判断。
2,值的个数通常是固定的
对比总结: 对于几个固定的值判断,建议使用switch语句,因为switch语句
会将具体的答案都加载进内存,效率相对较高,其它情况用if语句比较好
for和while的特点;
1,for和while可以互换。
2;格式上不同,使用上有一些区别
while 循环结束后不会释放内存,变量x的值仍驻留在内存中
for 循环结束,变量在内存中释放 性能优化,内存问题
for和while的区别示例
intx=1;
while(x<5)
{
System.out.println("x="+x);
x++;
}
System.out.println("x===="+x);//x还在内存中,此时x=5,所以会输出x====5
for(inty=1;y<5;y++)
{
System.out.println("y="+y);
}
//System.out.println("y===="+y);// y的值已经被释放,所以此处会提示报错
无限循环最简单的形式
while(true){}
for(;;){}
循环结构的使用场景
对某些代码执行很多次时,使用循环结构
对一个条件进行一次判断时 if
当对一个条件进行多次判断时,使用while语句
注意事项
使用循环时,要明确哪些语句参与循环,那些不需要
循环通常情况下需要定义条件,控制次数
编程思想
累加算法思想
例如:1~100数字的和
用while循环实现
intx=1; //记录参与加法的数据
intsum=0; //记录每一次的和
while(x<=100)
{
sum+=x;
x++;
}
用for循环实现
int sum=0;
for(intx=1;x<=100;x++)
{
sum=sum+x;
}
System.out.println("sum="+sum);
计数器思想
例如: 统计1~100之间6的倍数出现次数
用while循环实现
intx=1;
int count=0;
while(x<=100)
{
if(x%6==0)
count++;
x++;
}
用for循环实现
int count=0;
for(intx=1;x<=100;x++)
{
if (x%3==0)
count++;
}
System.out.println("count="+count);
break作用的范围:要么是switch语句,要么是循环语句。
break跳出所在的当前循环。
用法示例:
for(int x=0; x<3; x++)
{
if(x==1)
break;//记住:当break语句单独存在时,下面不要定义其他语句,因为执行不到。
System.out.println("x="+x);//如果没有if判断,这句话就执行不到
}
xiaoqiang:for (int x=0; x<3 ;x++ )//标号
{
wangcai:for (int y=0; y<4 ; y++)
{
System.out.println("x="+x);
break xiaoqiang;//如果未命名break跳出所在的当前循环。命名则跳出指定循环
<span style="white-space:pre"> </span>}//如果出现了循环嵌套,break想要跳出指定的循环,可以通过标号来完成。
<span style="white-space:pre"> </span>}
continue:继续。
作用的范围:循环结构。
continue:结束本次循环,继续下次循环。
用法示例:
for (int x=0; x<11 ;x++ )
{
if(x%2==0)
continue;
System.out.println("x="+x);//如果continue单独存在时,下面不要有任何语句,因为执行不到。
}
*/
xiaoqiang:for (int x=0; x<3 ;x++ )
{
wangcai:for (int y=0; y<4 ; y++)
{
System.out.println("x="+x);
continue xiaoqiang;//结束本次内循环,继续外循环
}
}
函数
函数的定义
l函数的格式:
•修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,)
{
执行语句;
return 返回值;
}
函数的特点
定义函数可以将功能代码进行封装
函数的应用
int getSum(int x,int y)
{
return x+y;
}
函数的重载(重点)
同一个类 同名 参数个数或类型不同
重载的概念
在同一个类中,允许存在一个以上的同名函数,只要它们的参数个数或者参数类型不同即可。
重载的特点:
与返回值类型无关,只看参数列表。
重载的好处:
方便于阅读,优化了程序设计。
重载示例:
//返回两个整数的和
int add(int x,int y){return x+y;}
//返回三个整数的和
int add(int x,int y,int z){return x+y+z;}
//返回两个小数的和
double add(double x,double y){return x+y;}
栈内存的特点:先进后出
数组
数组的定义格式:
格式1: //需要一个容器,但不明确容器中的具体数据
元素类型[] 数组名 = new 元素类型[元素个数或数组长度];
示例:int[] arr = new int[5];
格式2: // 存储已知的具体数据
元素类型[] 数组名 = new 元素类型[]{元素,元素,……};
int[] arr = new int[]{3,5,1,7};
int[] arr = {3,5,1,7};
格式1: //需要一个容器,但不明确容器中的具体数据
元素类型[] 数组名 = new 元素类型[元素个数或数组长度];
示例:int[] arr = new int[5];
格式2: // 存储已知的具体数据
元素类型[] 数组名 = new 元素类型[]{元素,元素,……};
int[] arr = new int[]{3,5,1,7};
int[] arr = {3,5,1,7};
多维数组(略)
数组的内存结构
Java程序在运行时,需要在内存中的分配空间。为了提高运算效率,有对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
栈内存
l 用于存储局部变量,当数据使用完,所占空间会自动释放。
堆内存
l 数组和对象,通过<strong>new</strong>建立的实例都存放在堆内存中。
l 每一个实体都有内存地址值
l 实体中的变量都有默认初始化值 0,0.0/0.0f,bolean false,char'\u0000'
l 实体不在被使用,会在不确定的时间内被垃圾回收器回收
方法区,本地方法区,寄存器
内存划分,局部代码块限定 局部变量 的生命周期 垃圾回收机制
内存图解
数组常见异常
数组脚标越界异常(ArrayIndexOutOfBoundsException)
int[] arr = new int[2];
System.out.println(arr[3]);
访问到了数组中的不存在的脚标时发生。
空指针异常(NullPointerException)
int[] arr = null;
System.out.println(arr[0]);
arr引用没有指向实体,却在操作实体中的元素时。
数组常见操作
数组的遍历获取数组最大值
数组排序<选择排序 冒泡排序, 获取索引排序
将数组换换成字符串
有序数组 折半查找(二分查找)
查表法的使用
小扩展:数组任意位置任意长度元素的copy
class ArrayDemo
{
public static void main(String[] args)
{
int[] arr={127,52,90,98,106,85};//大括号!
// int max=getMax_2(arr);
// System.out.println("max="+max);
// printArray(arr);
// selectSort(arr);
// printArray(arr);
// bubbleSort(arr);
selectSort_2(arr);
printArray(arr);
}
//遍历数组的功能
public static void printArray(int[] arr)
{
System.out.print("[");
for (int x=0;x<arr.length ;x++ )
{
if (x!=arr.length-1)
System.out.print(arr[x]+",");
else
System.out.println(arr[x]+"]");
}
}
public static void swap(int arr[],int a,int b)//元素换位
{
int temp=arr[a];
arr[a] =arr[b];
arr[b] =temp;
}
//冒泡排序 <span style="color:#ff0000;">!面试!</span>
public static void bubbleSort(int[] arr)
{
for(int x=0;x<arr.length-1;x++)
{
for (int y=0;y<arr.length-1-x ;y++ )
{
if (arr[y]>arr[y+1])
{
swap(arr,y+1,y);
/*
int temp=arr[y];
arr[y]=arr[y+1];
arr[y+1]=temp;
*/
}
}
}
}
//冒泡排序2 <span style="color:#ff0000;">!面试!</span>
public static void bubbleSort_2(int[] arr)
{
for(int x=arr.length-1;x>0;x--)
{
for (int y=0;y<x ;y++ )
{
if (arr[y]>arr[y+1])
{
swap(arr,y,y+1);
/*
int temp=arr[y];
arr[y]=arr[y+1];
arr[y+1]=temp;
*/
}
}
}
}
<p>// import java.util.*; Array.sort(arr);<span style="white-space:pre"> </span>//开发时用<span style="font-family: Arial, Helvetica, sans-serif;">排序函数<span style="white-space: pre;"> </span><span style="font-family: arial; font-size: 13px; line-height: 20px;">希尔排序</span><span style="font-family: arial; font-size: 13px; line-height: 20px;">(Shell Sort)</span></span></p>
//选择排序
public static void selectSort(int [] arr)
{
for (int x=0;x<arr.length-1 ;x++ )
{
for (int y=x+1; y<arr.length ;y++ )
{
if(arr[x]>arr[y])
{
swap(arr,x,y);
/*
int temp = arr[x];
arr[x] = arr[y];
arr[y] =temp;
*/
}
}
}
}
//选择排序2 使用角标,每次排序只交换一次,优化性能!元素多的时候性能差别较大
public static void selectSort_2(int[] arr)
{
for (int x=0;x<arr.length-1 ;x++ )
{
int num = arr[x];
int index= x;
for (int y=x+1;y<arr.length ; y++)
{
if(num>arr[y])
{
num=arr[y];
index=y;
}
}
if(index!=x)
swap(arr,x,index);
}
}
/*
获取数组组最大值
思路
1,需要进行比较,并定义变量记录住每次比较后较大的值
2,对数组中元素进行遍历取出,和变量中记录的元素进行比较
如果遍历到的元素大于变量记录的元素,就用变量记录住该大值
3,遍历结果,该遍历结果就是最大值
定义一个功能来实现
明确1,结果是数组元素 int
明确2,数组未知内容
*/
public static int getMax(int[] arr)
{
//定义变量记录较大的值
int maxElement=arr[0];//初始化不应为0,负数
for(int x=1;x<arr.length;x++)
{
if(arr[x]>maxElement)
maxElement=arr[x];//元素
}
return maxElement;
}
public static int getMax_2(int[] arr)
{
int maxIndex=0;
for(int x=1;x<arr.length;x++)
{
if(arr[x]>arr[maxIndex])
maxIndex =x;//角标
}
return arr[maxIndex];//返回角标对应的元素
}
}
一个数组操作工具集合
import java.util.Arrays;
public class ArrayTest
{
public static void main(String[] args)
{
int x=2;
int y=5;
int z=y-x;
int[] src =new int[]{1,3,2,3,5,7,9,5};
int[] dest=new int[y];
System.out.println(ArrayTool.getMax(src));
System.arraycopy(src,x,dest,0,y);
System.out.println(Arrays.toString(dest));
}
}
public class ArrayTool
{
private ArrayTool(){}
//求数组最大值
public static int getMax(int[] arr)
{
int maxIndex=0;
for (int x=1;x<arr.length ;x++ )
{
if(arr[x]>arr[maxIndex])
maxIndex=x;
}
return arr[maxIndex];
}
public static void swap(int[] arr, int a,int b)//位置交换
{
int Temp =arr[a];
arr[a]=arr[b];
arr[b]=Temp;
}
//选择排序
public static void slectSort(int[] arr)
{
for (int x=0;x<arr.length-1 ;x++ )
{
for(int y=x+1;y<arr.length;y++)
{
if (arr[x]>arr[y])
swap(arr,x,y);
}
}
}
//数组查找 获取索引
public static int getIndex(int[] arr,int key)
{
for (int x=0;x<arr.length ;x++ )
{
if (arr[x]==key)
return x;
}
return -1;
}
//将数组转换成字符串
public static String arrToString(int[] arr)
{
String str="";
for (int x=0;x<arr.length ;x++ )
{
str=str+arr[x]+",";
}
return str;
}
}
小扩展:数组任意位置任意长度元素的copy
方法一:创建一个新的数组,使用循环,从原数组起始位置遍历赋值给新数组(略)方法二:JAVA自带方法
System.arraycopy() 可以复制数组
从指定源数组中复制一个数组,复制从指定的位置开始到目标数组的指定位置结束
Arrays.copyOf() 可以创建数组副本
import java.util.Arrays;
public class ArrayTest
{
public static void main(String[] args)
{
int x=2;
int y=5;
int z=y-x;
int[] src =new int[]{1,3,2,3,5,7,9,5};
int[] dest=new int[y];
System.out.println(ArrayTool.getMax(src));//调用上文数组工具
System.arraycopy(src,x,dest,0,y);//从原数组src[]的 角标=x 位置开始复制y个元素到数组dest[]
System.out.println(Arrays.toString(dest));
}
}
面试题:二分查找的应用
/*
给定一个有序数组,如果往该数组中存储一个元素,并保证这个数组还是有序的
那么这个元素存储的角标如何如何获取?
{11,13,15,17,19,34,45,67,88,109};
*/
import java.util.*;
class ArrayDemo5
{
public static void main(String[] args)
{
// int[] arr ={14,10,4,75,6,56};
// int index = getIndex(arr,11);
int[] arr={1,4,5,7,11,15,25,46,89,123};
int index=halfSearch_2(arr,89);
System.out.println("index="+index);
int index1= Arrays.binarySearch(arr,46);//java特有方法,如果存在,插入的是具体的返回位置
//如果不存在,返回值为: -插入点-1
System.out.println("index1="+index1);
}
/*
数组常见功能:查找 都适用
*/
public static int getIndex(int[] arr, int key)
{
for (int x=0;x<arr.length ;x++ )
{
if(arr[x]==key)
return x;
}
return -1;//数据为int型必须有返回值
}
//二分查找 折半查找 !必须是有序数组
//三个变量 循环
public static int halfSearch(int[] arr,int key)
{
int max,min,mid;
min=0;
max=arr.length-1;
mid=(min+max)/2;
while(arr[mid]!=key)
{
mid=(max+min)/2;
if(key>arr[mid])
min=mid+1;
else if(key<arr[mid])
max=mid-1;
if(max<min)
return -1;
}
return mid;
}
//下面这种方法更直观
public static int halfSearch_2(int[] arr,int key)
{
int max,min,mid;
min=0;
max=arr.length-1;
while (min<=max)
{
mid=(min+max)>>1;//位移运算相当于"/2"
if(key>arr[mid])
min=mid+1;
else if(key<arr[mid])
max=mid-1;
else
return mid;
}
//return -1;
return min;//返回插入位置 !面试题!
}
}
查表法的应用
什么时候使用数组呢?
如果数据出现了对应关系,而且对应关系一方是有序的数字编号,并作为角标使用,这时就必须要想到数组的使用。
将这些数据存储到数组中,根据运算结果作为角标直接去查询数组中对应的元素即可
这种方式:称为!查表法! 编程思想无序数组同样适用
class ArrayTest
{
public static void main(String[] args)
{
toHex_2(68);
}
public static void toHex_2(int num)
{
if(num=0)
{
System.out.println("0");
return; //这个return存在的意义,一旦满足条件下面的程序就不再执行
}
<span style="white-space:pre"> </span>//对应一个关系表
char[] chs={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
/*
查表会查到比较多的数据,数据一多,就先存储起来,再进行操作;所以定义一个数组作为临时容器
pos=0; pos++
pos=arr.length ; --pos 角标反转,从大角标逆序输出
*/
//临时容器的使用!!!
char[] arr= new char[32];
int pos=arr.length; //pos=0改成 用指针操作数组中的元素
while (num!=0)
{
int temp=num&15;
arr[--pos]=chs[temp];<span style="white-space:pre"> </span>//pos++改成--pos
num=num>>>4;
}
System.out.println("pos="+pos);
for (int x=pos;x< arr.length;x++ )
{
System.out.print(arr[x]+",");
}
return;<span style="white-space:pre"> </span>//这个return可以省略
}
//查表法
public static void toHex_1(int num)
{ <span style="white-space:pre"> </span>//对应一个关系表,无序数组同样适用
char[] chs={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
for (int x=0;x<8 ;x++ )
{
int temp=num&15;
System.out.print( chs[temp] );
num=num>>>4;
}
}
//一般方法
public static void toHex(int num)
{
for (int x=0;x<8 ;x++ )
{
int temp=num&15;
if(temp>9)
System.out.print( (char)(temp-10+'A') );//print(char)强转
else
System.out.print(temp);
num=num>>>4;
}
}
}
查表法拓展,进制转换工具
class ArrayTest //进制转换
{
public static void main(String[] args)
{
toHex(60);
toBinary(60);
toOctal(60);
}
//十进制-->十六进制
public static void toHex(int num)
{
trans(num,15,4);
}
//十进制-->八进制
public static void toBinary(int num)
{
trans(num,7,3);
}
//十进制-->二进制
public static void toOctal(int num)
{
trans(num,1,1);
}
//转换方法封装
public static void trans(int num,int base, int offset)
{
if(num==0)
{
System.out.println("0");
return;
}
char[] chs={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char[] arr= new char[32];
int pos=arr.length;
while (num!=0)
{
int temp=num& base ; //将与运算定义为变量
arr[--pos]=chs[temp];
num=num>>> offset ; //将位运算定义为变量
}
System.out.println("pos="+pos);
for (int x=pos;x< arr.length;x++ )
{
System.out.print(arr[x]+",");
}
}
}
本章小结:
对于初学者而言,语法基础应该重视起来,不能盲目的贪功冒进,试想你写了几十行的小程序,一下子弹出十几个错误,光调试排错就要花掉比你写程序更多的时间,显然是得不偿失的,因为本人就亲身有过这样的经历~⊙﹏⊙b汗
尤其是对于JAVA这种强类型语言养成严谨规范的代码风格,能够在以后的学习中避免许多不必要的错误,提高学习效率和质量