Java内置API


集合框架

集合框架是一种保存数据的容器,它与数组的区别在于集合框架的大小可以动态变化

Java集合框架提供了一套性能优良且方便使用的接口和类,位于java.unil包中

Collection(接口)
├── List(接口)- 有序、可重复、有索引
│ ├── ArrayList(类)- 数组实现,查询快,增删慢
│ ├── LinkedList(类)- 链表实现,增删快,查询慢
│ └── Vector(类)- 线程安全,已过时
│ └── Stack(类)- 栈结构

├── Set(接口)- 无序、唯一(不重复)
│ ├── HashSet(类)- 哈希表实现,无序
│ │ └── LinkedHashSet(类)- 链表维护插入顺序
│ └── SortedSet(接口)- 有序Set
│ └── TreeSet(类)- 红黑树实现,自然排序

└── Queue(接口)- 队列
├── Deque(接口)- 双端队列
│ ├── ArrayDeque(类)- 数组实现双端队列
│ └── LinkedList(类)- 也实现了Deque
├── PriorityQueue(类)- 优先级队列
└── BlockingQueue(接口)- 阻塞队列(JUC)
├── ArrayBlockingQueue(类)
├── LinkedBlockingQueue(类)
└── PriorityBlockingQueue(类)

Map(接口)- 键值对,独立于Collection
├── HashMap(类)- 哈希表实现
│ └── LinkedHashMap(类)- 链表维护插入顺序
├── Hashtable(类)- 线程安全,已过时
├── SortedMap(接口)- 有序Map
│ └── TreeMap(类)- 红黑树实现
└── ConcurrentMap(接口)- 并发Map(JUC)
├── ConcurrentHashMap(类)
└── ConcurrentSkipListMap(类)

Collection接口存储一组不唯一,无序的对象

List接口存储一组不唯一,有序的对象

Set接口存储一组唯一,无序的对象

Map接口存储一组键值对象,提供了key到value的映射

ArrayList实现了长度可变的数组,在内存中连续分配空间,遍历元素和随机访问的效率较高

LinkedList采用链表的存储方式,插入删除时的效率较高

ArrayList

添加数据:add(Object obj)

插入数据:add(int index,Object obj)

删除数据:remove(Object obj)

删除指定位置元素:remove(int index)

判断是否存在指定元素:contains(Object obj)

LinkedList

LinkList提供对头部和尾部元素进行操作的方法

在列表头部添加元素:addFirst(Object obj)

在列表末尾添加元素:addLast(Object obj)

返回列表的第一个元素:getFirst()

返回列表的最后一个元素:getLast()

删除并返回列表的第一个元素:removeFirst()

删除并返回列表的最后一个元素:removeLast()

HashSet

具有Set接口的所有方法,Set存储的是对象的引用,也就是唯一的对象

HashMap

HashMap属于双列集合,既要提供key也要提供value

添加数据:put(key,value)

根据键获取值:get(key)

获取所有键的集合:keySet()

获取所有值的集合:values()

获取所有键值对的集合:entrySet()

检测是否包含某个键:containsKey(key)

迭代器(Iterator)

迭代器是一个接口

如何获取一个迭代器的实现类?我们可以通过一个对象的方法创建对象,如通过Iterator iterator = set.iterator创建一个迭代器的实现类

检测是否具有下一个数据:hashNext()

获取下一个数据:next()

泛型集合

泛型集合限制了集合元素的类型

List<Book> list = new ArrayList<Book>();此时的list集合内便只能存储Book类型的数据


实用类

枚举

枚举(enum)指一组固定的常量组成的类型,当某种类型只能取固定范围内的值时,可以定义为枚举类型,如

public enum Weekday {}
MONDAY,TUESDAY,WENESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
}

引用枚举类型

public class Main {
public static void main(String[] args) {
Weekday day = Weekday.Monday;
}
}

包装类

包装类把基本数据类型转换为对象,并提供了一系列方法

基本数据类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
boolean Boolean
char Character

包装类可以有构造,并使用构造赋值(手动装箱)

Integer num = new Integer(1);
Double num2 = new Double(1.2);
Character ch = new Characer('hello');
Boolean bool = new Boolean(true);

基本类型可以自动转化为包装类,如Integer num = 1;(自动装箱)

包装类转化为基本类型,直接取值,如int num1 = num.intValue;(手动拆箱)

装箱和拆箱

装箱:基本类型转化为包装类型对象

拆箱:包装类型对象转化为基本类型的值

自动拆箱的例子int num1 = num;这里的num是一个Integer包装类的对象

装箱操作存在的必要性:泛型集合中不能容纳基本类型数据

Math

Math.abs()用于获得绝对值

Math.max()用于求最大值

Math.pow()用于进行次方运算

Math.sqrtI()用于进行开方运算

这些方法都是静态方法,不需要对Math类进行实例化

StringStringBuffer

String

常用方法

方法 说明
length() 获取字符串长度
equals(Object boj) 比较字符串内容是否一致
equalsIgnoreCase(String str) 忽略大小写对比
toLowerCase() 转小写
toUpperCase() 转大写
concat(String str) 连接字符串
indexOf(String value) 搜索第一个出现的字符串value,有则返回索引,没有找到则返回-1
lastIndexOf(String value) 搜索最后一个出现的字符串value,有则返回索引,没有找到则返回-1
substring(int index) 提取从位置索引开始的字符串部分
substring(int beginindex,int endindex) 提取beginindexendindex之间的字符串部分
trim() 返回一个前后不含任何空格的调用字符串的副本
replace(char oldChar,char newChar) oldChar替换为newChar
replace(CharSequence target,CharSequence replacement) target替换为replacement
split(String regex) 将第一个字符串分割为子字符处女,结果作为字符串数组返回

StringBuffer

StringBuffer是可变字符串。需要对字符串进行大量拼接时,使用StringBuffer类可以提高执行效率

常用方法

方法 说明
append(Striing str) 追加字符串
insert(int index) 插入字符串

输出StringBuffer需要先使用toString方法转换

随机数

使用Random类可以生伪随机数,位于java.util包下

使用Random random = new Random();实例化Random类,可以在构造方法中传入任意数字作为seed

获取日期和时间

使用Date类获得有关时间的数据,位于java.util包下

Date date = new Date;
//设置输出格式
SimpleDateFormate formater = new SimpleDateFormate("yyyy-MM-dd")
String result = formater.format(date);
System.out.println(result);
System.out.println(date.toString());

IO流

File类访问文件及目录

使用java.io.file包下的File

方法 说明
boolean exists() 判断文件或目录是否存在
boolean isFile() 判断是否是文件
boolean isDirectory() 判断是否是目录
String getPath() 返回此对象表示的文件的相对路径名
String getAbsolutePath() 返回此对象表示的文件的绝对路径名
String getName() 返回此对象表示的文件或目录的名称
boolean delete() 删除此对象指定的文件或目录
boolean createNewFile() 创建名称的空文件,不创建文件夹
long length() 返回文件的长度,单位为字节,如果文件不存在,则返回0L

字节流

FileInputStream,继承于InputStream

int read()返回下一个字节
int read(byte[] b)返回缓冲区数据总量
int read(byte[] b,int off,int len)从输入流中读取最多 len 个字节的数据到字节数组 b 中,从数组的偏移位置 off 开始存储
void close()关闭流
int available() 可以从输入流中读取的字节数目

import java.io.FileInputStream;
import java.io.IOException;

public class SimpleFileReader {
public static void main(String[] args) {
FileInputStream fis = null;

try {
// 1. 创建文件输入流
fis = new FileInputStream("test.txt");

// 2. 逐个字节读取并显示
int byteData;
System.out.println("文件内容(字节形式):");

while ((byteData = fis.read()) != -1) {
// 将字节转换为字符显示
System.out.print((char) byteData);
}

} catch (IOException e) {
System.out.println("读取文件出错: " + e.getMessage());
} finally {
// 3. 关闭流
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
System.out.println("关闭文件出错: " + e.getMessage());
}
}
}
}
}

FileOutputStream可用于写入文件,继承于OutputStream
void write(int c)写入整数
void write(byte[] buf)写入字节数组
void write(byte[] b,int off,int len)向输入流中写入最多 len 个字节的数据到字节数组 b 中,从数组的偏移位置 off 开始存储
void close()关闭流

import java.io.FileOutputStream;
import java.io.IOException;

public class SimpleFileWriter {
public static void main(String[] args) {
FileOutputStream fos = null;

try {
// 1. 创建文件输出流
// 如果文件不存在会自动创建,如果存在会覆盖
fos = new FileOutputStream("output.txt");

// 2. 写入字符串(需要转换为字节)
String text = "Hello, World!\n";
byte[] bytes = text.getBytes(); // 字符串转字节数组

// 3. 写入文件
fos.write(bytes);

System.out.println("文件写入成功!");

} catch (IOException e) {
System.out.println("写入文件出错: " + e.getMessage());
} finally {
// 4. 关闭流
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
System.out.println("关闭文件出错: " + e.getMessage());
}
}
}
}
}

字符流

字符流以字符为单位进行读取写入操作,基本逻辑与字节流无异

FileReader的父类是InputStreamReaderInputStreamReader的父类是Reader

import java.io.FileReader;
import java.io.IOException;

public class SimpleFileReader {
public static void main(String[] args) {
FileReader reader = null;

try {
// 1. 创建FileReader
reader = new FileReader("test.txt");

// 2. 逐个字符读取
int charData;
System.out.println("文件内容:");

while ((charData = reader.read()) != -1) {
System.out.print((char) charData);
}

} catch (IOException e) {
System.out.println("读取文件出错: " + e.getMessage());
} finally {
// 3. 关闭流
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
System.out.println("关闭文件出错: " + e.getMessage());
}
}
}
}
}

FileWriter的父类是OutputStreamWriterOutputStreamWriter的父类是Writer

import java.io.FileWriter;
import java.io.IOException;

public class SimpleFileWriter {
public static void main(String[] args) {
FileWriter writer = null;

try {
// 1. 创建FileWriter
// 默认覆盖模式,文件不存在会自动创建
writer = new FileWriter("output.txt");

// 2. 写入内容
writer.write("你好,世界!\n");
writer.write("Hello, World!\n");
writer.write("这是第三行。\n");

System.out.println("文件写入成功!");

} catch (IOException e) {
System.out.println("写入文件出错: " + e.getMessage());
} finally {
// 3. 关闭流
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
System.out.println("关闭文件出错: " + e.getMessage());
}
}
}
}
}

缓冲流

使用BufferedReader读取文件

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class SimpleBufferedReader {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {

String line;
int lineNumber = 1;

System.out.println("文件内容:");

// 逐行读取,直到文件结束
while ((line = reader.readLine()) != null) {
System.out.println(lineNumber + ": " + line);
lineNumber++;
}

System.out.println("总共 " + (lineNumber - 1) + " 行");

} catch (IOException e) {
System.out.println("读取文件出错: " + e.getMessage());
}
}
}

使用BufferedWriter写入文件

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class SimpleBufferedWriter {
public static void main(String[] args) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {

// 写入内容
writer.write("你好,世界!");
writer.newLine(); // 换行
writer.write("Hello, World!");
writer.newLine();
writer.write("这是第三行。");

System.out.println("文件写入成功!");

} catch (IOException e) {
System.out.println("写入文件出错: " + e.getMessage());
}
}
}

读写二进制文件

上面说的集几种流只能操作文本,使用二进制流可以让我们实现对更多文件的读写

DataInputStream类,是FileInputStream的子类,与FileInputStream类结合使用读取二进制文件

DataOutputStream类,是FileOutputStream的子类,与FileOutputStream类结合使用写二进制文件

import java.io.*;

public class BinaryFileCopy {
public static void main(String[] args) {
DataInputStream dis = null;
DataOutputStream dos = null;

try {
// 源文件(二进制文件,如图片)
FileInputStream fis = new FileInputStream("C:\\Java\\读书\\1.png");
// 目标文件
FileOutputStream fos = new FileOutputStream("C:\\Java\\读书\\2.png");

dis = new DataInputStream(fis);
dos = new DataOutputStream(fos);

// 边读取数据,边写入数据
int data; // 存储读取的字节(0-255)或-1(文件结束)

while ((data = dis.read()) != -1) {
// 写入读取的字节
dos.write(data);
}

System.out.println("文件复制完成!");

} catch (FileNotFoundException e) {
System.out.println("文件未找到: " + e.getMessage());
} catch (IOException e) {
System.out.println("IO错误: " + e.getMessage());
} finally {
// 关闭流(实际代码中应该在这里)
}
}
}

多线程

所谓的多线程是多个线程交替占用CPU资源,而非真正的并行执行-

在Java中创建线程:继承 java.lang.Thread 类或者实现 java.lang.Runnable 接口

在通过实现 java.lang.Runnable 接口创建线程时,我们定义的线程类中并没有start()方法,还需要调用Thread类中的带参构造方法将Runnable 接口的实现类包装成一个Thread对象才可以进行调用start()方法

线程同步

多个线程访问同一个资源时,会引发数据不安全的问题

synchronized修饰符:对于被修饰的方法,synchronized就是为当前线程声明一个锁,将被修饰的方法视为一个整体。对于使用synchronized关键字修饰的代码块,相比synchronized同步的范围更小,仅同步被修饰的代码块

类型名称 线程是否安全 效率比较 适合场景
Vector 多线程并发共享资源
ArrayList 单线程
Hashtable 多线程并发共享资源
HashMap 单线程

线程池

Java线程池是一种实现多线程编程的机制,它可以帮助我们有效地管理和调度多个线程,从而提高程序的性能和效率

Java线程池的使用步骤:

创建线程池:使用 java.util.concurrent.Executors 类中的静态方法创建线程池

创建任务:创建实现 RunnableCallable 接口的任务

提交任务:使用线程池的 submit() 方法提交任务,也可以使用 execute() 方法提交 Runnable 任务

关闭线程池:使用线程池的 shutdown()shutdownNow() 方法关闭线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SimpleThreadPool {
public static void main(String[] args) {
// 1. 创建线程池(2个线程)
ExecutorService pool = Executors.newFixedThreadPool(2);
// 2. 提交5个任务
for (int i = 1; i <= 5; i++) {
int taskId = i;
pool.execute(() -> {
// 简单输出:哪个线程执行哪个任务
System.out.println(Thread.currentThread().getName() + " -> Task " + taskId);
});
}
// 3. 关闭线程池
pool.shutdown();
}
}