Java高级
方法的递归调用
简单的说: **递归就是方法自己调用自己,**每次调用时传入不同的变量.递归有助于编程者解决复杂问题,同时可以让代码变得简洁。
//求1-n的和的递归方法
public int sumone2n(int n){
int sum = n;
if(n == 1){
return 1;//等于1就不再调用,加完n=1就结束了
}else {
return n + sumone2n(n - 1);
}
}
//求n的阶乘
public int factorial(int n){
if (n == 1 ){
return 1;
}else {
return n*factorial(n - 1);
}
}
//斐波那契数列递归
public long fibonacci(int n){
if(n == 1 || n == 2){
return 1;
}else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
- 递归阶乘的分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gq02Xhlt-1660528654074)(C:\Users\13749\AppData\Roaming\Typora\typora-user-images\image-20220814140112009.png)]
- 递归重要规则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F3QVLutV-1660528654075)(C:\Users\13749\AppData\Roaming\Typora\typora-user-images\image-20220814140423333.png)]
异常
程序没有按照设计的正常的逻辑执行,出现了不可预知的情况,就叫异常。
一旦程序出现异常,就会终止执行。
学习异常的目的:
- 当我们的程序处理不了的情况,抛出(产生)一个异常,终止程序
- 当发生了异常的时候,给出提示,让程序能够继续执行
当我们调用的方法抛出了非Runtime的异常,就会报编译错误
要求代码添加 try catch 语句来处理异常,catch 语句可以有多个,也可以只有一个(异常类型要大于等于抛出最大的异常)
finally语句块的代码一定会执行(不管有没有异常)
只要有非运行时异常时,try/catch 必不可少,finally 可要可不要
try {
createException.getName();
createException.getSex(3);
/*} catch (IOException e) {
e.printStackTrace();*/
}catch (Exception e){
e.printStackTrace();
}finally {
//finally的代码一定会执行(不管有没有异常)
System.out.println("finally语句");
}
CreateException createException = new CreateException();
try {// try/catch 捕获异常
createException.getSex(3);
} catch (Exception e) {
e.printStackTrace();
System.out.println("异常出现的原因=" + e.getMessage());
}
System.out.println("cl");
集合
一些数据结构的统称集合,包含List、Set、Map
List
List就是列表,用来存储一组数据的数据结构
List是可变长的数据结构,可以知道List里面存有多少个数据
List里面可以保存不同类型的数据
List是有序的列表,数据可以重复
ArrayList
ArrayList是采用数组方式实现的
读和遍历速度比较快,插入和删除数据比较慢
LinkedList
采取双向链表实现的,插入和删除速度快, 查询和遍历速度慢
- 链表里面的数据是保存的地址
- 每个节点除了自身的数据的地址外,还保存了上一个和下一个节点的地址
Set
无序集合,元素不重复, 允许存null(存一个)
没有索引(序号),不能通过下标访问,只能遍历
给出一个数组,把数组中的重复元素去掉,返回新数组
{1,30,25,40,18,30,22,40}
HashSet<Integer> set = new HashSet<>();//Integer整数
int[] arrInt = {1,30,25,40,18,30,22,40};
for (int i = 0; i < arrInt.length; i++) {
set.add(arrInt[i]);
}
//定义新数组,长度与原数组相同
int[] str1 = new int[set.size()];
int i = 0;//数组下标
for (int a : set){//遍历set
str1[i] = a;//放元素
i++;
}
System.out.println(Arrays.toString(str1));
哈希表 hash table
哈希表,散列表,是一种高效数据结构
要保存的数据称为值,根据hash算法给每个值算出一个hash code
保存数据用hash code跟值一一对应。
hash toble保存数据的原理
根据hash code从表里查找是否存在:
- 不存在就当成新的值保存
- 存在,判断equals是否相等:falsh,直接添加;true,说明两个值是一样的,不添加
Collections集合工具类
- Collection跟Collections的区别
Collection是一个接口,它是List 和Set的父接口
Collections是一个处理集合类型数据的工具类
Map
-
保存键值对数据(key - value)
-
key不能重复, value可以重复
-
key和value都可以为null
IO 文件读写
Input输入, Output输出
信息需要永久保存(持久化),一般用文件的形式把信息保存到磁盘。
程序运行需要一些基本配置信息,这种配置信息也是保存在磁盘的文件中。
程序从磁盘上读取文件,就称为Input; 把文件写到磁盘,称为Output ( 参考位置是内存)
多线程
进程和线程
进程是指运行中的程序,比如使用QQ,就启动了一个进程,操作系统就会为该进程分配内存空间。当使用迅雷,又启动了一个进程,操作系统将为迅雷分配新的内存空间。每个进程独享一段内存空间,进程之间互不干扰。
线程由进程创建,是进程的一个实体,一个进程可以拥有多个线程,多个线程之间共享同一进程资源
并发
并发是指在某个时间段内,多任务交替的执行任务。执行同一个方法或访问同一个属性。
并发可能导致数据不一致(混乱)。
**解决并发:**把并发代码(或方法)添加一个同步关键字:synchronized
同步和异步
同步就是当A请求一个资源的时候,这个资源正在被B使用,那么A就必须要等待,等到B使用完了A才能请求到。
异步就是当A请求一个资源的时候,这个资源正在被B使用,A不需要等也可以请求到
同步是安全的保险的,异步是不安全的,容易导致死锁,一个线程死掉就会导致整个进程崩溃。
实现线程方式
1继承Thread类,重写run( )方法
2、实现Runnable接口,实现run()方法
3.实现Callable接口,实现call方法创建FutureTask对象,构造方法是实现了Callable接口对象创建Thread对象, 构造方法的参数是FutureTask对象
死锁
-
互斥条件:线程使用的资源必须至少有一个是不能共享的。即在一段时间内,一个资源只能被一个进程占用,直到被该进程释放。
-
请求与保持条件:指的是进程至少有一个资源,但又提出了新的资源请求,而该资源已被其它线程占有,此时请求进程阻塞,但又对自己获得的其它资源保持不释放。
-
不可抢占条件:指的是进程已获得资源,在未使用完之前,不能被抢占,只能在使用完时由自己释放。
-
循环等待条件:第一个线程等待其他的线程释放资源。后者又在等待第一个线程释放资源。
怎样避免死锁:
- 以相同的顺序去所锁定资源
- 另外建立一个锁的对象,只锁一个对象,不要锁多个对象
生命周期
-
New 新生状态
新生状态,当线程被实例化后new Thread(),就进入新生状态。
-
Runnable 就绪状态
就绪状态,当线程对象执行了start()后进入就绪状态。
就绪状态的线程可以执行,但不会执行,等待线程调度触发它执行
-
Running 运行状态
运行状态,当线程被激活执行,这时候线程就是运行状态,执行run()方法
不一定在一个执行周期内能执行完成run()方法,如果cpu时间片消耗完毕或者线程的yield()方法被调用,线程会退回就绪状态,等待下一次运行
-
Blocked 阻塞状态
阻塞状态,暂停运行, 正在运行的线程执行了sleep()方法或wait()方法,就进入到阻塞状态。
因sleep阻塞的线程,sleep时间到了后,重新回到就绪状态
因wait()方法阻塞的线程,等待notify()或notifyAll()被执行,才重新回到就绪状态
-
Terminated 终止状态
终止状态,run()正常执行完毕,就进入到终止状态,线程生命周期就结束
学习代码
1.打印2~100的所有质数
public static void main(String[] args) {
for (int i = 2; i <=100; i++) {
int a = 0;
for (int j = 2; j <i ; j++) {
if (i%j==0){
a++;
}
}
if (a==0){
System.out.println(i);
}
}
}
2.给出一个数组{5,7,20, 18, 6}, 找出数组中最大的元素
假设最大的数为 int max = arr[0]
package come.hqyj;
public class GetArrMax {
public static void main(String[] args) {
int[] arr = {5, 7, 20, 18, 6};
int getmax = arr[0];
for (int i = 0; i < arr.length; i++) {
getmax = getmax < arr[i] ? arr[i] : getmax;
}
System.out.println(getmax);
}
}
3.双色球号码生成
6个红球,红球范围1~32 , 随机生成,不能有重复
1个蓝球,蓝球范围1~7
package com.hqyj.homework;
/**
* 扑克牌的类
*/
public class Card {
//花色。黑桃,红桃,梅花,方块
private String type;
//点数。2~10,A,K,Q,J
private String num;
public Card() {
}
public Card(String type, String num) {
this.type = type;
this.num = num;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
@Override
public String toString() {
return "Card{" +
"type='" + type + '\'' +
", num='" + num + '\'' +
'}';
}
}
package com.hqyj.homework;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CardGame {
public static void main(String[] args) {
//生成一副牌
List<Card> cardList = new ArrayList<>();
//生成一副扑克牌
initCard(cardList);
//洗牌
Collections.shuffle(cardList);
//发牌
Player[] players = new Player[4]; //玩家数组
for (int i = 0; i < players.length; i++) {
players[i] = new Player("玩家"+ i);
}
for (int i = 0; i < cardList.size(); i++) {
Card card = cardList.get(i);//按顺序取出一张牌
//通过循环变量i模4,得到玩家的序号
int playerIndex = i % players.length;
// 给玩家发一张牌
players[playerIndex].getCards().add(card);
}
//打印玩家的牌
for (Player player : players
) {
System.out.println(player.getName()); //打印玩家姓名
List<Card> cards = player.getCards(); //返回玩家手上的牌
//遍历并打印玩家的牌
for (Card card : cards
) {
System.out.println(card);
}
}
}
private static void initCard(List<Card> cardList) {
String[] types = {"黑桃", "红桃", "梅花", "方块"};
String[] nums = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
//外层循环,花色
for (int i = 0; i < types.length; i++) {
//内层循环,每种花色的点数
for (int j = 0; j < nums.length; j++) {
String type = types[i]; //花色
String num = nums[j];//点数
Card card = new Card(type, num); //用不同的花色和点数创建一张牌
cardList.add(card); //把牌添加到List
}
}
}
}
package com.hqyj.homework;
import java.util.ArrayList;
import java.util.List;
/**
* 游戏玩家
*/
public class Player {
//玩家名字
private String name;
//玩家手上的牌
private List<Card> cards = new ArrayList<>(); //先初始化, 否则getCards()方法返回的是null
public Player() {
}
public Player(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Card> getCards() {
return cards;
}
public void setCards(List<Card> cards) {
this.cards = cards;
}
}