1.异常
异常分类:运行时异常和编译异常
java
package com.popo.exceptiondemo;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionDemo1 {
public static void main(String[] args) {
// 异常包括两种:编译时异常和运行时异常
try {
show1();
} catch (Exception e) {
e.printStackTrace();
// Unparseable date: "2026-10-24 14:38:44"
// D:\java.png (系统找不到指定的文件。)
}
try {
show2();
} catch (Exception e) {
e.printStackTrace(); // Index 3 out of bounds for length 3
}
}
public static void show1() throws Exception{
// 编译时异常:编写代码时必须进行处理,否则程序无法编译通过
String time = "2026-10-24 14:38:44";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = sdf.parse(time); // 必须对其进行捕获或声明以便抛出
System.out.println(date);
InputStream is = new FileInputStream("D:/java.png");
}
public static void show2() throws Exception{
// 运行时异常:编译时不会检查,但运行时会检查
int[] arr = {1,2,3};
System.out.println(arr[3]); // ArrayIndexOutOfBoundsException
}
}
异常作为函数返回值
java
package com.popo.exceptiondemo;
public class ExceptionDemo2 {
public static void main(String[] args) {
// 异常作为函数返回值
try {
div(10, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
// throws 声明,写在方法签名上,告知调用者该方法可能抛出的异常类型
public static void div(int a, int b) throws Exception {
if (b == 0) { // 编译时异常
// throw 动作,在方法内部手动抛出一个异常对象
throw new Exception("除数不能为零");
}
System.out.println(a / b);
}
// public static void div(int a, int b) {
// if (b == 0) { // 运行时异常
// throw new RuntimeException("除数不能为零");
// }
// System.out.println(a / b);
// }
}
自定义异常
java
package com.popo.exceptiondemo;
public class ExceptionDemo3 {
public static void main(String[] args) {
// 自定义异常
try {
saveAge(121);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void saveAge(int age) {
if (age < 1 || age > 120) {
throw new AgeIllegalRuntimeException("年龄不能为负数");
}
}
// public static void saveAge(int age) throws Exception{
// if (age < 1 || age > 120) {
// throw new AgeIllegalException("年龄不能为负数");
// }
// }
}
java
package com.popo.exceptiondemo;
public class AgeIllegalRuntimeException extends RuntimeException {
public AgeIllegalRuntimeException() {
}
public AgeIllegalRuntimeException(String message) {
super(message);
}
}
java
package com.popo.exceptiondemo;
public class AgeIllegalException extends Exception {
public AgeIllegalException() {
}
public AgeIllegalException(String message) {
super(message);
}
}
2.泛型
自定义泛型类
java
package com.popo.fanxingdemo;
import java.util.ArrayList;
public class FanxingDemo1 {
public static void main(String[] args) {
// 自定义泛型类
MyArrayList<String> myArrayList = new MyArrayList<>();
myArrayList.add("Hello");
myArrayList.add("World");
System.out.println(myArrayList.get(0));
System.out.println(myArrayList.get(1));
}
}
class MyArrayList<E> {
private ArrayList<E> list = new ArrayList<>();
public void add(E e) {
list.add(e);
}
public E get(int index) {
return list.get(index);
}
}
自定义泛型接口
java
package com.popo.fanxingdemo;
public class FanxingDemo2 {
public static void main(String[] args) {
// 自定义泛型接口
Data<Student> studentData = new StudentData();
studentData.add(new Student());
Student student = studentData.get(0);
Data<Teacher> teacherData = new TeacherData();
teacherData.add(new Teacher());
Teacher teacher = teacherData.get(0);
}
}
class Student {
}
class Teacher {
}
interface Data<T> {
void add(T t);
T get(int index);
}
class StudentData implements Data<Student> {
@Override
public void add(Student t) {
}
@Override
public Student get(int index) {
return null;
}
}
class TeacherData implements Data<Teacher> {
@Override
public void add(Teacher t) {
}
@Override
public Teacher get(int index) {
return null;
}
}
泛型方法
java
package com.popo.fanxingdemo;
public class FanxingDemo3 {
public static void main(String[] args) {
// 泛型方法
Integer[] intArray = {1, 2, 3, 4, 5};
printArray(intArray);
String[] stringArray = {"H", "e", "l", "l", "o"};
printArray(stringArray);
}
public static <T> void printArray(T[] array) {
for (T t : array) {
System.out.println(t);
}
}
}
通配符
java
package com.popo.fanxingdemo;
import java.util.ArrayList;
public class FanxingDemo4 {
public static void main(String[] args) {
// 通配符 ? 代表任意类型
// <? extends Car> 代表 Car 或 Car 的子类,即上限通配符
// <? super Car> 代表 Car 或 Car 的父类,即下限通配符
ArrayList<BMW> bmws = new ArrayList<>();
ArrayList<Benz> benzs = new ArrayList<>();
go(bmws);
go(benzs);
}
public static void go(ArrayList<? extends Car> cars) {
for (Car car : cars) {
System.out.println(car + "is running");
}
}
}
class Car {}
class BMW extends Car {}
class Benz extends Car {}
包装类
java
package com.popo.fanxingdemo;
import java.util.ArrayList;
public class BaoZhuangLei {
public static void main(String[] args) {
// 包装类
// 泛型容器不支持基本数据类型,只能支持包装类
Integer i = 10; // 自动装箱
int j = i; // 自动拆箱
ArrayList<Integer> list = new ArrayList<>();
list.add(120); // 自动装箱
int m = list.get(0); // 自动拆箱
Integer k = Integer.valueOf(10); // 手动装箱
// 把字符串转换为对应的真实数据类型
Integer v = Integer.valueOf("123");
Double d = Double.valueOf("123.45");
}
}
3.集合
集合分为:单列集合Collection、双列集合Map
Collection集合
Collection分为List和Set
Collection的常用方法
java
package com.popo.collectiondemo;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo1 {
public static void main(String[] args) {
// Collection的常用方法
Collection<String> collection = new ArrayList<>();
// 1. 添加元素
collection.add("Hello");
collection.add("World");
collection.add("Java");
// 2. 获取元素个数
System.out.println(collection.size());
// 3. 移除元素
collection.remove("Hello");
// 4. 是否包含某个元素
System.out.println(collection.contains("World"));
// 5. 是否为空
System.out.println(collection.isEmpty());
// 6. 转为数组
Object[] array = collection.toArray();
// 7. 清空集合
collection.clear();
}
}
Collection的三种遍历
java
package com.popo.collectiondemo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo2 {
public static void main(String[] args) {
// Collection的三种遍历
Collection<String> collection = new ArrayList<>();
collection.add("Hello");
collection.add("World");
collection.add("Java");
// 1.迭代器遍历
Iterator<String> iterator = collection.iterator();
// hasNext() 一开始指向第一个元素,判断当前元素是否存在
// next() 获取当前元素,并将迭代器指向下一个元素
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
// 2.增强for循环遍历
for (String element : collection) {
System.out.println(element);
}
// 3.lambda表达式遍历
collection.forEach(System.out::println);
// collection.forEach(s -> System.out.println(s));
// collection.forEach(new Consumer<String>() {
// @Override
// public void accept(String s) {
// System.out.println(s);
// }
// });
}
}
并发修改异常
java
package com.popo.collectiondemo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo3 {
public static void main(String[] args) {
// 并发修改异常
Collection<String> collection = new ArrayList<>();
collection.add("Hello");
collection.add("Java");
collection.add("World");
collection.add("Java");
collection.add("Java");
// 1.迭代器遍历可以安全地删除元素
Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()) {
if (iterator.next().equals("Java"))
iterator.remove();
}
System.out.println(collection);
// 2.增强for循环遍历,不能安全地删除元素
// 增强for基于迭代器,但是拿不到迭代器的remove方法
// 迭代器向前,元素删除后左移,会产生错位,抛出异常
for (String element : collection) {
if (element.equals("Java"))
collection.remove(element);
}
System.out.println(collection);
// 3.lambda表达式遍历,不能安全地删除元素
// lambda基于增强for,也会抛异常
collection.forEach(s -> { if (s.equals("Java")) collection.remove(s); });
System.out.println(collection);
}
}
List集合
ArrayList的常用方法
java
package com.popo.listdemo;
import java.util.ArrayList;
import java.util.List;
public class ListDemo1 {
public static void main(String[] args) {
// ArrayList的常用方法
List<String> names = new ArrayList<>();
// ArrayList基于数组实现,根据索引访问元素快,但插入和删除元素慢
// 1. 添加元素
names.add("Alice");
names.add("Bob");
names.add("Charlie");
// 2. 获取元素
String firstElement = names.get(0);
System.out.println(firstElement);
// 3. 删除元素
names.remove(0);
// 4. 修改元素
names.set(0, "David");
}
}
LinkedList的常用方法
java
package com.popo.listdemo;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListDemo2 {
public static void main(String[] args) {
// LinkedList的常用方法
LinkedList<String> names = new LinkedList<>();
// LinkedList基于双向链表实现,插入和删除元素快,但根据索引访问元素慢
// 且针对头尾元素设计了特殊的方法
// // LinkedList实现队列
// // 入队
// names.addLast("Alice");
// names.addLast("Bob");
// names.addLast("Charlie");
// System.out.println(names);
// // 出队
// System.out.println(names.removeFirst());
// System.out.println(names.removeFirst());
// System.out.println(names);
// LinkedList实现栈
// 入栈 addFirst
names.push("Alice");
names.push("Bob");
names.push("Charlie");
System.out.println(names);
// 出栈 removeFirst
System.out.println(names.pop());
System.out.println(names.pop());
System.out.println(names);
}
}
Set集合
HashSet
java
package com.popo.setdemo;
import java.util.HashSet;
public class HashSetDemo1 {
public static void main(String[] args) {
// HashSet的底层基于哈希表:数组+链表+红黑树
// 每个对象都有哈希值,数组的初始容量为16,用哈希值对16取余,把对象存到取余的索引位置
// 如果哈希值取余的索引相同,则把对象追加到同一索引位置的链表中
// 如果哈希值相同,再用equals比较,如果返回true,则不存入,否则存入
// 如果数组长度>=64,且链表的元素个数>=8,则把链表转换为红黑树(平衡二叉排序树)
// 所以HashSet的特点是:无序、不重复、无索引
String str1 = "Hello";
String str2 = "World";
System.out.println(str1.hashCode()); // 69609650
System.out.println(str2.hashCode()); // 83766130
// HashSet的常用方法
HashSet<String> set = new HashSet<>();
// 1. 添加元素
set.add("Alice");
set.add("Alice");
set.add("Bob");
set.add("Charlie");
System.out.println(set); // [Bob, Alice, Charlie]
// 2. 删除元素
set.remove("Bob");
System.out.println(set); // [Alice, Charlie]
// 3. 判断元素是否存在
boolean contains = set.contains("Charlie");
System.out.println(contains); // true
}
}
HashSet的去重
java
package com.popo.setdemo;
import java.util.HashSet;
import java.util.Objects;
public class HashSetDemo2 {
public static void main(String[] args) {
// HashSet的去重
// 认为:只要学生的三个属性相同,则认为是同一个学生
// 下面的写法,因为重复学生的hashcode()不同,equals()返回false,所以不会去重
// HashSet<Student> set = new HashSet<>();
// set.add(new Student("Alice", 18, 1));
// set.add(new Student("Alice", 18, 1));
// set.add(new Student("Bob", 19, 2));
// set.add(new Student("Charlie", 20, 3));
// set.add(new Student("Charlie", 20, 3));
// System.out.println(set);
// 所以要重写Student类的hashcode()和equals()方法
// 相同属性的学生,计算出的hashcode()相同,equals()返回true
HashSet<Student> set = new HashSet<>();
set.add(new Student("Alice", 18, 1));
set.add(new Student("Alice", 18, 1));
set.add(new Student("Bob", 19, 2));
set.add(new Student("Charlie", 20, 3));
set.add(new Student("Charlie", 20, 3));
System.out.println(set);
}
}
class Student {
private String name;
private int age;
private int id;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && id == student.id && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, id);
}
public Student() {
}
public Student(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}' + '\n';
}
}
LinkedHashSet
java
package com.popo.setdemo;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
public class LinkedHashSetDemo3 {
public static void main(String[] args) {
// LinkedHashSet的特点:有序、不重复、无索引
// LinkedHashSet的底层:哈希表+双向链表
// 每个元素都额外多了两个指针,分别指向插入顺序的前一个元素和后一个元素
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("hello");
linkedHashSet.add("world");
linkedHashSet.add("hello");
System.out.println(linkedHashSet);
}
}
TreeSet
java
package com.popo.setdemo;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.TreeSet;
public class TreeSetDemo4 {
public static void main(String[] args) {
// TreeSet的特点:默认升序、不重复、无索引、基于红黑树
// 当元素为自定义类时,要么在元素类中实现Comparable接口
// 要么在创建TreeSet对象时传入Comparator对象
TreeSet<Teacher> ts = new TreeSet<>(new Comparator<Teacher>() {
@Override
public int compare(Teacher o1, Teacher o2) {
// 按工资升序
return Double.compare(o1.getSalary(), o2.getSalary());
}
});
ts.add(new Teacher("Alice", 25, 5000.4));
ts.add(new Teacher("Bob", 30, 6000.6));
ts.add(new Teacher("Charlie", 35, 7000.7));
ts.add(new Teacher("David", 25, 8000.8));
System.out.println(ts);
}
}
class Teacher implements Comparable<Teacher> {
private String name;
private int age;
private double salary;
@Override
public int compareTo(Teacher o) {
// 按年龄升序,如果年龄相同则视为重复元素
return this.age - o.age;
}
public Teacher() {
}
public Teacher(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public double getSalary() {
return salary;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}' + '\n';
}
}
Map集合
Map的常用方法
java
package com.popo.mapdemo;
import java.util.HashMap;
import java.util.Map;
public class MapDemo1 {
public static void main(String[] args) {
// 常用的Map实现类
// 1. HashMap:关键字无序,不重复,无索引
// 2. LinkedHashMap:关键字有添加的先后顺序,不重复,无索引
// 3. TreeMap:关键字升序,不重复,无索引
// Map的常用方法
Map<String, Integer> map = new HashMap<>();
// 1. put(key, value):添加元素
map.put("Alice", 25);
map.put("Bob", 30);
map.put("Charlie", 35);
map.put("David", 40);
System.out.println(map);
// 2. get(key):根据关键字获取值
System.out.println(map.get("Alice"));
// 3. remove(key):根据关键字删除元素
map.remove("Bob");
System.out.println(map);
// 4. containsKey(key):判断是否包含某个关键字
System.out.println(map.containsKey("Charlie"));
// 5. containsValue(value):判断是否包含某个值
System.out.println(map.containsValue(40));
// 6. size():获取Map的大小
System.out.println(map.size());
// 7. isEmpty():判断Map是否为空
System.out.println(map.isEmpty());
// 8. keySet():获取所有关键字的集合
System.out.println(map.keySet());
// 9. values():获取所有值的集合
System.out.println(map.values());
// 10. clear():清空Map
map.clear();
System.out.println(map);
}
}
Map的三种遍历
java
package com.popo.mapdemo;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
public class MapDemo2 {
public static void main(String[] args) {
// Map的三种遍历
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 25);
map.put("Bob", 30);
map.put("Charlie", 35);
map.put("David", 40);
// 1. 键找值
for (String key : map.keySet()) {
System.out.println(key + "=" + map.get(key));
}
// 2. 增强for循环
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
// 3. lambda表达式
map.forEach((key, value) -> System.out.println(key + "=" + value));
// map.forEach(new BiConsumer<String, Integer>() {
// @Override
// public void accept(String key, Integer value) {
// System.out.println(key + "=" + value);
// }
// });
}
}
set集合都是基于map集合实现的,只是不用存储值

4.Stream流
Stream流提供了很多lambda调用,可以链式完成集合的数据处理
stream流的使用
java
package com.popo.streamdemo;
import java.util.ArrayList;
import java.util.List;
public class StreamDemo1 {
public static void main(String[] args) {
// stream流的使用
List<String> list = new ArrayList<>();
list.add("Alice");
list.add("Amy");
list.add("Aby");
list.add("Bob");
// 得到A开头且长度为3的元素
list.stream()
.filter(s -> s.startsWith("A"))
.filter(s -> s.length() == 3)
.forEach(System.out::println);
}
}
获取stream流
java
package com.popo.streamdemo;
import java.util.*;
import java.util.stream.Stream;
public class StreamDemo2 {
public static void main(String[] args) {
// 获取stream流
// 1. 通过集合.stream()获取stream流
List<String> list = new ArrayList<>();
Stream<String> s1 = list.stream();
Map<String, Integer> map = new HashMap<>();
Stream<String> sk = map.keySet().stream();
Stream<Integer> sv = map.values().stream();
Stream<Map.Entry<String, Integer>> s2 = map.entrySet().stream();
// 2. 通过Arrays.stream()获取stream流
String[] arr = {"Alice", "Bob", "Charlie"};
Stream<String> s3 = Arrays.stream(arr);
// 3. 通过Stream.of()获取stream流
Stream<String> s4 = Stream.of(arr);
}
}
stream流的常用中间方法
java
package com.popo.streamdemo;
import java.util.*;
import java.util.stream.Stream;
public class StreamDemo3 {
public static void main(String[] args) {
// stream流的常用中间方法
List<Integer> list = new ArrayList<>();
list.add(11);
list.add(12);
list.add(12);
list.add(32);
list.add(14);
list.add(14);
list.add(52);
// 1. filter 过滤
list.stream()
.filter(s -> s / 10 == 1)
.forEach(System.out::println);
// 2. limit 截取
list.stream()
.limit(2)
.forEach(System.out::println);
// 3. skip 跳过
list.stream()
.skip(2)
.forEach(System.out::println);
// 4. distinct 去重
list.stream()
.distinct()
.forEach(System.out::println);
// 5. sorted 排序
list.stream()
.sorted()
.forEach(System.out::println);
// 6. sorted 降序
list.stream()
.sorted((o1, o2) -> o2 - o1)
.forEach(System.out::println);
// 7. map 映射 对每个元素加工
list.stream()
.map(s -> s * 2)
.forEach(System.out::println);
// 8. concat 连接
List<String> list2 = new ArrayList<>();
list2.add("Alice");
list2.add("Bob");
Stream<Integer> s1 = list.stream();
Stream<String> s2 = list2.stream();
Stream<Object> s3 = Stream.concat(s1, s2);
s3.forEach(System.out::println);
}
}
stream流的常用终结方法
java
package com.popo.streamdemo;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class StreamDemo4 {
public static void main(String[] args) {
// stream流的常用终结方法,即不再返回stream流
List<Integer> list = new ArrayList<>();
list.add(11);
list.add(12);
list.add(12);
list.add(32);
list.add(14);
list.add(14);
list.add(52);
// 1. forEach 迭代器走到了最后面
list.stream().filter(s -> s / 10 == 1).forEach(System.out::println);
// 2. count 统计个数
long count = list.stream().filter(s -> s / 10 == 1).count();
// 3. max 最大值
Optional<Integer> max = list.stream().max(Integer::compare);
Integer maxInt = max.get();
// 4. min 最小值
Optional<Integer> min = list.stream().min(Integer::compare);
Integer minInt = min.get();
}
}
stream流的常用收集方法
java
package com.popo.streamdemo;
import java.util.*;
import java.util.stream.Collectors;
public class StreamDemo5 {
public static void main(String[] args) {
// stream流的常用终结方法,收集到集合中
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Amy");
names.add("Amy");
names.add("Aby");
names.add("Bob");
// 1. 收集到List
List<String> a = names.stream()
.filter(s -> s.startsWith("A"))
.collect(Collectors.toList());
System.out.println(a);
// 2. 收集到Set
Set<String> b = names.stream()
.filter(s -> s.startsWith("A"))
.collect(Collectors.toSet());
System.out.println(b);
// 3. 收集到数组
Object[] c = names.stream()
.filter(s -> s.startsWith("A"))
.toArray();
System.out.println(Arrays.toString(c));
// 4. 收集到Map
List<Teacher> ts = new ArrayList<>();
ts.add(new Teacher("Alice", 25, 5000.4));
ts.add(new Teacher("Bob", 30, 6000.6));
ts.add(new Teacher("Charlie", 35, 7000.7));
ts.add(new Teacher("David", 25, 8000.8));
Map<String, Double> d = ts.stream()
.collect(Collectors.toMap(Teacher::getName, Teacher::getSalary));
System.out.println(d);
}
}
class Teacher {
private String name;
private int age;
private double salary;
public Teacher() {
}
public Teacher(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public double getSalary() {
return salary;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}' + '\n';
}
}
可变长参数
java
package com.popo.streamdemo;
public class KeBianCanShu {
public static void main(String[] args) {
// 可变长参数就是一个数组,只能有一个,且要放到最后
getNums(18);
getNums(18, 1, 2, 3, 4, 5);
}
public static void getNums(int age, int... nums) {
System.out.println("age = " + age);
for (int i = 0; i < nums.length; i++) {
System.out.println("nums[" + i + "] = " + nums[i]);
}
}
}
Collections提供的静态方法
java
package com.popo.streamdemo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsDemo6 {
public static void main(String[] args) {
// Collections提供的静态方法
// 1. 批量添加元素
List<String> names = new ArrayList<>();
Collections.addAll(names, "Alice", "Bob", "Charlie");
System.out.println(names);
// 2. 打乱顺序
Collections.shuffle(names);
System.out.println(names);
// 3. 排序
Collections.sort(names);
System.out.println(names);
// 4. 降序
Collections.sort(names, (a, b) -> b.compareTo(a));
System.out.println(names);
}
}