Java学习
一个java程序的编写
模块->软件包->类
java主要是利用函数调用进行程序执行,主函数调用其他函数(类似于C++)

1 2 3 4 5 6 7 8 9 10 11
| public class functionBasic { public static void main(String[] args) { int a = 10; int b = 20; int c = sum(a,b); System.out.println(c); } public static int sum(int a, int b){ return a+b; } }
|
java类似C++的方法重载

重载的意义在于使一个函数实现多种功能以及方便记忆
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class chongzai { public static void main(String[] args) { System.out.println("这是重载"); fire(); fire(99); fire(100,99); } public static void fire(){ System.out.println("发射导弹"); } public static void fire(int a){ System.out.println("发射导弹"+a+"个"); } public static void fire(int a,int b){ System.out.println("坐标x:"+a+",y:"+b); } }
|
Java的类型转换(自动与强制)
自动类型转换

强制类型转换

表达式的自动类型提升

Java的输入和输出


1 2 3 4 5 6 7 8 9 10 11
| public class testScanner { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入一个整数:"); int a = sc.nextInt(); System.out.println("您输入的整数是:" + a); System.out.println("您的名字是:"); String name = sc.next(); System.out.println("您的名字是:" + name); } }
|
java运算符和C++的区别
运算符类型 |
C++ 特性 |
Java 特性 |
赋值运算符 |
支持重载 |
不支持重载,仅基本类型和引用赋值 |
三元运算符 |
允许隐式类型转换 |
严格类型兼容 |
逻辑运算符 |
接受非布尔类型(隐式转换) |
必须为 boolean 类型 |
java的boolean和C++的bool
boolean
在 Java 中是一个关键字,它定义了一个逻辑值类型,用来表示逻辑状态。与其他原始数据类型不同,boolean
只有两个固定的值:true
和 false
,用于逻辑判断、条件判断等。
boolean和C++的bool不同的是boolean不允许与其他类型进行隐式转换,也就是boolean只能等于true或者false,不能等于1或0
Java分支、循环结构和C++的区别
特性 |
C++ |
Java |
if 条件类型 |
允许隐式转换为 bool (如 int ) |
必须为 boolean 类型 |
switch 类型 |
整型、枚举 |
整型、String 、枚举等 |
case 值 |
常量表达式 |
编译时常量 |
for-each 循环 |
基于范围的 for |
需实现 Iterable 接口 |
goto |
支持 |
不支持 |
标签跳转 |
支持(少用) |
支持(明确用于多层循环) |
java数组和C++区别
特性 |
Java 数组 |
C++ 数组 |
内存分配 |
堆内存,GC 管理 |
栈或堆,手动管理堆内存 |
类型安全 |
严格类型检查 |
弱类型检查(可通过指针绕过) |
多维数组 |
数组的数组(支持不规则) |
连续内存块(固定维度) |
长度获取 |
arr.length |
需手动维护或计算(栈数组用 sizeof ) |
越界检查 |
抛出异常 |
无检查,导致未定义行为 |
动态调整大小 |
不可变,需借助集合类 |
堆数组可手动重新分配 |
语法初始化 |
支持直接初始化 {1, 2, 3} |
栈数组支持 {} 初始化(C++11+),堆数组需 new |
语法差异:
声明与初始化:
Java:
1 2
| int[] arr1 = new int[3]; int[] arr2 = {1, 2, 3};
|
**C++**:
1 2 3
| int arr1[3]; int arr2[] = {1, 2, 3}; int* arr3 = new int[3];
|
java的类和对象
创建类和对象的语法和C++一样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package CreatClass;
public class LearnCreat { public static void main(String[] args) { class CreatClass { private String name; private int age; private String sex; } CreatClass creatClass = new CreatClass(); creatClass.name="张三"; creatClass.age=18; creatClass.sex="男"; System.out.println(creatClass.name); System.out.println(creatClass.age); System.out.println(creatClass.sex); } }
|

java的构造器就是C++的类函数(方法)
注意:java的有参构造器创建了。默认的无参构造器就没有了,如果想用有参构造器,就必须自己写一个出来
java的this和C++的也是一样
this
回顾this的作用:解决对象属性和类函数的参数名冲突的问题
1 2 3 4 5 6 7 8 9
| package yyssh.LearnClass;
public class testItem { public static void main(String[] args) { itemDemo s1 = new itemDemo("yanyuan", 18); s1.print(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package yyssh.LearnClass;
public class itemDemo { String name; int age; public itemDemo(){
} public itemDemo(String name,int age){ this.name = name; this.age = age; } public void print(){ System.out.println("姓名:"+name+"年龄:"+age); } }
|
java的封装和C++一样,都是先赋值类函数,再取值类函数
static
java的static和C++一样,下面回顾一样static,static是属于类的公共成员变量,所有的对象都可以访问,作用是统计公共数据的变化等等
java:工具类私有化构造器,使用静态函数(方法),方便调用

1 2 3 4 5 6 7 8 9 10 11 12
| package yyssh.LearnStatic;
public class staticDemo { public static void main(String[] args) { Student s1 = new Student(); s1.SetStudent("yanyuan", 18); s1.print(); Student s2 = new Student(); s2.SetStudent("chenzhuang", 19); Student.printStudentCount(); } }
|
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
| package yyssh.LearnStatic;
public class Student { private String name; private int age; private static int StudentCount; public Student(){ StudentCount++; } public void SetStudent(String name,int age){ this.name=name; this.age=age; } public int GetStudent(){ return this.age; } public String GetName(){ return this.name; } public void print(){ System.out.println("姓名:"+this.name+"年龄:"+this.age); } public static void printStudentCount(){ System.out.println("学生人数:"+StudentCount); } }
|
继承
大致含义和C++的一样,都是只能继承父类的非私有成员和方法
java语法:
1
| public class A extends B
|
继承权限
private<缺省<protected<public
private 本类
缺省 本类、同一个包中的类
protected 本类、同一个包中的类、子孙类中
public 任意位置
java继承特点:单继承,不支持多继承(不能有多个父类)、支持多层继承(可以有爷类)
子类重写父类函数,名称、形参列表必须一样,访问权限要大于父类权限,私有和静态不能被重写

super()
:调用父类构造器
super和this构造器都只能放在函数第一行,两者不能同时出现
多态
java的多态,要在重写函数的上一行加上@Override

类方法:编译看父类,运行看子类
成员变量:编译、运行都看父类
多态下的一个问题,怎么调用子类独有的方法?
这个子类特有方法必须是重写父类的方法,才可以使用自动类型转换调用,如果是子类完全特有的,则只能强制类型转换

1 2 3 4 5 6 7 8
| if (a instanceof wolf){ wolf w = (wolf)a; w.run(); } else if { rabbit r=(rabbit)a; r.run(); }
|
final

1 2
| final int [] arr1={11,22,33}; arr1[1]=99;
|
java的常量

设计模式

单例设计模式
饿汉式单例:

懒汉式单例:

枚举类


枚举类构造一个枚举对象也是单例类,因为他是常量,只能进行一次赋值操作
抽象类
抽象方法的特点:
- 只能在抽象类中
- 只有方法声明,没有方法体
- 子类必须重写:如果一个类继承了含有抽象方法的抽象类,子类必须提供该抽象方法的实现,除非子类本身也被声明为抽象类。


抽象类设计模板

1 2 3 4 5 6 7 8 9 10 11
| package yyssh.LearnAbstractDemo;
public class testAbstractDemo { public static void main(String[] args) { People s1 = new Student(); s1.write(); People t1 =new Teacher(); t1.write(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| package yyssh.LearnAbstractDemo;
public abstract class People{ public final void write(){ System.out.println("我是一个人"); writemian(); System.out.println("我生活在地球"); System.out.println("-------------------------------------"); } public abstract void writemian(); }
|
1 2 3 4 5 6 7 8
| package yyssh.LearnAbstractDemo;
public class Teacher extends People{ @Override public void writemian() { System.out.println("我是一个老师"); } }
|
1 2 3 4 5 6 7 8
| package yyssh.LearnAbstractDemo;
public class Student extends People{ @Override public void writemian() { System.out.println("我是一个学生"); } }
|
接口

java接口的作用,就类似于C++可以继承多个父类


代码块

内部类

成员内部类

静态内部类
不能访问外部类的成员变量

局部内部类

匿名内部类

开发方式:

使用场景:
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
| package yyssh.innerClass;
import java.util.Comparator; import java.util.Arrays;
public class testSort { public static void main(String[] args) { Student [] students = new Student[5]; students[0] = new Student(18,"yanyuan","男"); students[1] = new Student(19,"chenzhuang","男"); students[2] = new Student(20,"zhanghao","男"); students[3] = new Student(21,"zhangjie","男"); students[4] = new Student(22,"xuziyang","男"); Arrays.sort(students,new Comparator<Student>(){ @Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge();
} }); for (int i=0; i<5; i++) { Student s = students[i]; System.out.println(s); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package yyssh.innerClass; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;
@AllArgsConstructor @NoArgsConstructor @Data
public class Student { private int age; private String name; private String sex;
}
|
Lambda表达式(函数式编程)

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
| package yyssh.learnLambda;
public class lambdaDemo { public static void main(String[] args) { Leap l = new Leap(){ @Override public void leaping() { System.out.println("leaping"); } }; l.leaping(); Swim s = ()->{ System.out.println("swimming"); }; s.swimming(); } }
@FunctionalInterface interface Swim { void swimming(); }
abstract class Leap { public abstract void leaping(); }
|

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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| package yyssh.learnLambda;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Arrays; import java.util.Comparator;
public class lambdaOmit { public static void main(String[] args) { sort(); } public static void sort(){ Student [] students = new Student[5]; students[0] = new Student(18,"yanyuan","男"); students[1] = new Student(19,"chenzhuang","男"); students[2] = new Student(20,"zhanghao","男"); students[3] = new Student(21,"zhangjie","男"); students[4] = new Student(22,"xuziyang","男");
Arrays.sort(students,(Student o1, Student o2)-> { return o1.getAge() - o2.getAge(); }); Arrays.sort(students,( o1, o2)-> { return o1.getAge() - o2.getAge(); }); Arrays.sort(students,( o1, o2)-> o1.getAge() - o2.getAge()); for (int i=0; i<5; i++) { Student s = students[i]; System.out.println(s); } } }
@AllArgsConstructor @Data @NoArgsConstructor class Student { private int age; private String name; private String sex; }
|
静态方法引用

这是正常方法
1 2 3
| Arrays.sort(students,( o1, o2)-> { return o1.getAge() - o2.getAge(); });
|
使用静态方法
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| package yyssh.learnLambda;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Arrays; import java.util.Comparator;
public class lambdaOmit { public static void main(String[] args) { sort(); } public static void sort(){ Student [] students = new Student[5]; students[0] = new Student(18,"yanyuan","男"); students[1] = new Student(19,"chenzhuang","男"); students[2] = new Student(20,"zhanghao","男"); students[3] = new Student(21,"zhangjie","男"); students[4] = new Student(22,"xuziyang","男");
Arrays.sort(students,(Student o1, Student o2)-> { return o1.getAge() - o2.getAge(); }); Arrays.sort(students,( o1, o2)-> { return o1.getAge() - o2.getAge(); }); Arrays.sort(students,( o1, o2)-> o1.getAge() - o2.getAge()); Arrays.sort(students,Student::compare); for (int i=0; i<5; i++) { Student s = students[i]; System.out.println(s); } } }
@AllArgsConstructor @Data @NoArgsConstructor class Student { private int age; private String name; private String sex; public static int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } }
|
实例方法引用

1 2 3 4
| Student t = new Student(); Arrays.sort(students,( o1, o2)->t.compareHeight(o1,o2)); Arrays.sort(students,t::compareHeight);
|
特定类型引用

这里的特定类型是指lambda 表达式所实现的函数式接口的具体类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package yyssh.lambdaOmitDemo;
import java.util.Arrays; import java.util.Comparator;
public class Demo { public static void main(String[] args) { String [] names = {"Alies","ailiy","Bob","曹操","张飞","CaoCao"};
Arrays.sort(names, String::compareToIgnoreCase); System.out.println(Arrays.toString(names)); } }
|
构造器引用

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
| package yyssh.lambdaOmitDemo;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;
public class Demo2 { public static void main(String[] args) {
CarFactory cf = Car::new; Car c1 = cf.getCar("Benz"); System.out.println(c1.getBrand()); } }
@FunctionalInterface interface CarFactory { Car getCar(String brand); }
@AllArgsConstructor @Data @NoArgsConstructor class Car { private String brand; }
|
常用的库
Lombok
检查模块依赖
- 打开 IntelliJ IDEA,进入 File > Project Structure > Modules,确认每个模块的 Dependencies 选项卡中包含 Lombok。
- 如果缺少,可以手动添加或确保 Maven/Gradle 已同步。
启用注解处理
- 进入 Settings > Build, Execution, Deployment > Compiler > Annotation Processors,勾选 “Enable annotation processing” 和 “Obtain processors from project classpath”。
- 这确保 Lombok 的注解处理器能被正确识别。
@AllArgsConstructor
- 作用:生成一个包含所有字段的构造函数(即所有成员变量的初始化构造函数)。
- 引用:
import lombok.AllArgsConstructor
@Data
@NoArgsConstructor
- 作用:生成一个无参构造函数。
- 引用:
import lombok.NoArgsConstructor
java类和对象与C++的区别
特性 |
Java |
C++ |
类定义 |
所有代码必须在类中 |
允许全局函数和类外代码 |
对象存储 |
堆内存(GC 管理) |
栈或堆(手动管理) |
继承 |
单继承 + 接口多继承 |
支持多重继承 |
多态 |
所有方法默认是虚函数(除非 final ) |
需显式声明 virtual |
内存管理 |
自动垃圾回收 |
手动 new /delete |
访问控制 |
支持包级私有 |
无包级私有 |
静态成员 |
类内直接初始化 |
需类外初始化 |
Java的API学习.
String

String提供的常用方法

ArrayList

Java中的API和C++、python有什么异同
特性 |
Java |
C++ |
Python |
内存管理 |
自动垃圾回收 |
手动管理(new /delete ) |
自动垃圾回收 |
类型系统 |
静态类型,强类型检查 |
静态类型,弱类型检查(可强制转换) |
动态类型,运行时检查 |
API 调用方式 |
通过类方法、接口 |
通过函数、类方法、运算符重载 |
通过函数、模块、动态类型 |
跨平台性 |
字节码(JVM) |
需重新编译为平台特定机器码 |
解释执行(如 CPython) |
代码复杂度 |
严格的面向对象结构 |
支持多范式(面向对象、过程式) |
灵活,支持函数式编程 |
典型应用场景
- Java:适合企业级应用(如 Spring 框架的 RESTful API)、Android 开发,依赖成熟的生态系统(如 Maven、JUnit)916。
- **C++**:适用于高性能计算(如游戏引擎、操作系统底层 API)、资源敏感场景(如嵌入式系统)510。
- Python:快速原型开发(如 Flask/Django 的 Web API)、数据科学(如 NumPy、Pandas),依赖简洁语法和丰富库支持313。
Java的异常


使用快捷键(alt+回车
)可以快速将异常抛出,异常统称exception和python是一样的,可以用这个关键字接收所有异常,java异常是层级抛出的,在最初调用的main函数进行异常处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package yyssh.exceptionDemo;
public class exceptionDemo1 { public static void main(String[] args) { try { System.out.println(test(15,0)); } catch (Exception e) { System.out.println(e.getMessage()); System.out.println("程序异常"); e.printStackTrace(); } System.out.println("程序结束"); System.exit(0); } public static int test(int a,int b) throws Exception { int result =a/b; if (b==0){ throw new Exception("除数不能为0"); } return result; } }
|

尽量定义运行时异常,编译时异常正在被全面放弃,因为编译时异常需要层级上抛需要每层进行处理或者上抛,资源消耗大
异常的解决方案
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
| package yyssh.exceptionDemo2;
import java.util.Scanner;
public class exceptionDemo2 { public static void main(String[] args) { System.out.println("程序开始"); while (true) { try { UserInputPrice(); System.out.println("用户输入成功!!!"); break; } catch (Exception e) { System.out.println("你的输入有问题,请输入正常的价格"); } } System.out.println("程序结束"); } public static double UserInputPrice() { Scanner sc = new Scanner(System.in); System.out.println("请输入商品的价格:"); double price = sc.nextDouble(); return price; } }
|
java的异常和C++、python有什么异同
特性 |
Java |
C++ |
Python |
异常传播 |
检查型异常必须处理或声明 |
异常可跨函数传播,无需声明 |
异常自动传播,无需声明 |
性能开销 |
较高(因堆栈跟踪生成) |
低(无运行时类型检查) |
较高(动态类型和堆栈跟踪) |
错误恢复 |
支持完整的异常链(cause 属性) |
仅支持基本异常信息 |
支持异常链(raise ... from ... ) |
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
| package yyssh.knowGenerics;
import java.util.ArrayList;
public class knowGenerics { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add(1); list.add("yyssh"); list.add(true); list.add(new Object()); for (Object o : list) { System.out.println(o); } ArrayList<String> StringList = new ArrayList<>(); StringList.add("yyssh"); for (String s : StringList) { System.out.println(s); } } }
|
shift+f6
一键式改名
泛型类和接口


泛型的方法、通配符和上下限

泛型的包装类
Java为了灌输它的万物皆对象的理念,只允许泛型传入的数据是对象,而不能传入基本数据类型,所以包装类也就应运而生,包装类就是将基本数据类型转换为对象

其实第二种方法也不是经常使用可以直接将两者进行转换看,因为java内置了一个自动装箱(自动把int转换为Integer)和自动拆箱(自动把Integer转换为int)的功能
但是这种方法没有被程序员认可,所以sun公司提供了包装类的两个好用的API

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
| package yyssh.genericsPack;
import java.util.ArrayList;
public class PackClass { public static void main(String[] args) { ArrayList <Integer> list = new ArrayList<>(); list.add(123); list.add(456); for (Integer integer : list) { System.out.println(integer); } Integer i =123; System.out.println(i); int j=i; System.out.println(j); System.out.println(i==j); String name = i.toString(); System.out.println(name); String is = i+""; System.out.println(is); System.out.println(is.getClass()); String a = "123"; String c = "456"; Integer b = Integer.parseInt(a); Integer d = Integer.valueOf(c); System.out.println(b); System.out.println(b.getClass()); System.out.println(d); System.out.println(d.getClass()); } }
|
java的泛型和C++、python有什么异同
特性 |
Java 泛型 |
C++ 模板 |
Python 类型系统 |
类型检查时机 |
编译时 |
编译时 |
运行时(类型提示为静态检查工具服务) |
实现机制 |
类型擦除 |
代码实例化 |
动态类型 + 类型提示 |
支持基本类型 |
需装箱(如 Integer ) |
直接支持(如 int ) |
无泛型,直接支持所有类型 |
类型约束 |
显式边界(extends ) |
隐式约束(操作符/方法存在性) |
鸭子类型 |
代码复用灵活性 |
高(类型安全) |
极高(支持元编程) |
极高(动态特性) |
java的集合
collection集合的特点

collection常用方法

collection的遍历方法:迭代器遍历

collection的遍历方法:for循环遍历

collection的遍历方法:lambda遍历

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 40 41 42 43 44 45 46
| package yyssh.knowCollection;
import java.util.ArrayList; import java.util.List; import java.util.Iterator; import java.util.function.Consumer;
public class CollectionDemo1 { public static void main(String[] args) { List<String> list =new ArrayList<>(); list.add("123"); list.add("yyssh"); list.add("yanyuan"); list.add("chenzhuang"); list.add("张浩");
Iterator<String> iterator = list.iterator(); while(iterator.hasNext()){ String s = iterator.next(); System.out.println(s); } System.out.println("-------------------------------------------------------");
for (String s : list) { System.out.println(s); } System.out.println("-------------------------------------------------------");
list.forEach(s-> System.out.println(s)); System.out.println("--------------------------------------------------------"); list.forEach(System.out::println); System.out.println(System.out.getClass()); } }
|
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
| import java.util.ArrayList; import java.util.List;
public class circleDemo1 { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("金龙"); list.add("木龙"); list.add("水龙"); list.add("火龙"); list.add("土龙"); list.add("龙虾"); list.add("龙王"); list.add("男人"); list.add("女人"); for (int i=0;i< list.size();i++) { String name = list.get(i); if (name.contains("龙")){ list.remove(i); } } System.out.println(list); } }
|
可以看到含有龙的字样并没有被删除完全,这里我们可以采取两种解决方案
方案一:
将for循环,进行i–,因为每删除一个就会漏掉一个,那我就回退一个就可以解决这个问题
for (int i=0;i< list.size();i++) {
String name = list.get(i);
if (name.contains("龙")){
list.remove(i);
i--;
}
}
1 2 3 4 5 6 7 8 9 10 11 12
| + 方案二:
+ 使用倒序循环,将不存在漏掉情况
+ ```java for (int i= list.size()-1;i>=0;i String name = list.get(i); if (name.contains("龙")){ list.remove(i); } }
|
这前面两个例子是为了说明在有索引的情况下是可以采用上面方案解决并发异常问题的,但是如果没有索引的话,例如Set集合,就无法采用上面的方案进行删除,只能采用迭代器自带的删除功能进行删除
1 2 3
| for (String name : list){ System.out.println(name); }
|
1 2
| list.forEach(System.out::println);
|
都无法进行索引,也无法进行并发操作,只有迭代器可以
1 2 3 4 5 6 7 8
| Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ String name = iterator.next(); if (name.contains("龙")){ iterator.remove(); } } System.out.println(list);
|

ArrayList底层原理
ArrayList的扩容原理是基于数组存储数据的,查询数据效率高,但是增减效率慢,第一次扩容10个长度,以后每一次扩容1.5倍
LinkedList底层原理
LinkedLIst底层是基于双链表存储数据的,查询效率慢,无论查询哪个数据都要从头或者尾(双向链表)开始找,增删速率高
java为LinkedList增加了许多对于首尾操作的方法
LinkedList的应用场景队列和栈
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
| package yyssh.applyLinkedListDemo1;
import java.util.List; import java.util.LinkedList;
public class LinkedListDemo1 { public static void main(String[] args) { LinkedList<String> queue = new LinkedList<>(); queue.addLast("张三"); queue.addLast("李四"); queue.addLast("王五"); queue.addLast("赵六");
for (int i=0;i<queue.size();i++){ System.out.println(queue.removeFirst()); i--; }
System.out.println("------------------------------------------------------------------");
LinkedList<String> stack = new LinkedList<>(); stack.push("张三"); stack.push("李四"); stack.push("王五"); stack.push("赵六");
for (int i=0;i<stack.size();i++){ System.out.println(stack.pop()); i--; } } }
|
Set集合

java的哈希表
JDK8之前,哈希表=数组+链表
JDK8之后,哈希表=数组+链表+红黑树
哈希表是一种增删改查数据效率都比较高的数据结构


HashSet集合对象去重操作
HashSet虽然是不重复的,但是对象之间如果数据完全相等,但对象之间的hash值不一定相等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package yyssh.hashset;
import java.util.Set; import java.util.HashSet;
public class HashSetSingle { public static void main(String[] args) { Set<Student> Students = new HashSet<>(); Students.add(new Student("yanyuan", 21, 100, 1, "男", "北京", "123456789")); Students.add(new Student("chenzhuang", 18, 91, 2, "男", "北京", "123456789")); Students.add(new Student("zhanghao", 20, 95, 3, "男", "北京", "123456789")); Students.add(new Student("zhangjie", 39, 88, 4, "男", "北京", "123456789")); Students.add(new Student("chenzhuang", 18, 91, 2, "男", "北京", "123456789")); Students.add(new Student("zhanghao", 20, 95, 3, "男", "北京", "123456789"));
for (Student s : Students) { System.out.println(s); } } }
|
学生类:
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| package yyssh.hashset;
import java.util.Objects;
public class Student { private String name; private int age; private int score; private int id; private String sex; private String address; private String phone;
public Student(String name, int age, int score, int id, String sex, String address, String phone) { this.name = name; this.age = age; this.score = score; this.id = id; this.sex = sex; this.address = address; this.phone = phone; }
@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 && score == student.score && id == student.id && Objects.equals(name, student.name) && Objects.equals(sex, student.sex) && Objects.equals(address, student.address) && Objects.equals(phone, student.phone); }
@Override public int hashCode() { return Objects.hash(name, age, score, id, sex, address, phone); }
@Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + ", id=" + id + ", sex='" + sex + '\'' + ", address='" + address + '\'' + ", phone='" + phone + '\'' + '}'+'\n'; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public int getScore() { return score; }
public void setScore(int score) { this.score = score; }
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getSex() { return sex; }
public void setSex(String sex) { this.sex = sex; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; } }
|
主要在于equals和hashCode两个方法,但是sun公司都帮你写好了,直接调用就可以了,原理就是hashset集合存储数据要经过两个比较,一个是hashcode算hash值,一个是equals比较实际值
TreeSet集合自定义类型对象排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package yyssh.TreeSet;
import java.util.Comparator; import java.util.Set; import java.util.TreeSet;
public class TreeSetDemo1 { public static void main(String[] args) {
Set<Teacher> teachers =new TreeSet<>(( o1, o2)->Double.compare(o1.getSalary(), o2.getSalary())); teachers.add(new Teacher("yanyuan", 21, "男", 9009.9)); teachers.add(new Teacher("chenzhuang", 18, "男", 10010.4)); teachers.add(new Teacher("zhanghao", 20, "男", 10009.9)); teachers.add(new Teacher("zhangjie", 39, "男", 99999.9)); teachers.add(new Teacher("huangzhenbao", 18, "男", 199999.9)); System.out.println(teachers); } }
|
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
| package yyssh.TreeSet;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;
@Data @NoArgsConstructor @AllArgsConstructor
public class Teacher { private String name; private int age; private String sex; private double salary;
@Override public String toString() { return "Teacher{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + ", salary=" + salary + '}'+'\n'; } }
|
集合的选择
- 如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据?
- 用ArrayList集合(有序、可重复、有索引),底层基于数组的(常用)。
- 如果希望记住元素的添加顺序,且增删首位数据的情况较多?
- 用LinkedList集合(有序、可重复、有索引),底层基于双链表的。
- 如果不在意元素顺序,也没有重复元素需要存储,只希望增删改查都快?
- 用HashSet集合(无序、不重复、无索引),底层基于哈希表实现的。(常用)
- 如果希望记住元素的添加顺序,也没有重复元素需要存储,且希望增删改查都快?
- 用LinkedHashSet集合(有序、不重复、无索引),底层基于哈希表和双链表。
- 如果要对元素进行排序,也没有重复元素需要存储?且希望增删改查都快?
Map集合

Map集合的常用方法

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package yyssh.LearnMapFunction;
import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set;
public class MapDemo1 { public static void main(String[] args) { Map<String, Integer> maps = new HashMap<>(); maps.put("张三", 18); maps.put("王五", 19); maps.put("赵六", 20); System.out.println(maps); System.out.println(maps.size()); Set<String> keys = maps.keySet(); System.out.println(keys); Collection<Integer> values = maps.values(); System.out.println(values); } }
|
Map集合的遍历方法
根据键找值
先获取Map集合的全部键,再通过遍历键来找值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package yyssh.MapTraversingDemo1;
import java.util.HashMap; import java.util.Map; import java.util.Set;
public class MapTraversingDemo1 { public static void main(String[] args) { Map<String, Integer> maps = new HashMap<>(); maps.put("张三", 18); maps.put("王五", 19); maps.put("赵六", 20); Set<String> keys = maps.keySet(); for (String key : keys) { Integer value = maps.get(key); System.out.println(key + ":" + value); }
} }
|
把键值对看成一个整体进行遍历
利用java内置api将键值对看成一个entry对象进行遍历

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package yyssh.MapTraversingDemo2;
import java.util.HashMap; import java.util.Map; import java.util.Set;
public class MapTraversingDemo2 { public static void main(String[] args) { Map<String, Double> maps = new HashMap<>(); maps.put("蜘蛛精", 169.8); maps.put("紫霞",165.8 ); maps.put("至尊宝", 169.5); maps.put("牛魔王", 183.6);
Set<Map.Entry<String, Double>> entries = maps.entrySet(); for (Map.Entry<String, Double> entry : entries) { String key = entry.getKey(); Double value = entry.getValue(); System.out.println(key + ":" + value); } } }
|
lambda表达式遍历

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
| package yyssh.MapTraversingDemo3;
import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.function.BiConsumer;
public class MapTraversingDemo3 { public static void main(String[] args) { Map<String, Double> maps = new HashMap<>(); maps.put("蜘蛛精", 169.8); maps.put("紫霞",165.8 ); maps.put("至尊宝", 169.5); maps.put("牛魔王", 183.6);
maps.forEach(( key, value)-> System.out.println(key + ":" + value));
} }
|
Map集合的实现类
描述:Set集合就是基于Map集合的,Set集合就是Map集合不取值,只取键的结果
实现类 |
底层原理 |
Set集合基于Map集合 |
HashMap |
哈希表 |
public HashSet() { map = new HashMap<>(); } |
LinkedHashMap |
基于双链表的首尾指针进行排序 |
HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity, loadFactor); } |
TreeMap |
哈希表+红黑树 |
public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); } |
Stream流

stream流的使用步骤

获取stream流

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
| package fun.yyssh.GetStream;
import java.util.*; import java.util.stream.Stream;
public class GetStream { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("yanyuan"); list.add("chenzhuang"); Stream<String> sl = list.stream();
Map<String,Integer> map = new HashMap<>(); Stream<String> sm = map.keySet().stream(); Stream<Integer> sv = map.values().stream(); Stream<Map.Entry<String,Integer>> sme = map.entrySet().stream();
String[] arr = {"yanyuan","chenzhuang"}; Stream<String> sa = Arrays.stream(arr); Stream<String> sa2 = Stream.of(arr);
} }
|
java的集合和python的集合有什么异同
1. List(列表)
特性 |
Java |
Python |
有序性 |
有序(插入顺序),可重复 |
有序(插入顺序),可重复 |
实现分类 |
ArrayList (数组)、LinkedList (链表)、Vector (线程安全数组) |
单一列表类型(list ),底层为动态数组 |
线程安全 |
Vector 线程安全,其他默认不安全 |
默认不安全,需手动同步 |
操作示例 |
list.add(元素) 、list.get(索引) |
list.append(元素) 、list[索引] |
特点 |
类型固定(泛型),需显式声明 |
动态类型,可混合存储不同类型元素 |
2. Map(字典)
特性 |
Java |
Python |
键值对存储 |
键唯一,值可重复 |
键唯一且不可变(如字符串、数字、元组),值可任意类型 |
实现分类 |
HashMap (哈希表)、TreeMap (红黑树) |
单一字典类型(dict ),底层为哈希表 |
线程安全 |
ConcurrentHashMap 线程安全,其他默认不安全 |
默认不安全 |
操作示例 |
map.put(key, value) 、map.get(key) |
dict[key] = value 、dict.get(key) |
特点 |
键可为任意对象(需实现hashCode() 和equals() ) |
键必须为不可变类型(如列表不可作为键) |
3. Set(集合)
特性 |
Java |
Python |
元素特性 |
无序,不可重复 |
无序,不可重复(支持集合运算如并集、交集) |
实现分类 |
HashSet (哈希表)、TreeSet (红黑树) |
单一集合类型(set ),底层为哈希表 |
线程安全 |
默认不安全 |
默认不安全 |
操作示例 |
set.add(元素) 、set.contains(元素) |
set.add(元素) 、元素 in set |
特点 |
基于Map 实现(键存储,值为空对象) |
直接支持数学集合操作(如 union() , intersection() |