版本问题 写这篇笔记时 Oracle 官网上的最新的 JDK 版本是 Java 19,兼容 Apple Silicon,然而目前最常用的 Java 8 和 Java 11 还没有适配,可以使用 Zulu JDK,关于如何配置 Sublime Text 3 快速编写简单的 Java 程序可以参考 如何在 macOS 下配置 Sublime Text 的可交互 Java 环境 ,集成开发环境推荐 IntelliJ IDEA。
编译运行 过程:代码编译成字节码(可以在 Java CPU 上运行),经 JVM 再转变为机器指令。
编译:javac file_name.java
运行:java file_name
打包:jar cvf file_name.jar *.*
注意:一个文件只能有一个 public class
,且类名与文件名一致。
输入输出 标准 1 2 3 4 5 6 7 import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner in = new Scanner(System.in); System.out.println(in.nextLine()); } }
in.next()
:读入一个字符串。
in.nextLine()
:读入一行,返回一个字符串。
可以使用 hasNextInt()
等方法来预判(以通过 while
循环读取任意数量的数据):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.Scanner;public class test { public static void main (String[] args) { Scanner in = new Scanner(System.in); if (in.hasNextInt()) { int i = in.nextInt(); System.out.printf("The next integer is %d.\n" ,i); } else System.out.println("The next integer does not exist." ); } }
快读 关于字节流和字符流相关:待填坑。(StreamTokenizer)
1 2 3 4 5 6 7 8 9 10 11 import java.io.*;public class test { public static void main (String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); Integer n = Integer.parseInt(in.readLine()); out.write(n.toString()); out.newLine(); out.flush(); } }
导入 java.io.*
,主函数 throws IOException
。
BufferedReader
和 BufferedWriter
使用 InputStreamReader
和 OutputStreamWriter
初始化。
输出后刷新缓冲区 flush()
。
【Kattio】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.io.*;class Kattio extends PrintWriter { private BufferedReader bf; private StringTokenizer st; public Kattio () { super (System.out); bf = new BufferedReader(new InputStreamReader(System.in)); } public String next () { try { while (st == null || !st.hasMoreTokens()) { st = new StringTokenizer(bf.readLine()); } return st.nextToken(); } catch (Exception e) {} return null ; } public int nextInt () { return Integer.parseInt(next()); } }
注意程序结束时需要执行 io.close()
。
变量 命名规范
不能以数字开头,可以包含 _
和 $
。
函数、变量采用峰驼命名法,类、接口首字母大写,常量全部大写。
数据类型 常量使用 final
修饰。(final 方法不允许重写,final 类不允许继承)
基本数据类型(如 int
、double
)及强制类型转换,语法与 C++ 类似,但布尔类型的关键字为 boolean
。
整数常量默认 int,long 类型是 10000000L。
浮点常量默认 double,float 类型是 3.14F。
使用 Unicode 码,字符类型 char 为 16 位(0~65536)。
空:null
&
和 |
等在 Java 中也可以用于逻辑运算,不过不短路。
+
可以连接字符串。
分为基本数据类型和引用数据类型。
数组是引用数据类型,不是基本数据类型。
对于引用类型,==
比较指向相同,equals()
比较内容相同。
基本类型放在栈中,引用类型放在堆中。
Java 只有值传递,引用类型存放的是其指向(指针),故传递的也是其指向。
数组 数组是引用类型 而非基本数据类型。
一维数组 定义数组:int[] a = new int[100];
,数组的元素个数可以为变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int [] a = new int [n]; for (int i = 0 ; i < n; ++i) a[i] = i; for (int i = 0 ; i < n; ++i) { System.out.print(a[i] + ((i == n - 1 )?"\n" :" " )); } } }
可以使用 a.length
访问数组大小,数组中元素默认为 $0$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int [] a = new int [n]; for (int i = 0 ; i < n / 2 ; ++i) a[i] = i; for (int i = 0 ; i < a.length; ++i) { System.out.print(a[i] + ((i == n - 1 )?"\n" :" " )); } } }
初始化:
int[] a = {0, 1, 2, 3, 4, 5};
。
初始化:a = new int[]{0, 1, 2, 3, 4, 5};
维表达式:a = new int[6];
而这样是错误的 a = new int[6]{0, 1, 2, 3, 4, 5};
,不能同时用维表达式和初始化创建数组。
二维数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Scanner in = new Scanner(System.in); int n = in.nextInt(), m = in.nextInt();int [][] a = new int [n][m];for (int i = 0 , cnt = 1 ; i < n; ++i) { for (int j = 0 ; j < m; ++j) { a[i][j] = cnt++; } } for (int [] b: a) { for (int c: b) { System.out.print(c + " " ); } System.out.println(); }
1 2 3 4 5 6 7 8 9 10 11 12 int [][] a = { {1 , 2 , 3 }, {4 , 5 , 6 }, {7 , 8 , 9 } }; for (int i = 0 ; i < a.length; ++i) { for (int j = 0 ; j < a[i].length; ++j) { a[i][j] = 0 ; } }
允许不规则数组:
1 2 3 4 int arr[][] = new int [3 ][];arr[0 ] = new int [2 ]; arr[1 ] = new int [3 ]; arr[2 ] = new int [5 ];
Arrays java.util.Arrays
数组拷贝:int[] dest = Arrays.copyOf(src, src.length)
数组排序
引入:import java.util.Arrays;
基本用法:Arrays.sort(a);
对数组 a
进行递增排序。
时间复杂度:$O(nlog_2n)$。
指定排序范围:Arrays.sort(a, 0, 5);
对数组 a
的前 6 个元素进行排序。
自定义排序规则:实现 Comparable 接口,实现 public int compareTo(Object o) 方法;创建实现 Comparator 接口的类,实现 public int compare(Object a, Object b) 方法。
数组查找:int loc = Arrays.binarySearch(src, element);
注释 用法与 C++ 类似。
分支 if
语句和 switch
语句与 C++ 类似。
就近原则:
等同于
1 2 3 4 if () { if () {} else {} }
也就是说,第一部分代码中的 else
无视缩进,与第二个 if
形成一组。
switch
语句中的 default
不是必要的。
循环 while
语句和 do-while
语句与 C++ 类似。
for
语句与 C++ 类似,可使用 break
语句和 continue
语句,也可以使用 goto
。
类似 for-in
的 for-each
遍历数组元素:
1 2 3 for (int x: a) { System.out.println(x); }
注意,上述代码中改变 x
的值并不会改变原数组中对应项的值(引用类型的数组除外),例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Main { public static void main (String[] args) { int [] a = new int [10 ]; for (int i = 0 ; i < 10 ; ++i) { a[i] = i; } for (int x: a) { x = 0 ; System.out.print(x + " " ); } System.out.println(); for (int x: a) { System.out.print(x + " " ); } System.out.println(); } }
break
和 continue
语句可以给出标号,跳出制定的代码块。
数据类型 字符类型 Java 使用 Unicode 编码,用单引号表示字符,可与 int
相互赋值。
转义字符:\t
、\b
、\n
、\r
、\\
、\'
、\"
……
Wrap 类型 将基本类型转化为对象,
1 2 3 4 5 6 7 8 9 int -> Integershort -> Short long -> Long float - > Float double -> Double boolean -> Boolean char -> Charaterbyte -> Byte
Integer.parseInt(String s, int radix)
方法可以将字符串转化为整数,radix
参数用于指定基数,默认为 10。
类似的还有 Long.parseLong(String s)
、Double.parseDouble(String s)
等等。
Integer 类型 可自由赋值给 int 类型。
1 2 3 4 5 6 7 8 9 10 11 12 Integer I = Integer(1024 ); Integer I = Integer.valueOf(1024 ); System.out.println(I); int i = I;System.out.println(i); System.out.println(Integer.MIN_VALUE + " " + Integer.MAX_VALUE);
成员函数 toString()
和 Integer.toString(int i)
方法可返回整数对应的字符串。
Integer.MAX_VALUE 返回最大值。
Character 类型 1 2 3 4 5 6 7 8 9 char c = 'C' ;System.out.println(Character.isDigit(c)); System.out.println(Character.isLetter(c)); System.out.println(Character.isLetterOrDigit(c)); System.out.println(Character.isLowerCase(c)); System.out.println(Character.isUpperCase(c)); System.out.println(Character.isWhitespace(c)); System.out.println(Character.toLowerCase(c)); System.out.println(Character.toUpperCase(c));
String 类型 字符串的连接是从左向右的,例如:
1 2 System.out.println(1 + 2 + "3" ); System.out.println("1" + 2 + 3 );
判断相等时应当使用 s1.equals(s2)
,在 Java 中,类的名称类似于指针,使用运算符 ==
相当于判断两者是否指向同一对象。
两种声明方式:
1 2 String s = new String("Hello World!" ); String s = "Hello World!" ;
这两种初始化的方式是有所不同的,例如:
1 2 3 4 5 6 String s1 = "Hello" ; String s2 = "Hello" ; System.out.println(s1 == s2); String s1 = new String("Hello" ); String s2 = new String("Hello" ); System.out.println(s1 == s2);
可见,使用 new
初始化相同内容的字符串时创建了新的对象,这里用到了 Java 中“常量池”的概念。
注意:在 Java 中采用值传递而非引用传递。
一些函数的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 String s1 = "ABC" ; String s2 = "BCD" ; System.out.println(s1.compareTo(s2)); System.out.println(s1.charAt(0 )); System.out.println(s1.substring(1 )); System.out.println(s1.substring(0 , 2 )); System.out.println(s1.indexOf('B' )); System.out.println(s1.indexOf('Z' )); System.out.println(s1.indexOf('A' , 1 )); System.out.println(s1.startsWith("AB" )); System.out.println(s1.endsWith("BA" )); s1 = " ABABA " ; System.out.println(s1.trim()); System.out.println(s1.replace('A' , 'C' )); System.out.println(s1.toLowerCase()); Scanner in = new Scanner(System.in); String s = in.next(); switch (s) { case "Happy" : System.out.println("You are happy." );break ; case "Sad" : System.out.println("You are sad." );break ; }
另:可使用 indexOf
进行字符串查找,内部实现为嵌套循环的朴素算法,时间复杂度为 $O(nm)$,但只能返回一个位置,却可以指定查找的起始位置来实现连续查找。
未初始化的 String 不能调用 length()
方法,而初始化为 ""
的 String 调用 length()
会返回数字 0。
split
方法可以对字符串进行拆分,得到拆分后的字符串数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.Scanner;public class test { public static void main (String[] args) { Scanner in = new Scanner(System.in); String str = in.nextLine(); String s[] = str.split(" " ); for (String ss: s) { System.out.println(ss); } } }
format
方法可以获得格式化的字符串:
1 2 3 4 5 6 7 8 9 import java.util.Scanner;public class test { public static void main (String[] args) { Scanner in = new Scanner(System.in); double d = in.nextDouble(); String s = String.format("Double Value is %.7f\n" ,d); System.out.print(s); } }
(Java 中 float
类型和 double
类型变量都使用 %f
表示,byte
类型、short
类型、int
类型、long
类型都使用 %d
表示)
函数 只能按值传递。
枚举类型 public enum Name { TYPE1, TYPE2, TYPE3 };
Name name = TYPE1 or Name.TYPE1
面向对象 继承性,封装性,多态性。
Type object = new Type();
:
Type object
:声明
new
:实例化
Type()
:初始化
没有析构函数,自动垃圾回收(GC,Garbage Collection)。【finilize()
被 Java 9 弃用】
耦合性(依赖关系)与可扩展性:硬编码 -> 框架+数据。
注意:类的赋值语句并不是对象赋值,而是改变变量管理的对象。
类 调用成员函数时可以直接使用成员变量名或成员函数名,可不使用 this
指定(若与成员函数某个参数重名则须要指定),this
像指针一样管理着调用成员函数的对象(就像一个快捷方式 )。
成员变量会被给予初始值 $0$,与本地变量(函数中的变量)不同,本地变量不被赋值就使用则编译失败。
创建对象的时候会对所有变量依次初始化,然后调用构造函数(如果存在的话),若有多个构造函数则调用与 new
时参数对应的构造函数。
1 2 3 4 5 6 7 8 9 10 11 public class test { int x; test() {} public void f (int x) { System.out.println(x); System.out.println(this .x); } public static void main (String[] args) { test t = new test();t.f(1 ); } }
可以在构造函数中使用 this
调用其它构造函数,例如:
1 2 3 4 5 6 7 8 9 10 11 public class test { int x; test ( ) {System.out.println("test" );} test (int x ) { this (); this .x = x; } public static void main (String [] args ) { test t = new test(1 ); } }
但是 this()
只能作为该构造函数的第一个语句,否则就会报错:
访问控制 public 属性:public
关键字修饰的类必须在它自己的 java
文件中,即文件名与类名相同。【同一个类,同一个包,子类,不同类不同包非子类】
protected 属性:protected
关键字保证包内的类和子类可以访问。【同一个类,同一个包,子类】
default 属性:默认属性,仅可以在同一个包内 访问。【同一个类、同一个包】
private 属性:private
关键字只适用于成员变量和成员函数,仅类中可使用,在类外实例化的对象不可访问 (但对于同一个类的私有成员变量,只要代码写在类中,两个不同的对象之间可以相互访问)。【仅同一个类】
package 包
包与目录对应,可以嵌套子目录:package parent.child
。
开头添加 package package_name;
表明文件属于这个包,使用小写,且只有一条
成员变量、成员函数和类前没有 private
或 public
关键字,则意味着它仅可以在同一个包内访问。
import java.lang.*;
默认添加,无需指明。
导入其它包内声明的类:import package_name.class_name;
,不选择导入则需要使用 package_name.class_name
作为全名调用包外的类,import package_name.*;
表明导入包内的所有内容。
static 属性 最先初始化。
同一个类的类(静态)变量为所有对象共有,可以使用 object_name.var_name
也可以使用 class_name.var_name
访问,可以称为类变量。
静态函数(用 static
修饰的属性的函数)与静态变量类似,静态函数只能访问类(静态)变量,不能访问成员变量(因为静态函数属于这个类,而成员变量属于一个特定的对象)。
泛型类 如 ArrayList<String> arr = new ArrayList<String>();
,声明 String 类型的容器,否则默认是 Object 类型。
定义:class A<E> { E e; }
(如 HashSet)、class B<X, Y> { X x; Y y; }
(如 HashMap)。
接口中也可以定义泛型
> ` extends T>` ` super T>`
注意:Java 中泛型只能是引用类型(如 `Integer`),不能是基本类型(如 `int`)。
##### 类数组
1. 基本数据类型的数组中存放数据,类数组中存放管理数据用的“指针”(初始为 `null`)。
2. 对于类数组,修改 `for-each` 语句中 `x` 的值将会影响原数组中的值,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class I { public int i; I(int i) { this .i = i; } } public class Main { public static void main (String[] args) { I[] a = new I[10 ]; for (int i = 0 ; i < 10 ; ++i) { a[i] = new I(i); } for (I x: a) { System.out.print(x.i + " " ); x.i = 0 ; } System.out.println(); for (I x: a) { System.out.print(x.i + " " ); } System.out.println(); } }
类的对象名仅仅为指向该对象的指针,赋值时也仅仅是指针的赋值,让两者管理同一个对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class I { public int i; I(int i) { this .i = i; } } public class Main { public static void main (String[] args) { I a = new I(128 ); I b = new I(64 ); b = a; a.i = 32 ; System.out.println(b.i); } }
##### 继承(`extends`)
final 修饰不允许继承。
所有类均默认为 Object 的子类:`toString()`、`equals(Object object)`……
继承是为了方便复用代码,避免重复编写代码,不利于维护。
如果父类和子类出现重名,则会生成两个变量,不加 `super.` 会默认为当前类的变量或函数。
覆盖:子类与父类出现同名函数。
##### Object 类:
`public String toString()`:定义在父类 `Object` 里,在类中重写来改变 `System.out` 时的输出:
1 2 @Override public String toString () {}
`toString()` 会自动调用,如 `"str" + object` 等同于 `"str" + object.toString()`。
`public boolean equals(Object obj)`:定义在父类 `Object` 里,在类中没有重写时调用很大概率返回与预期不符的结果。
1 2 3 4 5 @Override public boolean equals (Object obj) { Class object = (Class)obj; return element.equals(object.element); }
##### 多态
子类(动态类型)可以被当作父类(声明类型)使用:如父类容器可以放入继承自同一父类的不同子类的元素、向上造型【向上转型】(`FatherClass object = new ChildClass();`)。
特殊:
1 2 FatherClass object = new ChildClass(); ChildClass newObject = (ChildClass)object;
造型:当作…来看待;转换:变更。
**动态绑定**:“动态”是“运行时”绑定的意思。尽管声明类型不同,调用时还是会调用**动态类型**的函数。
**变量与函数不同,使用的是静态类型的变量,只能封装为函数访问动态类型的变量 getXXX()**
object instanceof Class:是其或其子类的对象
##### 构造函数
执行顺序:变量初始化 -> 父类构造函数 -> 当前类构造函数。
调用父类构造函数:`super(items)`,如果不写的话在执行子类构造函数时会**默认执行父类不带参数的构造函数**(不存在则报错)。
##### super 和 this
- 如果调用 super() 和 this() 都必须作为第一语句,因此两者不能同时出现。
- 子类中出现与父类同名变量用 super 区分。
##### 抽象 (abstract)
- 含有抽象函数 `abstruct func` 的一定是抽象类 `abstract class`。
- 继承自抽象类就要实现其所有抽象方法。
- 构造方法、static 方法、final 方法不能定义为抽象函数。
注:这里的“抽象”表示的含义是不具体,面向对象中另一种“抽象“的含义是封装使看不到底层细节。
final 类的方法都是 final 方法,因为不能继承自然就不能被重写。
final 方法可以提高执行效率。
final 变量可以先定义,随后初始化。
抽象类允许有 private 成员,但其抽象函数不能同时用 abstract 和 private/final/static 修饰。
##### 接口(interface)
纯抽象类
接口内的只有 public static final 常量,无需指明,必须初始化。
只有 public abstract 方法,无需指明。
接口不能实现 implements 接口,只能继承 extends 接口(可以继承多个)。
可以直接使用接口的常量 Interface.constant. 常量可以用 Math.random() 初始化。
##### 内部类
内部类:需要先有外部类的对象。**out_object.new**,`Out.this`
1 2 3 class Out { class In { } }Out out = new Out(); Out.In in = out.new In () ;
静态类:嵌套类。
局部内部类:可以访问外部。
匿名内部类:`new superclass_or_interface() {}`,传递排序规则时经常用到,若继承的父类只有含参构造函数则在参数列表中指明。
##### 重载(Overload)
参数列表不同的同名函数,返回值等均不能用于区分。
多个构造函数也叫重载
##### 重写(Override)
- 名称、参数、返回值必须相同。
- 子类重写的访问控制只能更宽松。
- 与 C++ 不同,默认类似虚函数,无论静态类型一律调用动态类型的方法。
### 输入输出
InputStream OutputStream:字节流
Reader/Writer:字符流
FileInputStream/FileOutputStream
Buffered:缓冲流
PrintStream/PrintWriter:打印流
DataInputStream/DataOutputStream:数据流
ObjectInputStream/ObjectOutputStream:对象流
### GUI
AWT(Abstract Window Toolkit)重量级组件
Swing 轻量级组件
SWT(Standard Widget Toolkit)
Container 与 Component,Component 父类,Container 容纳 Component。
### 多线程
1. implements Runnable public void run() {} Thread thread = new Thread(ClassName) 同一实例的多个进程
2. extends Thread public void run() {} Thread thread = new ClassName() 多个实例
getPriority() setPriority(int) 1-10, 5 is normal
synchronized 放在函数前
sychronized(object) {}
wait() notify()
### 数据库
Structure Query Language
create table name
drop table name
select xxx from xxx
insert into xxx
update xxx
delete from xxx
### 网络编程
import java.net.*;
1 2 3 4 5 6 7 InetAddress address = InetAddress.getLocalHost InetAddress address = InetAddress.getByName address.getHostName address.getHostAddress
ServerSocket()(int port)
Socket accept()
close()
Socket()(String host, int port)(InetAddress address, int port)
close() getInputStream getOutputStream
### 异常处理
异常(Exception)和错误(Error)
不受检异常(Unchecked Exception):Runtime Exception/Error……
受检异常(Checked Exception):IOException/FileNotFoundException……
1 2 3 4 5 6 7 try { } catch (Exception e) { } finally { }
throws 让上一级处理
- `getMessage()`
- `printStackTrace()`
- `toString()`:返回异常名与 `getMessage()` 的信息。
1 2 3 public static void main(string [] args) throws Exception { throw Exception ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import java.io.*;import javax.swing.*;class CustomException extends Exception { CustomException() { System.out.println("init()" ); } public String toString () { return super .toString(); } public String getMessage () { return super .getMessage() + " and " + "getMessage()" ; } } public class Main { static void test () throws CustomException { throw new CustomException(); } public static void main (String[] args) { try { test(); } catch (Exception e) { e.printStackTrace(); System.out.println(e); JOptionPane.showMessageDialog(null , e.getMessage()); } finally { System.out.println("Final" ); } System.out.println("Hello world!" ); } }
### 常用库/函数
##### Math
- 常数:`Math.PI`,`Math.E`.
- 绝对值:`Math.abs(int/long/double var)`
- 转整数:`Math.ceil(double var)`(上界),`Math.floor(double var)`(下界),`Math.rint(double var)`(最接近)。
- 四舍五入:`Math.round(double var)`。
- 比较:`Math.max(a, b)`,`Math.min(a, b)`。
- 数学:`exp()`、`log()`、`pow()`、`sqrt()`、`sin()`、`cos()`、`tan()`、`asin()`、`acos()`、`atan()`。
- 笛卡尔坐标转极坐标:`atan2()`。
- 随机数:`Math.random()` 得到一个 $[0,1)$ 的随机数。
##### 系统信息
1 2 System.getProperty("os.name" ); System.getProperty("java.version" );
##### 时间统计
`System.currentTimeMillis()` 作差可得代码段的运行时间(以毫秒为单位)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); long st = System.currentTimeMillis();for (int i = 0 ; i < 1000000 ; ++i) { out.write(String.format("%d\n" , (int )(Math.random() * 100000 ))); } out.flush(); long et = System.currentTimeMillis();System.out.println(et - st); long st = System.currentTimeMillis();for (int i = 0 ; i < 1000000 ; ++i) { System.out.println((int )(Math.random() * 100000 )); } long et = System.currentTimeMillis();System.out.println(et - st);
##### Random
1 2 3 4 5 import java.util.Random;Random r = new Random(); r.nextInt(); r.nextInt(10 ); r.nextDouble();
##### Date
- 头文件:`import java.util.Date;`
- `long getTime()` 返回 1970.1.1 00:00:00 过去的秒数。
- `setTime(long)` 设置 1970.1.1 00:00:00 过去的秒数。
##### Calendar
- 头文件:`import java.util.Calendar;`
- 初始化:`Calendar cal = Calendar.getInstance();`
- 设置日期(年月日):`cal.set(year, month, day)`。
- 设置日期(设置一项):`cal.set(Calendar.YEAR, 2023)`。
- 修改日期:`cal.add(Calendar.YEAR, -10)`
- 获取日期:`cal.get(Calendar.YEAR)`
附:
- Calendar.YEAR
- Calendar.MONTH
- Calendar.DATE
- Calendar.HOUR_OF_DAY:24小时制
- Calendar.MINUTE
- Calendar.SECOND
- Calendar.DAY_OF_WEEK:星期
GregorianCalendar 继承自 Calendar,日期计算很方便。
注意:月的范围是 [0, 11],而非 [1,12]。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.util.GregorianCalendar;public class Main { public static void main (String[] args) { GregorianCalendar cal = new GregorianCalendar(2000 , 1 , 2 ); while (cal.get(GregorianCalendar.YEAR) <= 2023 ) { int year = cal.get(GregorianCalendar.YEAR); if (cal.isLeapYear(year)) { System.out.println(year); } cal.add(GregorianCalendar.YEAR, 1 ); } } } import java.util.GregorianCalendar;public class Main { public static void main (String[] args) { GregorianCalendar cal1 = new GregorianCalendar(2000 , 1 , 1 ); GregorianCalendar cal2 = new GregorianCalendar(2000 , 2 , 1 ); System.out.println((cal2.getTime().getTime() - cal1.getTime().getTime()) / (1000L * 24 * 60 * 60 )); } }
##### 更快的 StringBuilder
append(), insert(), delete(), replace(); charAt();
重要:Java 中容器类型只能为 Wrap 类型,不能是基本数据类型。
引入:`import java.util.*;`。
遍历:`for-each`。
##### ArrayList
基本用法:
- 插入:`add(value)`
- 修改:`set(index, value)`
- 删除:`remove(index or value)`
- 大小:`size()`
- 取值:`get(index)`
- 转数组:`toArray(newArrayName)`
##### LinkedList
add/get/remove + First/Last
- `add(value)`,`addFirst`
- `removeFirst()`
- `getFirst()`、`getLast()`
- `peekFirst()`、`peekLast()`
##### HashSet
特点:无序集合。
基本用法:
- 插入:`add(value)`
- 删除:`remove(value)`
- 判断是否存在:`contains(value)`
- 大小:`size()`
- 清空:`clear()`
##### TreeSet
特点:有序集合。
##### HashMap
基本用法:
- 插入:`put(key, value)`。
- 取值:`get(key)`,不存在返回 `null`。
- 判断是否存在:`containsKey(key)`。
- 键集合:`keySet()`。
- entrySet()
- values()
- 遍历:`for(KeyType key: hashMap.keySet()) {}`
LinkedHashSet/LinkedHashMap
##### Collections
sort
binarySearch
reverse
copy
min
max
##### PriorityQueue
`add(_element_)`
`peek()`
`poll()`
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.PriorityQueue;import java.util.Comparator;public class Main { public static void main (String[] args) { PriorityQueue<Integer> pq = new PriorityQueue<Integer>(new Comparator<Integer>() { @Override public int compare (Integer a, Integer b) { return a < b ? -1 : 1 ; } }); pq.add(64 ); pq.add(32 ); pq.add(128 ); System.out.println(pq.peek()); pq.poll(); System.out.println(pq.peek()); pq.poll(); System.out.println(pq.peek()); pq.poll(); } }
##### Deque
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import java.util.Deque;import java.util.LinkedList;Deque<Integer> dq = new LinkedList<Integer>(); System.out.println(dq.size()); dq.addLast(512 ); dq.offerLast(1024 ); System.out.println(dq.getFirst()); System.out.println(dq.peekLast()); System.out.println(dq.removeFirst()); System.out.println(dq.pollLast());
##### 迭代器
1 for (Iterator<String> it = s.iterator(); s.hasNext(); ) System.out.println(s.next());
For-each 只能遍历数组和实现了Iterable接口的实例。
##### hashCode
public int hashCode() { return 123; }
##### 排序
- Arrays.sort() 用于数组排序,还有 `Collections.sort()`.
- 可以指定后两个参数 fromIndex 和 toIndex,左闭右开。
- 返回值:负数表示在前,返回零表示相等,返回整数表示在后。
1 2 3 4 5 6 7 8 9 10 11 12 import java.util.Arrays;Arrays.sort(a); Arrays.sort(a, new Comparator<typename>() { @Override int compare (typename a, typename b) { if (a.x == b.x) return a.y < b.y ? -1 : 1 ; return a.x < b.x ? -1 : 1 ; } })
对类排序可以实现 Comparable 接口。
1 2 3 4 5 6 public class ClassName implements Comparable <ClassName > { @Override public int compareTo (Classname rhs) { return -1 ; } }