这里是根据本项目所需要的java基础写的博客,后面如果技术涉及到其他内容也会再进行补充,不断完善。
1安装环境
1.1安装idea
1.2创建项目
2.基本概念
2.1JDK、JRE、JVM的关系
- JDK:Java Development Kit, java开发工具包
- JRE:Jave RunTime Environmnet, java运行环境
- JVM:Java Virtual Machine,Java虚拟机
- 三者关系:JDK包含JRE,JRE包含JVM
2.2JDK版本的选择
- JDK1.8用的最多
2.3Java代码的编译运行流程
- 使java源码编译成java字节码
- 使用JVM将java字节码转换为机器码
- JVM的作用:跨平台、内存管理、安全
2.4JSE、JEE、JME的区别
- JSE:Java Standard Edition,标准版
- JEE:Java Enterprise Edition,企业版
- JME:Java MIrco Edition,移动版
- Spring是JEE的轻量级代替版
- SpringBoot是Spring + 自动配置
3.Java语法
java所有的变量和函数都要定义在
class
中
3.1变量、 运算符、 输入输出
3.1.1 内置数据类型
public class Main {
public static void main(String[] args) {
byte a = 123;
short b = 12345;
int c = 123456788;
long d = 1234567111111L;
float e = 1.2f;
double f = 1.2, g = 1.2D;
boolean j = false;
char h = 'A';
}
}
3.1.2常量
常量使用
final
修饰
3.1.3类型转化
- 显示转换:
int x = (int)'A';
(将字符A强转为整型变量) - 隐式转换:
double x = 12, y = 4 * 3.3;
(从低精度到高精度进行变化:int * double => double)
3.1.4表达式
+ - * / %
- 自增、自减
public class Main {
public static void main(String[] args) {
int a = 1, b = 2, c = 3;
int d = (a + b) * c;//表达式
System.out.println(d);
}
}
控制台输出:
9
3.1.5输入
方式一:Scanner
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s1 = sc.next();//读入一个不能包含空格的字符串
System.out.println("next()方法读入:" + s1);
String s2 = sc.nextLine();//读入一行,可以包含字符串
System.out.println("nextLine()方法读入:" + s2);
/*
sc.nextInt(): 读入一个整数
sc.nextDouble():读入一个双精度浮点数
sc.nextFloat():读入一个单精度浮点数
*/
}
}
控制台输出:
hello java test-nextLine
next()方法读入:hello
nextLine()方法读入: java test-nextLine
方式二:InputStreamReader
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s1 = br.readLine();// 读入一行
int x = br.read();//read()可以用来读入一个字符的Ascll码
System.out.println("readLine()读入的字符串:" + s1);
System.out.println("read()读入的一个整数:" + x);
}
}
控制台输出:
hello world
1
readLine()读入的字符串:hello world
read()读入的一个整数:49
读入一个整数的方法
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 如何读入整数
int num = Integer.parseInt(br.readLine());
System.out.println("输出的整数为 " + num);
}
}
控制台输出:
123
输出的整数为 123
一行内多个整数的读入方法
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 如何一行读入多个整数
String[] line = br.readLine().split(" ");//读入一行整数,用空格隔开,存入字符串数组
int x = Integer.parseInt(line[0]);
int y = Integer.parseInt(line[1]);
System.out.printf("x = %d, y = %d", x, y);
}
}
控制台输出:
123 456
x = 123, y = 456
3.1.5输出
方式一:
System.out.println()
:可以输出多种类型,自带换行System.out.print()
:不带换行System.out.printf()
:格式化输出,不带换行
public class Main {
public static void main(String[] args) throws IOException {
System.out.println("hello world");//自带回车
System.out.println(10);
System.out.print("hello ");//去掉ln,不带回车
System.out.println("world");
System.out.printf("%.2f %05d", 11.2376, 2);//格式化输出
}
}
控制台输出:
hello world
10
hello world
11.24 00002
方式二:BufferedWriter
:一定要记得在最后刷新缓冲区
public class Main {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write("Hello world\n");
bw.flush();//刷新缓冲区
}
}
控制台输出:
Hello world
3.1.6练习
题目链接:1. A + B - Acwing题库
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
System.out.println(a + b);
}
}
题目链接:608. 差 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();
int d = sc.nextInt();
System.out.printf("DIFERENCA = %d", a * b - c * d);
}
}
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
double x1 = sc.nextDouble(), y1 = sc.nextDouble();
double x2 = sc.nextDouble(), y2 = sc.nextDouble();
//java中double - %f
System.out.printf("%.4f", Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)));
}
}
题目链接:653. 钞票
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int totalMoney = sc.nextInt();
int[] money = {100 ,50, 20, 10, 5, 2, 1};
System.out.println(totalMoney);
for(int x : money){
System.out.printf("%d nota(s) de R$ %d,00\n", totalMoney / x, x);
totalMoney %= x;
}
}
}
题目链接:654. 时间转换 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int totalTime = sc.nextInt();
int hour = totalTime / 3600;
totalTime %= 3600;
int minute = totalTime / 60;
totalTime %= 60;
int second = totalTime;
System.out.printf("%d:%d:%d",hour, minute, second);
}
}
3.2判断语句
3.2.1 if-else
语句
闰年判断
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
int year = sc.nextInt();
if(year % 100 == 0 || (year % 400 == 0 && year % 100 != 0)){
System.out.printf("%d是闰年", year);
}else{
System.out.printf("%d不是闰年", year);
}
}
}
控制台输出:
2024
2024不是闰年
3.2.2 switch
语句
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
int day = sc.nextInt();
String name;
switch (day){
case 1:
name = "Monday";
break;
case 2:
name = "Tuesday";
break;
case 3:
name = "Wednesday";
break;
case 4:
name = "Thursday";
break;
case 5:
name = "Friday";
break;
case 6:
name = "Saturday";
break;
case 7:
name = "Sunday";
break;
default:
name = "invalid";
break;
}
System.out.printf("%s", name);
}
}
控制台输出:
12
invalid
3.2.3练习
题目链接:665. 倍数 - Acwing题库
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
if(a % b == 0 || b % a == 0){
System.out.println("Sao Multiplos");
}else{
System.out.println("Nao sao Multiplos");
}
}
}
题目链接:660. 零食 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int y = sc.nextInt();
if(x == 1){
System.out.printf("Total: R$ %.2f", y * 4.00);
}else if(x == 2){
System.out.printf("Total: R$ %.2f", y * 4.50);
}else if(x == 3){
System.out.printf("Total: R$ %.2f", y * 5.00);
}else if(x == 4){
System.out.printf("Total: R$ %.2f", y * 2.00);
}else if(x == 5){
System.out.printf("Total: R$ %.2f", y * 1.50);
}
}
}
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
double x = sc.nextDouble();
String res = null;
if(x < 0 || x > 100){
res = "Fora de intervalo";
}else if(x >= 0 && x <= 25){
res = "Intervalo [0,25]";
}else if(x > 25 && x <= 50){
res = "Intervalo (25,50]";
}else if(x > 50 && x <= 75){
res = "Intervalo (50,75]";
}else if(x > 75 && x <= 100){
res = "Intervalo (75,100]";
}
System.out.println(res);
}
}
题目链接:667. 游戏时间 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
if(b > a){
System.out.printf("O JOGO DUROU %d HORA(S)", b - a);
}else{
System.out.printf("O JOGO DUROU %d HORA(S)",b + 24 - a);
}
}
}
题目链接:670. 动物 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String a = sc.next(), b = sc.next(), c = sc.next();
if(a.equals("vertebrado")){
if(b.equals("ave")){
if(c.equals("carnivoro")){
System.out.println("aguia");
}else{
System.out.println("pomba");
}
}else{
if(c.equals("onivoro")){
System.out.println("homem");
}else{
System.out.println("vaca");
}
}
}else{
if(b.equals("inseto")){
if(c.equals("hematofago")){
System.out.println("pulga");
}else{
System.out.println("lagarta");
}
}else{
if(c.equals("hematofago")){
System.out.println("sanguessuga");
}else{
System.out.println("minhoca");
}
}
}
}
}
3.3循环语句
3.3.1 while
循环
public class Main {
public static void main(String[] args) throws IOException {
int i = 0;
while(i < 5){
System.out.println(i);
i ++;
}
}
}
控制台输出:
0
1
2
3
4
3.3.2do while
循环
do-while
和whlie
的区别在于,do-while
至少执行一次
public class Main {
public static void main(String[] args) throws IOException {
int i = 0;
do {
System.out.println(i);
i ++ ;
}while (i < 5);
}
}
控制台输出:
0
1
2
3
4
3.3.3for
循环
public class Main {
public static void main(String[] args) throws IOException {
for(int i = 0; i < 5; i ++){
System.out.println(i);
}
}
}
控制台输出:
0
1
2
3
4
3.3.4练习
题目链接:708. 偶数 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
for(int i = 1; i <= 100; i ++){
if(i % 2 == 0){
System.out.println(i);
}
}
}
}
题目链接:712. 正数 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int res = 0;
for(int i = 0; i < 6; i ++){
double x = sc.nextDouble();
if(x > 0){
res ++;
}
}
System.out.printf("%d positive numbers", res);
}
}
题目链接:721. 递增序列 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
while(x != 0){
for(int i = 1; i <= x; i ++){
System.out.printf("%d ", i);
}
System.out.println();//换行
x = sc.nextInt();
}
}
}
题目链接:724. 约数 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for(int i = 1; i <= n; i ++){
if(n % i == 0){
System.out.printf("%d\n", i);
}
}
}
}
题目链接:727. 菱形 - Acwing题库
曼哈顿距离:计算两个点之间距离的度量方法,只能沿着横向或者纵向移动。两个点(x1, y1)(x2, y2)之间的曼哈顿距离为:|x1 - x2| + |y1 - y2|
可以发现所有到中心点曼哈顿距离小于等于
n
/
2
n/2
n/2的都是*
,否则都是空格
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int cx = n / 2, cy = n / 2;//中心点
for(int i = 0; i < n; i ++){
for(int j = 0; j < n; j ++){
if(Math.abs(i - cx) + Math.abs(j - cy) <= n / 2){
System.out.print("*");
}else{
System.out.print(" ");
}
}
System.out.println();
}
}
}
3.4数组
3.4.1 初始化
public class Main {
public static void main(String[] args) throws IOException {
int[] a = new int[5];//初始化长度为5的int数组,初始值为0
int n = 10;
float[] b = new float[n];//初始化长度为10的数组,初始化值为0.0f
char[] c = {'a', 'b', 'c'};//初始化为长度为3的字符数组
char[] d = c;//d与c地址相同,更改c中的元素,d中的元素也会被改变, 反过来也一样
d[1] = 'x';
System.out.println(c[1]);
}
}
控制台输出:
x
3.4.2数组元素的读取与写入
public class Main {
public static void main(String[] args) throws IOException {
int[] a = new int[5];//初始化长度为5的int数组,初始值为0
for(int i = 0; i < 5; i ++){
a[i] = i;
}
for(int i = 0; i < 5; i ++){
System.out.println(a[i] * a[i]);
}
}
}
控制台输出:
0
1
4
9
16
3.4.3多维数组
int[][] a = new int[2][3];//初始化一个2行3列的二维数组
a[1][2] = 3;
//二维数组的初始化
int[][] b = {
{1, 2, 3},
{4, 5, 6}
};
System.out.println(Arrays.deepToString(a));//将数组直接变成一个字符串来输出
System.out.println(Arrays.deepToString(b));
控制台输出:
[[0, 0, 0], [0, 0, 3]]
[[1, 2, 3], [4, 5, 6]]
3.4.4常用API
- 属性
length
:返回数组长度,注意不加小括号 Arrays.sort()
:数组排序Arrays.fill(int[] a,int val)
:填充数组Arrays.toString()
:将数组转化为字符串Arrays.deepToString()
:将多维数组转化为字符串- 数组长度不可变
public class Main {
public static void main(String[] args) throws IOException {
int[] a = {2, 1, 5, 3, 4};
int[][] b = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Arrays.fill(a, 100);
Arrays.sort(a);
System.out.println(Arrays.toString(a));
System.out.println(Arrays.deepToString(b));
}
}
控制台输出:
[100, 100, 100, 100, 100]
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
3.4.5练习
题目链接:737. 数组替换 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int[] a = new int[10];
for(int i = 0; i < 10; i ++){
a[i] = sc.nextInt();
if(a[i] <= 0){
a[i] = 1;
}
System.out.printf("X[%d] = %d\n", i, a[i]);
}
}
}
java中判断字符串是否相同,需要使用equals
方法
import java.util.*;
public class Main{
public static void main(String[] args){
double[][] m = new double[12][12];
Scanner sc = new Scanner(System.in);
int l = sc.nextInt();
String op = sc.next();//直接当做读入字符串
for(int i = 0; i < 12; i ++){
for(int j = 0;j < 12; j ++){
m[i][j] = sc.nextDouble();
}
}
double sum = 0;
for(int i = 0; i < 12; i ++){
sum += m[l][i];
}
if(op.equals("M")){
System.out.printf("%.1f", sum / 12);
}else if(op.equals("S")){
System.out.printf("%.1f" ,sum);
}
}
}
每个位置的数字,是其位置距离上下左右边界的距离的最小值。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
while(x != 0){
for(int i = 0; i < x; i ++){
for(int j = 0; j < x; j ++){
int a = Math.min(i, x - 1 - i);
int b = Math.min(j, x - 1 - j);
System.out.printf("%d ",Math.min(a, b) + 1);
}
System.out.println();
}
System.out.println();
x = sc.nextInt();
}
}
}
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
double[][] m = new double[12][12];
String ch = sc.next();
for(int i = 0; i < 12; i ++){
for(int j = 0; j < 12; j ++){
m[i][j] = sc.nextDouble();
}
}
double sum = 0, cnt = 0;
for(int i = 0; i < 12; i ++){
for(int j = 0; j <= 10 - i; j ++){
sum += m[i][j];
cnt ++;
}
}
if("S".equals(ch)){
System.out.printf("%.1f\n", sum);
}else if("M".equals(ch)){
System.out.printf("%.1f", sum / cnt);
}
}
}
题目链接:756. 蛇形矩阵 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), m = sc.nextInt();
int [][] res = new int[n][m];
int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
int x = 0, y = 0, d = 1;
for(int i = 1; i <= n * m; i ++){
res[x][y] = i;
int a = x + dx[d], b = y + dy[d];
if(a < 0 || a >= n || b < 0 || b >= m || res[a][b] > 0){
d = (d + 1) % 4;
//重新算新方向的坐标
a = x + dx[d];
b = y + dy[d];
}
x = a;
y = b;
}
for(int i = 0; i < n; i ++){
for(int j = 0; j < m; j ++){
System.out.printf("%d ", res[i][j]);
}
System.out.println();
}
}
}
3.5字符串
java中判断字符串是否相同使用equals()
进行判断
3.5.1String
类
初始化:
public class Main {
public static void main(String[] args) throws IOException {
String a = "Hello World";
String b = "My name is";
String x = b;
System.out.println(b.hashCode());//物理地址的哈希值
System.out.println(x.hashCode());//x 和 b的Hash值一样,所以两者是一个变量
String c = b + "hxw";//String可以通过 + 号拼接
String d = "My name is " + 18; // 默认将18转换为字符串
String Str = String.format("My age is %d", 18);
String money_str = "123.45";
double money = Double.parseDouble(money_str);//将String转换为Double
}
}
只读变量,不能修改
public class Main {
public static void main(String[] args) throws IOException {
String a = "Hello";
System.out.println(a.hashCode());
a += "World";
System.out.println(a.hashCode());//a的地址发生了变化
}
}
控制台输出:
69609650
439329280
访问String
中的字符
public class Main {
public static void main(String[] args) throws IOException {
String a = "Hello World";//字符串的length需要加()
for(int i = 0; i < a.length(); i ++){
System.out.print(a.charAt(i));
}
}
}
控制台输出:
Hello World
常用API:
length()
:返回长度split(String regex)
:分割字符串intdexOf(char c)
、indexOf(String str)
:查找,找不到返回-1equals()
:判断两个字符串是否相同compareTo()
:判断两个字符串的字典序大小,负数表示小于,0表示相等,正数表示大于startsWith()
:判断是否以某个前缀开头endWith()
:判断是否以某一个后缀结尾trim()
:去掉首位的空白字符toLowerCase()
:全部用小写字符toUpperCase()
:全部用大写字符replace(char oldChar, char newChar)
:替换字符replace(char oldRegex, char newRegex)
:替换字符串subString(int beginIndex, int endIndex)
:返回[beginIndex, endIndex)
中的子串
public class Main {
public static void main(String[] args) throws IOException {
String a = "Hello World";
String[] strs = a.split(" ");//用空格隔开
System.out.println(Arrays.toString(strs));
System.out.println(a.indexOf("Wo"));
String b = "aaa";
String c = "aaa";
if(c.equals(b)){
System.out.println("a == b");
}
System.out.println(b.compareTo(c));
System.out.println("使用startsWith的结果:" + b.startsWith("a"));
System.out.println("使用endsWith的结果:" + b.endsWith("b"));
String d = " abc ";
System.out.println("使用trime()的结果:" + d.trim());
System.out.println(c.toLowerCase());
System.out.println(c.toUpperCase());
//字符串是不可修改的每次都会创建一个新的串
System.out.println( c.replace('a', 'x'));
System.out.println(c.replace("aa", "x"));
String h = "012345";
System.out.println(h.substring(1,4));
}
}
控制台输出:
[Hello, World]
6
a == b
0
使用startsWith的结果:true
使用endsWith的结果:false
使用trime()的结果:abc
aaa
AAA
xxx
xa
123
3.5.2StringBuilder
、StringBuffer
String
不能被修改,如果打算修改字符串,可以使用StirngBuilder
和StringBuffer
StringBuffer
线程安全,速度较慢;StringBuilder
线程不安全(没有加锁),速度较快
public class Main {
public static void main(String[] args) throws IOException {
StringBuilder sb = new StringBuilder("Hello ");
sb.append("World");//拼接字符串
System.out.println(sb);
for(int i = 0; i < sb.length(); i ++){
sb.setCharAt(i, (char)(sb.charAt(i) + 1));//读取和写入字符
}
System.out.println(sb);
}
}
控制台输出:
Hello World
Ifmmp!Xpsme
3.5.3练习
题目链接:760. 字符串长度 - Acwing
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println(sc.nextLine().length());
}
}
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String str = sc.next();//子读入字符,空格忽略,这里不影响,因为只读入字符
int[] cnt = new int[26];//数组初始化为0
for(int i = 0; i < str.length(); i ++){
cnt[str.charAt(i) - 'a'] ++;
}
for(int i = 0; i < str.length(); i ++){
int t = str.charAt(i) - 'a';
if(cnt[t] == 1){
System.out.println(str.charAt(i));
return;
}
}
System.out.println("no");
}
}
题目链接:770. 单词替换 - Acwing题库
可以体现java
相较于c++
的优势,split()
分割字符串为字符数组
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] strs = sc.nextLine().split(" ");//用空格隔开
String a = sc.next(), b = sc.next();
for(String str : strs){
if(str.equals(a)){
System.out.printf("%s ", b);
}else{
System.out.printf("%s ", str);
}
}
}
}
题目链接:775. 倒排单词 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
String[] strs =str.split(" ");
for(int i = strs.length - 1; i >= 0; i --){
System.out.printf("%s ", strs[i]);
}
}
}
题目链接 : 779. 最长公共字符串后缀 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(true){
int n = sc.nextInt();
if(n == 0){
break;
}
String[] strs = new String[n];
for(int i = 0; i < n; i ++){
strs[i] = sc.next();
}
StringBuilder sb = new StringBuilder();
for(int i = 1; i <= strs[0].length(); i ++){
boolean flag = true;
char c = strs[0].charAt(strs[0].length() - i);
for(int j = 1; j < n; j ++){
if(i > strs[j].length() || strs[j].charAt(strs[j].length() - i) != c){
flag = false;
break;
}
}
if(flag){
sb.append(c);
}else{
break;
}
}
sb.reverse();
System.out.println(sb);
}
}
}
3.6函数
3.6.1函数的概念
java
的所有变量和函数都要定义在类中。
函数或者变量前加static
表示静态对象,类似于全局变量
静态对象属于class
,而不属于class
的具体实例,每个实例共用静态函数和静态变量
静态函数中只能调用静态函数和静态变量
class Point{
private int x;
private static int y;
public int f(){
return 0;
}
public static int g(){
return 0;
}
}
public class Main {
public static void main(String[] args) throws IOException {
Point a, b, c;//a, b, c每一个都有对应的x,f(),但是共用一个y,g()
}
}
class Argument{
public final static int x = 1;
public final static int y = 1;
}
public class Main {
public static void main(String[] args) {//静态方法内部只能调用静态方法
int[][] a = new int[3][4];
fill(a, 3);
System.out.println(Arrays.deepToString(a));
int[][] b = getArray2d(3, 4, 9);
System.out.println(Arrays.deepToString(b));
System.out.println(Argument.x);//静态变量绑定到类上
}
private static int max(int a, int b){
return Math.max(a, b);
}
//参数中传递数组的方法
private static void fill(int[][] a, int val){
for(int i = 0; i < a.length; i ++){
for(int j = 0; j < a[i].length; j ++){
a[i][j] = val;
}
}
}
//返回值为一个数组
private static int[][] getArray2d(int row, int col, int val){
int[][] res = new int[row][col];
for(int i = 0; i < row; i ++){
for(int j = 0;j < col; j ++){
res[i][j] = val;
}
}
return res;
}
}
控制台输出:
[[3, 3, 3, 3], [3, 3, 3, 3], [3, 3, 3, 3]]
[[9, 9, 9, 9], [9, 9, 9, 9], [9, 9, 9, 9]]
1
3.6.2练习
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int x = sc.nextInt(), y = sc.nextInt();
System.out.println(max(x, y));
}
public static int max(int a, int b){
if(a >= b){
return a;
}else{
return b;
}
}
}
题目链接:813. 打印矩阵
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int row = sc.nextInt(), col = sc.nextInt();
int[][] a = new int[row][col];
for(int i = 0; i < row; i ++){
for(int j = 0; j < col; j ++){
a[i][j] = sc.nextInt();
}
}
print2D(a, row, col);
}
public static void print2D(int a[][], int row, int col){
for(int i = 0; i < row; i ++){
for(int j = 0; j < col; j ++){
System.out.printf("%d ", a[i][j]);
}
System.out.println();
}
}
}
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int a = sc.nextInt(), b = sc.nextInt();
System.out.println(gcd(a, b));
}
public static int gcd(int a, int b){
int min = Math.min(a, b);
for(int i = min; i >= 1; i--){
if(a % i == 0 && b % i == 0){
return i;
}
}
return 0;
}
}
题目链接:818. 数组排序 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), l = sc.nextInt(), r = sc.nextInt();
int[] a = new int[n];
for(int i = 0; i < n; i ++){
a[i] = sc.nextInt();
}
sort(a, l, r);
for(int i = 0; i < n; i ++){
System.out.printf("%d ", a[i]);
}
}
public static void sort(int a[], int l, int r){
//冒泡排序
for(int i = r; i > l; i --){
for(int j = l; j < i; j ++){
if(a[j] > a[j + 1]){
//交换
int t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
}
}
}
题目链接:823. 排列 - Acwing题库
import java.util.*;
import java.io.*;
public class Main{
private static int[] path;
private static boolean[] st;
private static int n;
//适用于输出规模较大
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
//递归求全排列:画递归搜索树
n = sc.nextInt();
path = new int[n];
st = new boolean[n];
dfs(0);
bw.flush();
}
private static void dfs(int u) throws Exception{
if(u == n ){
for(int i = 0; i < n; i ++){
bw.write(path[i] + " ");
}
bw.write("\n");
}else{
for(int i = 0; i < n; i ++){
if(!st[i]){
st[i] = true;
path[u] = i + 1;
dfs(u + 1);
st[i] = false;//恢复现场
}
}
}
}
}
3.7类与接口
3.7.1类
3.7.1.1源文件申明规则
- 一个源文件只能有一个
public
类 - 一个源文件可以有多个非
public
类 - 源文件的名称应该和
public
类的类名保持一致 - 每一个源文件中,先写
package
语句,再写import
语句,最后定义类
3.7.1.2类的定义
public
:所有对象均可以访问private
:只有自己可以访问
class Point{
private int x;
private int y;
public Point(int x, int y){//构造函数
this.x = x;
this.y = y;
}
public Point(int x){
this.x = x;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public void setX(int x){
this.x = x;
}
public void setY(int y){
this.y = y;
}
public String toString(){
return String.format("(%d, %d)",x ,y);
}
}
public class Main {
public static void main(String[] args) {//静态方法内部只能调用静态方法
Point point = new Point(3, 4);
point.setX(5);
point.setY(10);
System.out.println(point.getX());// 访问x
System.out.println(point.toString());
}
}
控制台输出:
5
(5, 10)
3.7.1.3类的继承
每个类只能继承一个类
class Point{
private int x;
private int y;
public Point(int x, int y){//构造函数
this.x = x;
this.y = y;
}
public Point(int x){
this.x = x;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public void setX(int x){
this.x = x;
}
public void setY(int y){
this.y = y;
}
public String toString(){
return String.format("(%d, %d)",x ,y);
}
}
class ColorPoint extends Point {
private String color;
public ColorPoint(int x, int y, String color) {
super(x, y);
this.color = color;
}
public String getColor(){
return color;
}
public void setColor(){
this.color = color;
}
public String toString(){
return String.format("(%d, %d, %s)", super.getX(), super.getY(), color);//子类不能直接访问父类中的私有成员
}
}
public class Main {
public static void main(String[] args) {//静态方法内部只能调用静态方法
ColorPoint colorPoint = new ColorPoint(3, 4, "red");
colorPoint.setX(10);
System.out.println(colorPoint.getX());
}
}
控制台输出:
10
3.7.1.4类的多态
同一个类的同一个函数可能会有不同行为,以下,toString()
的使用体现了多态
一般创建一个包,每一个class单独作为一个文件,多个类放在一个包下,这里为了展示效果,都写在一起了。
class Point{
private int x;
private int y;
public Point(int x, int y){//构造函数
this.x = x;
this.y = y;
}
public Point(int x){
this.x = x;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public void setX(int x){
this.x = x;
}
public void setY(int y){
this.y = y;
}
public String toString(){
return String.format("(%d, %d)",x ,y);
}
}
class ColorPoint extends Point {
private String color;
public ColorPoint(int x, int y, String color) {
super(x, y);
this.color = color;
}
public String getColor(){
return color;
}
public void setColor(){
this.color = color;
}
public String toString(){
return String.format("(%d, %d, %s)", super.getX(), super.getY(), color);//子类不能直接访问父类中的私有成员
}
}
public class Main {
public static void main(String[] args) {//静态方法内部只能调用静态方法
Point a = new Point(3, 4);
System.out.println(a.toString());
a = new ColorPoint(4, 5, "green");
System.out.println(a.toString());
}
}
控制台输出:
(3, 4)
(4, 5, green)
3.7.2接口
接口主要用来定义类中所需要包含的函数
接口可以继承其他接口,一个类可以实现多个接口
规定了必须实现的函数,有利于多人协作完成项目。
3.7.2.1接口的定义
使用关键字:interface
interface Role {
public void greet();
public void move();
public int getSpeed();
}
3.7.2.2接口的继承
interface Role {
public void greet();
public void move();
public int getSpeed();
}
interface Role2 {
}
interface Hero extends Role, Role2{ // 接口可以继承多个接口
public void attack();
}
3.7.2.3接口的实现
interface Role {
public void greet();
public void move();
public int getSpeed();
}
interface Role2 {
}
interface Hero extends Role, Role2{ // 接口可以继承多个接口
public void attack();
}
class Zeus implements Hero{// 一个类想要实现一个接口,就必须要实现其中的所有方法
private final String name = "Zeus";
@Override
public void attack() {
System.out.println(name + ": Attack!");
}
@Override
public void greet() {
System.out.println(name + ": Hi");
}
@Override
public void move() {
System.out.println(name + ": Move");
}
@Override
public int getSpeed() {
return 10;
}
}
public class Main {
public static void main(String[] args) {
Zeus zeus = new Zeus();
zeus.greet();
zeus.attack();
}
}
控制台输出:
Zeus: Hi
Zeus: Attack!
再来一个案例,体会一下多态带来的便利
interface Role {
public void greet();
public void move();
public int getSpeed();
}
interface Role2 {
}
interface Hero extends Role, Role2{ // 接口可以继承多个接口
public void attack();
}
class Athena implements Hero{
private final String name = "Athena";
@Override
public void attack() {
System.out.println(name + ": Attack!");
}
@Override
public void greet() {
System.out.println(name + ": Hi");
}
@Override
public void move() {
System.out.println(name + ": Move");
}
@Override
public int getSpeed() {
return 10;
}
}
class Zeus implements Hero{// 一个类想要实现一个接口,就必须要实现其中的所有方法
private final String name = "Zeus";
@Override
public void attack() {
System.out.println(name + ": Attack!");
}
@Override
public void greet() {
System.out.println(name + ": Hi");
}
@Override
public void move() {
System.out.println(name + ": Move");
}
@Override
public int getSpeed() {
return 10;
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请选择英雄:");
String name = sc.next();
Hero hero;
//多态的应用
if(name.equals("Zeus")){
hero = new Zeus();
}else{
hero = new Athena();
}
hero.greet();
}
}
控制台输出:
请选择英雄:
Zeus
Zeus: Hi
3.7.3泛型
类似于c++
的template
,java
的类和接口也可以定义泛型,就是同一套函数可以作用于不同的对象类型。
泛型只能使用对象类型,不能使用基本变量类型,例如如果是整数,不能用int
,而要用Integer
public class Main {
public static void main(String[] args) {
Stack<Integer> stk = new Stack<>();
}
}
3.7.4练习
解题思路:将待删结点的后一个结点赋值到该结点,然后删除后一个结点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public void deleteNode(ListNode node) {
ListNode p = node.next;
node.val = p.val;
node.next = p.next;
}
}
题目链接:35. 反转链表 - Acwing题库
解题思路:cur指向当前结点,pre指向当前结点的前一个结点,每一个更新的步骤,将cur指向的结点的next指向pre,然后pre更新到cur的位置,cur更新到原链表的下一个结点。
迭代写法
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode cur = head;
while(cur != null){
ListNode next = cur.next;//先把cur.next存起来
cur.next = prev;
prev = cur;
cur = next;
}
return prev;
}
}
递归写法
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode tail = reverseList(head.next);
head.next.next = head;
head.next = null;
return tail;
}
}
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public int[] printListReversingly(ListNode head) {
Stack<Integer> stk = new Stack<>();
for(ListNode p = head; p != null; p = p.next){
stk.push(p.val);
}
int[] res = new int[stk.size()];
int k = 0;
while(!stk.empty()){
res[k ++] = stk.pop();
}
return res;
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteDuplication(ListNode head) {
//双指针
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode p = dummy;
while(p.next != null){
ListNode q = p.next;
while(q != null && q.val == p.next.val){
q = q.next;
}
if(p.next.next != q){
p.next = q;
}else{
p = p.next;
}
}
return dummy.next;
}
}
题目链接:862. 三元组排序
import java.util.*;
class Data implements Comparable<Data>{
int x;
double y;
String z;
public Data(int x, double y, String z){
this.x = x;
this.y = y;
this.z = z;
}
//实现接口的函数
public int compareTo(Data t){
return x - t.x;//小于 返回负数,等于返回0, 大于返回正数
}
}
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Data[] datas = new Data[n];
for(int i = 0; i < n; i ++){
datas[i] = new Data(sc.nextInt(), sc.nextDouble(), sc.next());
}
Arrays.sort(datas);
for(Data data : datas){
System.out.printf("%d %.2f %s\n", data.x, data.y, data.z);
}
}
}
3.8常用容器
3.8.1List
接口:java.util.List<>
实现:
java.util.ArrayList<>
:变长数组java.util.LinkedList<>
:双链表
函数:
add()
:在末尾添加一个元素clear()
:清空size()
:返回长度isEmpty()
:是否为空get(i)
:获取第i个元素set(i, val)
:将第i个元素设置为val
public class Main {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
System.out.println(list);
System.out.println("list的长度:" + list.size());
System.out.println("list是不是空的:" + list.isEmpty());
System.out.println("获取第一个元素:" + list.get(0));
list.set(0, 100);
System.out.println(list);
list.clear();
System.out.println(list);
}
}
控制台输出:
[1, 2]
list的长度:2
list是不是空的:false
获取第一个元素:1
[100, 2]
[]
3.8.2栈
类:java.util.Stack<>
函数:
push()
:压入元素pop()
:弹出栈顶元素(最后一个元素)peek()
:返回栈顶元素(第一个元素)empty()
:栈是否为空clear()
:清空
public class Main {
public static void main(String[] args) {
Stack<Integer> stk = new Stack<>();
stk.push(1);
stk.push(2);
stk.push(10);
stk.push(9);
System.out.println(stk);
stk.pop();
System.out.println(stk);
System.out.println("栈顶元素:" + stk.peek());
System.out.println("栈是否为空:" + stk.empty());
stk.clear();
System.out.println(stk);
}
}
控制台输出:
[1, 2, 10, 9]
[1, 2, 10]
栈顶元素:10
栈是否为空:false
[]
3.8.3队列
接口:java.util.Queue<>
实现:
java.util.LinkedList<>
:双链表java.util.PriorityQueue<>
:优先队列- 默认是小根堆,大根堆的写法
new PriorityQueue<>(Collections.reverseOrder())
- 默认是小根堆,大根堆的写法
函数:
add()
:在队尾添加元素remove
:删除队头isEmpty()
:判断是否为空size()
:返回长度peek()
:返回队头clear()
:清空
public class Main {
public static void main(String[] args) {
Queue<Integer> q = new LinkedList<>();
q.add(1);
q.add(2);
q.add(10);
q.add(20);
System.out.println(q);
q.remove();
System.out.println(q);
System.out.println(q.isEmpty());
System.out.println(q.peek());
System.out.println(q.size());
}
}
控制台输出:
[1, 2, 10, 20]
[2, 10, 20]
false
2
3
public class Main {
public static void main(String[] args) {
Queue<Integer> q = new PriorityQueue<>();
q.add(5);
q.add(3);
q.add(4);
System.out.println(q);
q.remove();
System.out.println(q);
System.out.println(q.isEmpty());
System.out.println(q.peek());// 小根堆
System.out.println(q.size());
}
}
控制台输出:
[3, 5, 4]
[4, 5]
false
4
2
3.8.4 Set
接口 Java.util.Set<k>
实现
java.util.HashSet<k>
:哈希表(无序)Java.util.TreeSet<k>
:平衡树(有序)
函数
add()
:增加元素contains()
:是否包含remove()
:删除元素size()
:返回元素数isEmpty()
:是否为空clear()
:清空
Java.util.TreeSet<k>
:平衡树是有序序列,所以多几个操作
ceiling(key)
:返回大于等于key的最小元素,不存在返回nullfloor(key)
:返回小于等于key的最大元素,不存在返回null
public class Main {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(1);
System.out.println(set);
System.out.println(set.contains(1));
TreeSet<Integer> treeSet = new TreeSet<>();
treeSet.add(1);
treeSet.add(3);
treeSet.add(5);
System.out.println("大于等于2的最小值" + treeSet.ceiling(2));//返回大于等于某个元素的最小值
System.out.println("小于等于4的最大值" + treeSet.floor(4));
}
}
控制台输出:
[1, 2]
true
大于等于2的最小值3
小于等于4的最大值3
3.8.5 Map
接口:java.util.Map<k,v>
实现:
java.util.HashMap<k,v>
:哈希表java.util.TreeMap<k,v>
:平衡树
函数
put(key,value)
:添加关键字及其对应的值get(key)
:返回关键字对应的值contains(key)
:是否包含关键字romove(key)
:删除关键字size()
:返回元素数isEmpty()
:是否为空clear()
:清空entrySet()
:获取Map中所有对象的集合Map.Entry(K,V)
:Map中对象类型getKey()
:获取关键字getValue()
:获取值
java.util.TreeMap<k,v>
多的函数
ceilingEntry(key)
:返回大于等于key的最小元素,不存在就返回nullfloorEntry(key)
:返回小于等于key的最大元素,不存在就返回null
public class Main {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(2, "abc");
map.put(5, "yxc");
map.put(7, "AcWing");
System.out.println(map);
System.out.println(map.containsKey(5));
System.out.println(map.entrySet());
//Map的遍历
for(Map.Entry<Integer, String> p : map.entrySet()){
System.out.println(p.getKey());
System.out.println(p.getValue());
}
TreeMap<Integer, String> treeMap = new TreeMap<>();//平衡树
treeMap.put(1, "abc");
treeMap.put(5, "hxw");
treeMap.put(9, "Acwing");
Map.Entry<Integer, String> up = treeMap.ceilingEntry(4);
System.out.printf("%d %s\n", up.getKey(), up.getValue());
Map.Entry<Integer, String> down = treeMap.floorEntry(7);
System.out.printf("%d %s\n", down.getKey(), down.getValue());
}
}
控制台输出结果:
{2=abc, 5=yxc, 7=AcWing}
true
[2=abc, 5=yxc, 7=AcWing]
2
abc
5
yxc
7
AcWing
5 hxw
5 hxw
3.8.6练习
题目链接:828. 模拟栈 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
Stack<Integer> stk = new Stack<>();
while(m -- != 0){
String op = sc.next();
if(op.equals("push")){
int x = sc.nextInt();
stk.push(x);
}else if(op.equals("pop")){
stk.pop();
}else if(op.equals("empty")){
if(stk.empty()){
System.out.println("YES");
}else{
System.out.println("NO");
}
}else if(op.equals("query")){
System.out.println(stk.peek());
}
}
}
}
题目链接:829. 模拟队列 - Acwing题库
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
Queue<Integer> q = new LinkedList<>();
for(int i = 0; i < m; i ++){
String op = sc.next();
if(op.equals("push")){
int x = sc.nextInt();
q.add(x);
}else if(op.equals("pop")){
q.remove();
}else if(op.equals("empty")){
if(q.isEmpty()){
System.out.println("YES");
}else{
System.out.println("NO");
}
}else if(op.equals("query")){
System.out.println(q.peek());
}
}
}
}
class Solution {
public int[] findNumbersWithSum(int[] nums, int target) {
Set<Integer> set = new HashSet<>();
for(int x : nums){
int y = target - x;
if(set.contains(y)){
return new int[]{y, x};
}else{
set.add(x);
}
}
return null;//本题一定可以找到,随便返回一个
}
}
class Solution {
public List<Integer> getLeastNumbers_Solution(int[] input, int k) {
//使用优先队列
Queue<Integer> heap = new PriorityQueue<>();
for(int x : input){
heap.add(x);
}
List<Integer> res = new ArrayList<>();
for(int i = 0; i < k; i ++){
res.add(heap.remove());
}
return res;
}
}
题目链接:136. 邻值查找 - Acwing题库
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(br.readLine());
String[] strs = br.readLine().split(" ");
int[] w = new int[n];
for (int i = 0; i < n; i ++ )
w[i] = Integer.parseInt(strs[i]);
TreeMap<Integer, Integer> map = new TreeMap<>();
map.put(w[0], 0);
for (int i = 1; i < n; i ++ ) {
Map.Entry<Integer, Integer> up = map.ceilingEntry(w[i]);
Map.Entry<Integer, Integer> down = map.floorEntry(w[i]);
int res = Integer.MAX_VALUE, pos = -1;
if (down != null) {
res = w[i] - down.getKey();
pos = down.getValue();
}
if (up != null && up.getKey() - w[i] < res) {
res = up.getKey() - w[i];
pos = up.getValue();
}
bw.write(res + " " + (pos + 1) + "\n");
map.put(w[i], i);
}
bw.flush();
}
}