包
包是用来分门别类的管理各种不同的程序的,类似文件夹,建包有利于程序的管理与维护。
API文档
api为Java写好的程序供程序员使用
String
string是字符串类型,它定义的变量可以指向一个字符串对象。
string为不可变字符串。
String代表字符串,可以用来创建对象封装字符串数据,并对其进行处理。
package com.itheima.String;
public class StringDemo1 {
public static void main(String[] args) {
//掌握创建String对象,并对其进行封装要处理的字符串的两种方式
//1,直接双引号得到字符串对象,封装字符串数据
String name ="itheima";
System.out.println(name);
//2,new String 创建字符串对象,并调用构造器初始化字符串。
String rs1= new String();
System.out.println(rs1);
String rs2= new String("itheima");
System.out.println(rs2);
}
}
==是字符串判断地址的,会引起问题。此时用字符串equals方法可进行内容的判定
结论;字符串内容比较必须使用字符串的equals方法
基本数据类型比较使用==
1.length()获取字符串长度
String s ="黑马java";
//1,获取字符串长度
System.out.println(s.length());
2.cahrAt() 提取字符串中某个索引位置处的字母
//2,提取字符串中某个索引位置处的字母
char c=s.charAt(0);//出来的是黑
System.out.println(c);
3.字符串的遍历
//字符串的遍历
for (int i = 0; i < s.length(); i++) {
char ch= s.charAt(i);
System.out.print(ch);
3,把字符串转化为字符数组,再进行遍历
//3,把字符串转化为字符数组,再进行遍历
char [] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.print(chars[i]);
}
4,equals()判段字符串内容,内容一样就返回true不一样就返回false
//4,判段字符串内容,内容一样就返回true不一样就返回false
String s1=new String("黑马");
String s2=new String("黑马");
System.out.println(s1==s2);//false 因为s1,s2中为地址比较。
System.out.println(s1.equals(s2));//此方法为内容比较true
5,equalsIgnoreCase()忽略大小写比较字符串内容
//5,忽略大小写比较字符串内容
String c1="32aeEQW";
String c2="32AEeqw";
System.out.println(c1.equals(c2));//false
System.out.println(c1.equalsIgnoreCase(c2));//true
6,substring()截取字符串内容(包前不包后)类如我想截取下面的Java是最好的,那么我就要再编后截取
//6,截取字符串内容(包前不包后)类如我想截取下面的Java是最好的,那么我就要再编后截取
String s3="java是最好的编程语言之一";
String rs= s3.substring(0,8);
System.out.println(rs);//Java是最好的
7,substring()从当前索引位置一直截取到字符串末尾
//7,从当前索引位置一直截取到字符串末尾
String rs2= s3.substring(5);
System.out.println(rs2);//最好的编程语言之一
8.replace()把字符串中的某个新内容替换成新内容,并返回新的字符串对象给我们
//8,把字符串中的某个新内容替换成新内容,并返回新的字符串对象给我们
String info="这个电影是个垃圾,垃圾电影!!!";
String rs3=info.replace("垃圾","**");
System.out.println(rs3);
9.contains()判断字符串中是否包含某个关键字,包含就返回true,注意大小写。
//9判断字符串中是否包含某个关键字,包含就返回true,注意大小写。
String info2="Java是最好的编程语言之一,我爱Java,Java不爱我";
System.out.println(info2.contains("Java"));//true
10.starsWith()判断字符串是否以某个字符串开头,是就返回一个true
//10,判断字符串是否以某个字符串开头,是就返回一个true
String rs4="张三丰";
System.out.println(rs4.startsWith("张"));
System.out.println(rs4.startsWith("张三"));//true
11.split()分割字符串,把字符串按照某个指定内容分割成多个字符串,放到一个字符串数组中返回给我们
//11,分割字符串,把字符串按照某个指定内容分割成多个字符串,放到一个字符串数组中返回给我们
String rs5="张无忌,周芷若,新速速,赵敏";
String[]names =rs5.split(",");
for (int i = 0; i < names.length; i++) {
System.out.println(names[i]);
}
两种方式的区别: 双引号给出的字符串对象,存在于堆内存中的常量池中,相同内容只会存储一份。2,new 字符串对象,每new一次都会在堆内存中产生一个字符串对象 每次指向字符串新对象
package com.itheima.String;
public class StringDemo3 {
public static void main(String[] args) {
//1,只要是以双引号给出的字符串对象,存在常量池中,而且内容一致只会保存一分
String s1="abc";
String s2="abc";
System.out.println(s1==s2);//此时s1,s2指向同一个地址
//2,new String 创建字符串对象,每次new出来的都是一个新对象,放在堆内存中
char [] chars={'a','b','c'};
String a1=new String(chars);
String a2 =new String(chars);
System.out.println(a1==a2);//false
}
}
例子
在这图中第一行代码因为new出来,所以有两个对象。再第二行代码中因为字符串常量中有abc所以再双引号中就不会再有了
在下图中s1是在常量池中。s3是通过运算的出来是推内存。所以两者不相等
案例
package com.itheima.String;
import java.util.Scanner;
public class StringText {
public static void main(String[] args) {
//开发一个登录界面
for (int i=0;i<3;i++) {
Scanner sc =new Scanner(System.in);
System.out.println("请您输入登录名称:");
String loginName =sc.next();
System.out.println("请您输入登录密码:");
String passWord =sc.next();
//5,开始调用方法,判断是否登录成功
boolean rs= login(loginName,passWord);
if(rs)
{
System.out.println("恭喜您,欢迎进入系统");
break;//跳出for循环
}
else{
System.out.println("登录名或密码错误");
}
}
}
/**
2,开发一个登录方法,接受用户的登录名和密码,返回认证的结果
*/
public static boolean login(String loginName,String passWord)
{
//3,准备一份系统正确的登录名跟密码
String okloginName ="itheima";
String okPassWord="123456";
//4,开始判断用户是否登录成功
return okloginName.equals(loginName)&&okPassWord.equals(passWord);
}
}
ArrayList
ArrayList集合,用来装数据,类似于数组。元素可以重复,元素存在索引
集合的特点:大小可变,类型不固定,功能更加强大,适合做元素个数不能确定,同时存在增删操作的业务需求
注:与数组的区别为数组定义完成并启动长度固定,集合大小可变,开发中用的多。
如何构建一个ArrayList的对象代表一个集合容器,存储数据。
public ArrayList();
ArrayList = new ArrayList();
泛型:集合都是支持泛型的
ArrayList<E>
约束集合在编译阶段只能操作某种数据类型
ArrayList存储自定义类型的对象时,集合存储是的每一个对象在堆内存中的地址
ArrayList<String> list =new ArrayList();
ArrayList<Studeng> list =new ArrayList();
ArrayList<Move> list =new ArrayList();
ArrayList<integer> list =new ArrayList();
注:集合和泛型都不支持基本数据类型,只能支持引用数据类型
以后定义集合都要采用泛型
问题:如果我什么类型都要存入集合中
ArrayList list =new ArrayLislt();
ArrayList<Object> list =new ArrayLislt();
object 为对象。可定义任意类型
public class ArrayListDemo1 {
public static void main(String[] args) {
//创建一个ArrayList的集合对象
ArrayList<String> list =new ArrayList<>();//<String>限制只能为String
list.add("黑马");
list.add("黑马");
list.add("java");
System.out.println(list);//这里面list打印的是内容不是地址
//2,往集合中的某个索引位置处添加一个数据
list.add(1,"MYSQL");
System.out.println(list);
//3,根据索引获取集合中某个索引位置处的值
String rs= list.get(1);
System.out.println(rs);
//4,获取集合大小(返回集合中存储元素的个数)
System.out.println(list.size());
//5,根据索引删除集合中的某个元素值,会返回被删除的元素值给我们
System.out.println(list.remove(1));
System.out.println(list);
//6,直接删除某个元素值,删除成功会返回true,反之返回false
System.out.println(list.remove("java"));
System.out.println(list);
list.add(1,"html");
System.out.println(list);
System.out.println(list.remove("黑马"));//默认删除的是第一个黑马
System.out.println(list);
//7.修改某个索引位置处的数据,那么修改后的值会返回给我们
System.out.println(list.set(1, "黑马程序员"));
System.out.println(list);
}
案例
public class ArrayListTest2 {
public static void main(String[] args) {
//1,创建一个Arraylist集合对象
ArrayList<String> list = new ArrayList<>();
list.add("java入门");
list.add("宁夏枸杞");
list.add("黑枸杞");
list.add("人字拖");
list.add("特级枸杞");
list.add("枸杞子");
System.out.println(list);
// 2,开始完成需求,从集合中找出包含枸杞的数据并删除它
// for (int i = 0; i < list.size(); i++) {
// //i=0,1,2,3,4,5
// //取出当前遍历的数据
// String ele =list.get(i);
// //判断这个数据中包含枸杞吗
// if(ele.contains("枸杞"))
// {
// //直接从集合中删除该数据
// list.remove(ele);
// }
//
// }
// System.out.println(list);
//方式一:每次删除一个数据,就让i往左边退一步
// for (int i = 0; i < list.size(); i++) {
// //i=0,1,2,3,4,5
// //取出当前遍历的数据
// String ele =list.get(i);
// //判断这个数据中包含枸杞吗
// if(ele.contains("枸杞"))
// {
// //直接从集合中删除该数据
// list.remove(ele);
// i--;//因为每删除一个数据i会向下加一,后面的数据会自动往上走
// }
//
// }
System.out.println(list);
//方式二,从集合的后面开始遍历并删除
for (int i = list.size() - 1; i >= 0; i--) {
//取出当前遍历的数据
String ele = list.get(i);
//判断这个数据中包含枸杞吗
if (ele.contains("枸杞")) {
//直接从集合中删除该数据
list.remove(ele);
}
System.out.println(list);
}
}
ArrayList遍历并删除元素————边遍历边删除存在问题。
ArrayList综合案例
import java.util.ArrayList;
public class ArrayListTest3 {
public static void main(String[] args) {
//完成商家菜品上架
//1,设计一个菜品类Food,负责创建菜品对象,封装菜品数据
//2 设计一个菜品操作类FoodOperator负责完成对菜品的业务的实现,上架,浏览信息
FoodOperator operator =new FoodOperator();
operator.start();
}
}
类
public class Food {
private String name;
private double price;
private String desc;
public Food() {
}
public Food(String name, double price, String desc) {
this.name = name;
this.price = price;
this.desc = desc;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
import java.util.ArrayList;
import java.util.Scanner;
//菜品操作类负责完成对菜品的业务的实现,上架,浏览信息
public class FoodOperator {
//定义一个ArrayList 集合对象负责存储菜品信息
private ArrayList<Food> foodlist = new ArrayList<>();
//foodlist=[]
//2,开发功能,上架菜品功能
public void addFood() { //3,创建一个菜品对象,并封装上架的菜品信息
Food f = new Food();
//4,录入菜品信息进去
Scanner sc = new Scanner(System.in);
System.out.println("请您输入该菜品名称:");
String name = sc.next();
f.setName(name);
System.out.println("请您输入该菜品价格:");
double price = sc.nextDouble();
f.setPrice(price);
System.out.println("请您输入该菜品描述:");
String desc = sc.next();
f.setDesc(desc);
//5,把菜品对象存入到集合当中去
foodlist.add(f);
System.out.println("上架成功!");
}
//6,展示菜品
//foodlsit =[f1,f2,f3.....]
public void showAllFood() {
if(foodlist.size()==0)
{
System.out.println("什么菜品都没有,先去上架");
return;
}
for (int i = 0; i < foodlist.size(); i++) {
Food f = foodlist.get(i);
System.out.println(f.getName());
System.out.println(f.getPrice());
System.out.println(f.getDesc());
System.out.println("------------------------");
}
}
//负责显示操作界面
public void start()
{
while (true) {
System.out.println("请选择功能: ");
System.out.println("1,上架菜品");
System.out.println("2,展示菜品");
System.out.println("3,退出");
Scanner sc =new Scanner(System.in);
System.out.println("请选择你的操作: ");
String command = sc.next();
switch (command)
{
case "1":
addFood();
break;
case "2":
showAllFood();
break;
case "3":
System.out.println("下次再来哦!");
return;//干掉方法退出循环
default:
System.out.println("您输入命令不存在");
}
}
}
}
Object
重写toString方法使得打印对象不在是地址而是内容
//重写toString方法使得打印对象不在是地址而是内容
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
重写equals方法比较两者对象的内容是否一致,一样就返回true
比较者:s2 ==this
被比较者:s1 ==o
//重写equals方法比较两者对象的内容是否一致,一样就返回true
//比较者:s2 ==this
//被比较者:s1 ==o
@Override
public boolean equals(Object o) {
//1,判断两者的地址是否一致,一致返回true
if (this == o) return true;
//2.判断o是null或者getClass比较者的类型与被比较者的类型不一样,返回false
if (o == null || this.getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
浅克隆
//重写clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
深克隆
//重写clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
User u2 = (User) super.clone();
u2.scores=u2.scores.clone();
return u2;
}
public class Test {
public static void main(String[] args) {
Student s1 =new Student("刘翀羽",19);
System.out.println(s1.toString());
System.out.println("---------------------");
Student s2 =new Student("刘翀羽",19);
//因为在创建新对象时s2虽然内容一样但是由于是新对象所以地址不一样
//重写equals方法前
System.out.println(s2.equals(s1));//false
System.out.println(s1 == s2);//false 也是在比较两者的地址
//重写后
System.out.println(s2.equals(s1));//true
}
}
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student() {
}
//重写toString方法使得打印对象不在是地址而是内容
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//重写equals方法比较两者对象的内容是否一致,一样就返回true
//比较者:s2 ==this
//被比较者:s1 ==o
@Override
public boolean equals(Object o) {
//1,判断两者的地址是否一致,一致返回true
if (this == o) return true;
//2.判断o是null或者getClass比较者的类型与被比较者的类型不一样,返回false
if (o == null || this.getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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 class Test2 {
public static void main(String[] args) throws CloneNotSupportedException {
//掌握对象克隆的方法
//1,protected Object clone() :对象克隆
User u1 =new User(1,"刘翀羽","m12222"
,new double[]{99.0,99.5});
//因为clone是protected不能直接调用,需重写方法
// u1.clone();
System.out.println(u1.getId());
System.out.println(u1.getPassword());
System.out.println(u1.getScores());
System.out.println(u1.getUsername());
System.out.println("----------------");
//浅克隆
User u2 = (User) u1.clone();
System.out.println(u2.getId());
System.out.println(u2.getPassword());
System.out.println(u2.getScores());
System.out.println(u2.getUsername());
}
}
//Cloneable是一个标记接口
//规则
public class User implements Cloneable{
private int id;//编号
private String username;//用户名
private String password;//密码
private double[] scores;//分数
//重写clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
User u2 = (User) super.clone();
u2.scores=u2.scores.clone();
return u2;
}
public User() {
}
public User(int id, String username,
String password, double[] scores) {
this.id = id;
this.username = username;
this.password = password;
this.scores = scores;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double[] getScores() {
return scores;
}
public void setScores(double[] scores) {
this.scores = scores;
}
}
浅克隆
//重写clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
深克隆
//重写clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
User u2 = (User) super.clone();
u2.scores=u2.scores.clone();
return u2;
}
在下面的结果中数组地址不同说明实现了深克隆
Objects
import java.util.Objects;
public class Test {
public static void main(String[] args) {
//掌握Objects类提供的方法
// String s1 ="itheima";
// String s2 ="itheima";
// System.out.println(s1.equals(s2));//true
// System.out.println(Objects.equals(s1, s2));//true
String s1 =null;
String s2 ="itheima";
//System.out.println(s1.equals(s2));//false因为在s1为空比较时
//s1调就用不成,但是反过来若
// String s1 ="itheima";
// String s2 =null;
//那就调s1.equals(s2)不会报错但是总体而言使用Objects更好
System.out.println(Objects.equals(s1, s2));//false
}
}
包装类
1.把基本类型的数据都转换成字符串
//法1
Integer a =23;
String rs1= Integer.toString(a);
System.out.println(rs1 + 1);//231
//法2
String rs2 = a.toString();
System.out.println(rs2+1);
//法3
String rs3 = a+"";
System.out.println(rs3 + 1);//231
2,把字符串类型的数值转化成对应的基本类型
//2,把字符串类型的数值转化成对应的基本类型
// String ageStr ="29a";传入必须是数值,26a就不行
// String ageStr ="29.85";数据必须统一
String ageStr ="29";
// int ageI =Integer.parseInt(ageStr);用这个也行
int ageI =Integer.valueOf(ageStr);//更方便
System.out.println(ageI+1);//30
String ageStr2 ="29.9";
// double ageD =Double.parseDouble(ageStr2);用这个也行
double ageD =Double.valueOf(ageStr2);//更方便
System.out.println(ageD+0.1);//30
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
//Integer a1 = new Integer(12);过时了
Integer a2= Integer.valueOf(12);
System.out.println(a2);//12
//自动装箱:可以自动把基本类型的数据换成对象
Integer a3 =12;
//自动拆箱:可以自动将包装类型的对象换成对应的基本数据类型
int a4 =a3;
//泛型与集合都不支持基本的数据类型,只能支持引用数据类型
// ArrayList<int> list =new ArrayList<int>();
ArrayList<Integer> list =new ArrayList<>();
list.add(12);//自动装箱
int a5=list.get(0);//自动拆箱
System.out.println("-----------------------------");
//1.把基本类型的数据都转换成字符串
//法1
Integer a =23;
String rs1= Integer.toString(a);
System.out.println(rs1 + 1);//231
//法2
String rs2 = a.toString();
System.out.println(rs2+1);
//法3
String rs3 = a+"";
System.out.println(rs3 + 1);//231
System.out.println("---------------------");
//2,把字符串类型的数值转化成对应的基本类型
// String ageStr ="29a";传入必须是数值,26a就不行
// String ageStr ="29.85";数据必须统一
String ageStr ="29";
// int ageI =Integer.parseInt(ageStr);用这个也行
int ageI =Integer.valueOf(ageStr);//更方便
System.out.println(ageI+1);//30
String ageStr2 ="29.9";
// double ageD =Double.parseDouble(ageStr2);用这个也行
double ageD =Double.valueOf(ageStr2);//更方便
System.out.println(ageD+0.1);//30
}
}
StringBuilder
声明:
StringBuilder s = new StringBuilder();//s""
StringBuilder s =new StringBuilder("java");//s"java"
1.append()拼接内容
支持链式编程
//拼接内容
s.append(12);
s.append("黑马");
s.append(true);
//支持链式编程
s.append(666).append("erwtwt").append(12233);
//java12黑马true666erwtwt12233
2.reverse(); 反转内容操作
//2.反转操作
s.reverse();
System.out.println(s);//33221twtwre666eurt马黑21avaj
3.length()返回字符串长度
//3.返回字符串长度
System.out.println(s.length());//26
4,toString()
把StringBuild对象文件换成String类型
//4,把StringBuild对象文件换成String类型
String rs =s.toString();
System.out.println(rs);//33221twtwre666eurt马黑21avaj
注:以下面的代码为例,使用StringBuilder速度快,但是使用String会速度慢
public class StringBuilder_benefit {
public static void main(String[] args) {
//拼接100万次abc
//用string慢
// String rs ="";
// for (int i = 1; i <1000000 ; i++) {
// rs+="abc";
// }
// System.out.println(rs);
//使用strigbuild方法(快)
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i <1000000 ; i++) {
stringBuilder.append("abc");
}
System.out.println(stringBuilder);
}
}
StringBuffer
和 StringBuilder 都是用来处理可变字符串的类,但有以下主要区别:
1.线程安全:StringBuffer 是线程安全的,它的方法被同步,以确保在多线程环境中安全操作。而 StringBuilder 是非线程安全的,适合在单线程环境下使用,性能通常更高。
2.性能:由于 StringBuffer 的同步开销,StringBuilder 通常比 StringBuffer 更快。如果你在单线程中操作字符串,建议使用 StringBuilder。
3.使用场景:如果你的应用程序不涉及多线程的字符串修改,StringBuilder 是更优选择。如果你需要在多线程环境中安全地修改字符串,使用 StringBuffer 更合适。
总体来说,选择哪个类取决于你对线程安全性和性能的具体需求。
//案例
public class Test3 {
public static void main(String[] args) {
System.out.println(getArrayData(new int[]{11, 22, 33}));
}
public static String getArrayData(int [] arr)
{//1.判断arr是否为null
if(arr ==null)
{
return null;
}
//2.arr数组对象存在,arr=[11,22,33]
StringBuilder sb =new StringBuilder();
sb.append("[");
for (int i = 0; i <arr.length; i++) {
if(i==arr.length-1)
{
sb.append(arr[i]);
}
else {
sb.append(arr[i]).append(", ");
}
}
sb.append("]");
return sb.toString();
}
}
StringJoiner
1. StringJoiner s = new StringJoiner(",", "[", "]");//间隔符
使得数据在[ ,]里包着并且用逗号隔开
2.add()增添数据
3.length() 返回长度
4.toString()转成字符串
import java.util.StringJoiner;
public class Test {
public static void main(String[] args) {
StringJoiner s = new StringJoiner(",", "[", "]");//间隔符
s.add("java1");
s.add("java2");
s.add("java3");
System.out.println(s);//[java1,java2,java3]
System.out.println("-----------------------");
System.out.println(getArrayData(new int[]{11, 22, 33}));
}
public static String getArrayData(int[] arr) {
//1.判断arr是否为null
if (arr == null) {
return null;
}
//2.arr数组对象存在,arr=[11,22,33]
StringJoiner s =new StringJoiner(", ","[","]");
for (int i = 0; i <arr.length ; i++) {
s.add(arr[i]+"");
}
return s.toString();
}
}
StringBuilder、StringBuffer、StringJoiner和String在Java中都是用于处理字符串的类,但它们之间存在一些关键的区别,包括性能、线程安全性、使用场景以及功能特性。以下是对这些类的详细比较:
1. String
- 不可变性:String是Java中的不可变类,一旦创建就不能被修改。对String的任何修改操作(如拼接、替换等)实际上都会创建一个新的String对象。
- 使用场景:适用于字符串不经常改变的场景,如字符串常量、方法参数等。
- 性能:由于不可变性,每次修改都会产生新的对象,可能导致较高的内存开销和性能损失。
2. StringBuilder
- 可变性:StringBuilder是可变字符序列,可以动态地添加、删除和替换字符串中的字符,而无需创建新的对象。
- 线程安全性:StringBuilder不是线程安全的,因此在多线程环境下使用可能会遇到并发问题。
- 性能:在单线程环境下,StringBuilder的性能通常优于StringBuffer,因为它没有额外的同步开销。
- 使用场景:适用于需要在单线程环境下频繁修改字符串的场景。
3. StringBuffer
- 可变性:与StringBuilder类似,StringBuffer也是可变字符序列,可以动态地修改字符串内容。
- 线程安全性:StringBuffer是线程安全的,所有公共方法都进行了同步处理,以确保在多线程环境下的安全使用。
- 性能:由于同步处理,StringBuffer的性能在单线程环境下可能略逊于StringBuilder。
- 使用场景:适用于需要在多线程环境下安全修改字符串的场景。
4. StringJoiner
- 功能特性:StringJoiner是Java 8引入的一个实用类,用于构建由分隔符连接的字符串。它特别适用于需要频繁地添加元素并用特定分隔符分隔的场景。
- 线程安全性:StringJoiner的线程安全性取决于其内部使用的StringBuilder是否在多线程环境下被共享。如果只在单线程中使用,则是线程安全的。
- 使用场景:当需要连接多个字符串并添加前缀、后缀和分隔符时,StringJoiner会是一个更好的选择。
总结
类名 | 可变性 | 线程安全性 | 性能(相对于其他类) | 使用场景 |
---|---|---|---|---|
String | 不可变 | 无关(因为是不可变的) | 较低(每次修改都创建新对象) | 字符串不经常改变的场景 |
StringBuilder | 可变 | 非线程安全 | 较高(在单线程环境下) | 需要在单线程环境下频繁修改字符串的场景 |
StringBuffer | 可变 | 线程安全 | 适中(有同步开销) | 需要在多线程环境下安全修改字符串的场景 |
StringJoiner | 可变(内部使用StringBuilder) | 取决于内部StringBuilder的使用环境 | 较高(用于构建分隔符连接的字符串) | 需要连接多个字符串并添加前缀、后缀和分隔符的场景 |
在选择使用哪个类时,应根据具体的使用场景、性能要求和线程安全需求进行综合考虑。
Math
1,abs()取绝对值
1,取绝对值
System.out.println(Math.abs(-12));//12
System.out.println(Math.abs(-134.3434555));//134.3434555
2.ceil()向上取整
//2.向上取整
System.out.println(Math.ceil(4.00001));//5.0
System.out.println(Math.ceil(4.0));//4.0
3. floor()向下取整
//3向下取整
System.out.println(Math.floor(3.49999));//3.0
System.out.println(Math.floor(3.0));//3.0
4.round()四舍五入
//4.四舍五入
System.out.println(Math.round(3.4999));//3
System.out.println(Math.round(3.5001));//4
5.max() min()去最大小值
//5.去最大小值
System.out.println(Math.max(12, 123.43545));//123.43545
System.out.println(Math.min(1243242, 543545));//543545
6.pow()取次方
//6.取次方
System.out.println(Math.pow(2, 3));//2的3次方8.0
System.out.println(Math.pow(12, 3));//12的3次方1728.0
7.random()随机数[0.0 ,1.0) 左闭右开
//7.随机数[0.0 ,1.0) 左闭右开
System.out.println(Math.random());
System
在 Java 程序中,System.exit(int status)
方法用于终止当前正在运行的 Java 虚拟机(JVM)。参数 status
是一个整数,表示程序的退出状态码。通常情况下,0
表示程序成功退出,而非 0
的状态码通常表示程序异常终止或发生错误。
public class Test {
public static void main(String[] args) {
//1.System.exit();非0状态下表示异常终止
// System.exit(0);人为的终止虚拟机(不建议使用)
// System.out.println("--------------");
//2.System.currentTimeMillis()获取的是当前系统的时间
//返回的是long类型的时间毫秒值,指的是从1979—1-1 0:0:0开始到此走的总毫秒值
//1s ==1000s
long time = System.currentTimeMillis();
System.out.println(time);//1723364447039
for (int i = 0; i <1000000 ; i++) {
System.out.println("输出了"+i);
}
long time2 =System.currentTimeMillis();
System.out.println((time2-time)/1000.0+"s");//计算出运算所用时间
}
}
Runtime
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
//1.Runtime.getRuntime();返回与当前java应用程序关联的运行对象
Runtime r =Runtime.getRuntime();
//2.r.exit();终止当前运行的虚拟机,该参数运作状态代码,按照惯例,非零状态代码表示异常终止
// r.exit(0);
//3.r.availableProcessors()获取虚拟机能够使用的处理器数
System.out.println(r.availableProcessors());//16
//4.r.totalMemory() 返回虚拟机中的内存总数
System.out.println(r.totalMemory() / 1024.0 / 1024.0 + "MB");//1024=1k 1024*1024=1m
//5.r.freeMemory()返回Java虚拟机的可用内存
System.out.println(r.freeMemory() / 1024.0 / 1024.0 + "MB");
//6.启动程序,并返回代表该程序的对象
Process p= r.exec("QQ");
Thread.sleep(5000);//让该程序在这里暂停5s后继续往下走
p.destroy();//销毁,关闭程序
}
}
BigDecimal(解决失真问题)
在 Java 中,double
类型使用浮点数表示小数,这种表示方式可能导致精度问题。浮点数在计算机中通常是近似表示的,因此可能会出现小数点后数字的不准确。
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Test {
public static void main(String[] args) {
//解决小数运算失真问题
double a =0.1;
double b =0.2;
double c =a+b;
//double a= 0.1;
//double b =0.2;
//double c= a+b;
//System.out.println(c);
//System.out.println("-----------------");
//
//把他们变成字符串封装成BigDecimal对象来运算
//
// BigDecimal a1 =new BigDecimal(Double.toString(a));
BigDecimal a1 =BigDecimal.valueOf(a);
BigDecimal b1 =BigDecimal.valueOf(b);
BigDecimal c1 =a1.add(b1);
BigDecimal c2 = a1.subtract(b1);//减法
BigDecimal c3= a1.multiply(b1);
BigDecimal c4 = a1.divide(b1);
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println("-------------------");
BigDecimal i =BigDecimal.valueOf(0.1);
BigDecimal j =BigDecimal.valueOf(0.3);
BigDecimal k =i.divide(j,2,RoundingMode.HALF_UP);//除法四舍五入
System.out.println(k);
//把BigDecimal类型数据转换为double类型数据
double rs= k.doubleValue();
System.out.println(rs);
}
}
Date
import java.util.Date;
public class Test1Date {
public static void main(String[] args) {
//掌握Date日期类的使用
//1.创建一个Date的对象,代表系统当前的时间信息
Date date =new Date();
System.out.println(date);
//2,拿到时间毫秒值
long time = date.getTime();
System.out.println(time);
//3.把时间毫秒值转换成日期对象:2s之后的时间是多少
time+=2*1000;
Date date1 =new Date((time));
System.out.println(date1);
//4.直接把日期对象的时间通过settime方法进行修改
Date d3 =new Date();
d3.setTime(time);
System.out.println(d3);//结果同三
}
}
SimplateDateFormat
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test2SimpleDateFormat {
public static void main(String[] args) throws ParseException {
//1.准备一些时间
Date d =new Date();
System.out.println(d);
long time =d.getTime();
System.out.println(time);
//2. 格式化日期对象,和时间 毫秒值
SimpleDateFormat sdf =new SimpleDateFormat("yyyy年 MM月dd日 HH:mm:ss EEE a");
String rs = sdf.format(d);
String rs1 =sdf.format(time);
System.out.println(rs);
System.out.println(rs1);
//掌握SimpleDateFormat解析字符串时间成为日期对象
String dataStr ="2024-08-12 16:28:11";
//1,创建简单格式化对象,指定的时间格式化必须要与被解析的时间格式化一模一样,否则程序会出bug
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d2 = sdf2.parse(dataStr);
System.out.println(d2);
}
}
案例
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test3 {
public static void main(String[] args) throws ParseException {
//目标完成秒杀案例
//1.把开始时间,结束时间,小贾下单时间,小皮下单时间拿到程序当中来
String start ="2023年11月11日 0:0:0";
String end ="2023年11月11日 0:10:0";
String xj ="2023年11月11日 0:01:18";
String xp ="2023年11月11日 0:10:57";
//2.把字符串的时间解析成日期对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date startDt = sdf.parse(start);
Date endDt = sdf.parse(end);
Date xjDt = sdf.parse(xj);
Date xpDt = sdf.parse(xp);
//开始判断小贾与小皮是否秒杀成功了
//把日期对象换成时间毫秒值来判断
long starttime = startDt.getTime();
long endtime = endDt.getTime();
long xjtime = xjDt.getTime();
long xptime = xpDt.getTime();
if(xjtime>=starttime&&xjtime<=endtime)
{
System.out.println("小贾秒杀成功了");
}
else {
System.out.println("小贾秒杀失败了");
}
if(xptime>=starttime&&xptime<=endtime)
{
System.out.println("小皮秒杀成功了");
}
else {
System.out.println("小皮秒杀失败了");
}
}
}
Calendar
import java.util.Calendar;
import java.util.Date;
public class Test4Calendar {
public static void main(String[] args) {
//1.得到系统此刻时间对应的日历对象
Calendar now = Calendar.getInstance();
System.out.println(now);
//2.获取日历中的某个信息
int year = now.get(Calendar.YEAR);
System.out.println(year);
int month = now.get(Calendar.MONTH);//月份是从0开始计算的
System.out.println(month);
int days = now.get(Calendar.DAY_OF_YEAR);
System.out.println(days);
//拿到日历中记录的日期对象
Date time = now.getTime();
System.out.println(time);
//拿到时间毫秒值
long timeInMillis = now.getTimeInMillis();
System.out.println(timeInMillis);
//修改日历中的某个时间
now.set(Calendar.MONTH,9);//修改月份为10月份
now.set(Calendar.DAY_OF_YEAR,124);//修改成一年中的第124天
System.out.println(now);
//为某个信息增加或减少多少
now.add(Calendar.DAY_OF_YEAR,100);
now.add(Calendar.DAY_OF_YEAR,-10);//减少一年中的第几天10
now.add(Calendar.DAY_OF_MONTH,6);//一个月中的第几天
now.add(Calendar.HOUR,12);//增加小时
System.out.println(now);
}
}
jdk8新时间
LocalDateTime
import java.time.LocalDate;
public class Test1_LocalDate {
public static void main(String[] args) {
//获取本地日期时间对象(不可变对象)
LocalDate ld =LocalDate.now();//年 月 日
System.out.println(ld);
//1.获取日期对象的信息
int year = ld.getYear();//年
int month = ld.getMonthValue();//月(1-12)
int day = ld.getDayOfMonth();//日
int dayOfYear = ld.getDayOfYear();//一年中的第几天
int dayOfWeek = ld.getDayOfWeek().getValue();//星期几
System.out.println(year);
System.out.println(day);
System.out.println(dayOfWeek);//2
//2,直接修改某个信息:withYear,withDayOfMonth,withDayOfYear
LocalDate ld2 =ld.withYear(2099);
LocalDate ld3 =ld.withMonth(12);
System.out.println(ld2);
System.out.println(ld);
System.out.println(ld3);
//3.把某个信息加多少:plusYears,plusMonths,plusMonths,plusDays,plusWeek
LocalDate ld4 = ld.plusYears(2);
LocalDate ld5 = ld.plusMonths(3);
//4,把某个信息减多少 minusYear,minusMonths,minusDays,minusWeeks
LocalDate ld6 = ld.minusYears(2);
LocalDate ld7 = ld.minusMonths(4);
//5,获取指定日期的localDate对象,public static localDate of (int year ,int month,int dauOfMonth)
LocalDate ld8 = LocalDate.of(2099, 12, 12);
//6,判断2个日期对象,是否相等,在前还是在后:equals isBefore isAfter
System.out.println(ld8.equals(ld7));//false
System.out.println(ld8.isAfter(ld));//true
System.out.println(ld8.isBefore(ld));//false
}
}
zoneid
//了解时区与带时区的时间
public class Test4_Zoneid_ZoneDateTime {
public static void main(String[] args) {
//1ZooId的常见方法
// ZoneId.systemDefault();获取java支持的全部时区id
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId.getId());
System.out.println(zoneId);
//获取Java支持的全部时区id
System.out.println(ZoneId.getAvailableZoneIds());
//获取某个时区的id封装成ZoneId对象
ZoneId zoneId1 = ZoneId.of("America/New_York");
//2,ZoneDateTime 带时区的时间
// ZonedDateTime.now(ZoneId zone):获取某个时区的ZoneDateTime对象
ZonedDateTime now = ZonedDateTime.now(zoneId1);
System.out.println(now);
//世界标准时间
ZonedDateTime now1 = ZonedDateTime.now(Clock.systemUTC());
System.out.println(now1);
//ZoneDateTime now()获取系统默认时区的ZoneDateTime对象
ZonedDateTime now2 = ZonedDateTime.now();
System.out.println(now2);
//Canlender这个方法因为是可变对象,使用时不方便已被淘汰
// Calendar instance = Calendar.getInstance(TimeZone.getTimeZone(zoneId1));
}
}
instant
Instant对象的作用:做代码的性能分析,或者记录用户的操作时间点
import java.time.Instant;
//掌握instant的使用
public class Test5_Instant {
public static void main(String[] args) {
//创建instant的对象,获取此刻时间信息
Instant now = Instant.now();
//2,获取总秒数
long second = now.getEpochSecond();
System.out.println(second);
//3.不够一秒的纳秒值
int nano = now.getNano();
System.out.println(nano);
System.out.println(now);
Instant plusNanos = now.plusNanos(111);
System.out.println(plusNanos);
//Instant对象的作用:做代码的性能分析,或者记录用户的操作时间点
Instant now1 = Instant.now();
//代码执行
Instant now2 = Instant.now();
}
}
DateTimeFormatter
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Test6_DateTimeFormatter {
public static void main(String[] args) {
//1.创建一个日期时间格式化器对象出来
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
//2.对时间进行格式化
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
String rs = formatter.format(now);//正向格式化
System.out.println(rs);
//3.格式化时间,其实还有一种方案
String rs2 = now.format(formatter);
System.out.println(rs);
//4.解析时间,解析时间一般使用LocalDateTime想提供的解析方法来解析
String dateStr ="2099年12月12日 12:12:11";
LocalDateTime ldt = LocalDateTime.parse(dateStr, formatter);
System.out.println(ldt);
}
}
Period
import java.time.LocalDate;
import java.time.Period;
public class Test7_Period {
public static void main(String[] args) {
LocalDate start = LocalDate.of(2029, 7, 10);
LocalDate end = LocalDate.of(2029, 8, 15);
//创建Period对象,封装两个日期对象
Period period = Period.between(start, end);
//通过period对象获取两个日期对象相差的信息
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());
}
}
Duration
import java.time.Duration;
import java.time.LocalDateTime;
public class Test8_Duration {
public static void main(String[] args) {
LocalDateTime start = LocalDateTime.of(2025, 11, 11, 11, 11, 10, 10);
LocalDateTime end = LocalDateTime.of(2025, 11, 11, 11, 11, 11, 11);
//得到Duratio对象
Duration duration = Duration.between(start,end);
//2,获取两个时间对象间隔的信息
System.out.println(duration.toDays());//间隔多少天
System.out.println(duration.toHours());//间隔多少小时
System.out.println(duration.toMinutes());//间隔多少分
System.out.println(duration.toSeconds());//间隔多少秒
System.out.println(duration.toMillis());//间隔多少毫秒
System.out.println(duration.toNanos());//间隔多少纳秒
}
}
Arrays
import java.util.Arrays;
import java.util.function.IntToDoubleFunction;
public class Test1 {
public static void main(String[] args) {
//1.toString (类型[]arr) 返回字符串数组
int [] arr= {10,20,30,40,50,60};
System.out.println(Arrays.toString(arr));
//2.copyOfRange(类型[]arr,起始索引,结束索引),拷贝数组(指定范围,包前不包后)
int []arr2= Arrays.copyOfRange(arr,1,4);//[20, 30, 40]
System.out.println(Arrays.toString(arr2));
//3.copyOf(类型[]arr,int newlength)拷贝数组,可以指定新数组的长度
int[] arr3 = Arrays.copyOf(arr, 10);
System.out.println(Arrays.toString(arr3));//[10, 20, 30, 40, 50, 60, 0, 0, 0, 0]
//4.setAll(double[] array, IntToDoubleFunction generator) 把数组中的原数据改为新数据又存进去
//例子:给所有的价格都打八折,又存进去
double[] prices={99.8,128,100};
//value 0 1 2
Arrays.setAll(prices, new IntToDoubleFunction() {
@Override
public double applyAsDouble(int value) {
//value 0 1 2
return prices[value]*0.8;
}
});
System.out.println(Arrays.toString(prices));
//sort(类型[]arr); 对数组进行排序(默认为升序排序)
Arrays.sort(prices);
System.out.println(Arrays.toString(prices));//[79.84, 80.0, 102.4]
}
}
数组为对象排序
import java.util.Arrays;
import java.util.Comparator;
public class Test2 {
public static void main(String[] args) {
//掌握如何对数组中的对象进行排序
Student[] students = new Student[4];
students[0]=new Student("蜘蛛精",169.3,23);
students[1]=new Student("紫霞",163.8,26);
students[2]=new Student("紫霞",163.8,26);
students[3]=new Student("至尊宝",167.8,24);
//1,sort对数组进行排序
// Arrays.sort(students);
// System.out.println(Arrays.toString(students));
//2,public static <T> void (T[] arr,Comparator<? super T> c )
//参数1:需要排序的数组
//参数2:Comparator比较器对象(用来制定对象的比较规则)
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//制定比较规则 左边对象为o1 右边对象o2
//约定1:认为左边对象 大于 右边对象 请您返回正整数
//约定2:认为左边对象 小于 右边对象 请您返回负整数
//约定3:认为左边对象 等于 右边对象 请您返回0
// 直接比较会因为为int类型而报错 return o1.getHeight()-o2.getHeight();
//法一
// if(o1.getHeight()>o2.getHeight()) {
// return 1;
// }else if(o1.getHeight()<o2.getHeight())
// {
// return -1;
// }
// return 0;
//法二(跟法一个结果)
//升序
return Double.compare(o1.getHeight(),o2.getHeight());
//降序
// return Double.compare(o2.getHeight(),o1.getHeight());
}
});
System.out.println(Arrays.toString(students));
}
}
public class Student implements Comparable<Student>{
private String name;
private double height;
private int age;
//指定比较规则
// this o
@Override
public int compareTo(Student o) {
//约定1:认为左边对象 大于 右边对象 请您返回正整数
//约定2:认为左边对象 小于 右边对象 请您返回负整数
//约定3:认为左边对象 等于 右边对象 请您返回0
// if(this.age>o.age)
// {
// return 1;
// }else if(this.age<o.age)
// {
// return -1;
// }
//
// return 0;
//可以代替上面的方法
// return this.age -o.age;//年龄升序
return o.age-this.age;//年龄降序
}
//重写toString方法
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", height=" + height +
", age=" + age +
'}';
}
public Student(String name, double height, int age) {
this.name = name;
this.height = height;
this.age = age;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
lambda
package com.d16_lambda;
public class Test1 {
public static void main(String[] args) {
// Animal a = new Animal() {
// @Override
// public void run() {
// System.out.println("狗跑的贼快----");
// }
// };
// a.run();
//注意:lambda表达式并不是说能简化全部匿名内部类的写法,只能简化函数式接口的匿名内部类
//错误的代码
// Animal a =() ->{
// System.out.println("狗跑的贼快--");
// };
// a.run();
// Swimming s = new Swimming() {
// @Override
// public void swim() {
// System.out.println("学生快乐的游泳");
// }
// };
// s.swim();
Swimming s =()->{
System.out.println("学生快乐的游泳");
};
s.swim();
}
}
interface Swimming{
void swim();
}
abstract class Animal{
public abstract void run();
}
import java.util.Arrays;
import java.util.Comparator;
import java.util.function.IntToDoubleFunction;
public class Test2 {
public static void main(String[] args) {
//例子:给所有的价格都打八折,又存进去
double[] prices={99.8,128,100};
//value 0 1 2
// Arrays.setAll(prices, new IntToDoubleFunction() {
// @Override
// public double applyAsDouble(int value) {
// //value 0 1 2
// return prices[value]*0.8;
// }
// });
//第一步简化
//
// Arrays.setAll(prices,(int value)->{
// //value 0 1 2
// return prices[value]*0.8;
//
// });
//第2步
// Arrays.setAll(prices,( value)->{
// //value 0 1 2
// return prices[value]*0.8;
//
// });
//第三步
// Arrays.setAll(prices,( value)->{
// //value 0 1 2
// return prices[value]*0.8;
//
// });
//第四步
Arrays.setAll(prices, value->{
//value 0 1 2
return prices[value]*0.8;
});
//第五步
Arrays.setAll(prices,(value)-> prices[value]*0.8);
}
}
方法引用(简化代码)
package com.d17_method_references;
import com.d15_Arrays.Student;
import java.util.Arrays;
import java.util.Comparator;
public class Test1 {
public static void main(String[] args) {
Student[] students = new Student[4];
students[0]=new Student("蜘蛛精",169.3,23);
students[1]=new Student("紫霞",163.8,26);
students[2]=new Student("紫霞",163.8,26);
students[3]=new Student("至尊宝",167.8,24);
//原始写法:对数组中的学生对象,按照年龄升序排序
// Arrays.sort(students, new Comparator<Student>() {
// @Override
// public int compare(Student o1, Student o2) {
// return o1.getAge()-o2.getAge();
// }
// });
//使用lambda简化后的形式
// Arrays.sort(students,(o1,o2)->o1.getAge()-o2.getAge());
// Arrays.sort(students,(o1,o2)->CompareByData.compareByAge(o1, o2));
//使用静态方法引用(按照年龄升序)
Arrays.sort(students,CompareByData::compareByAge);
//实例方法(降序)
Arrays.sort(students,(o1,o2)->o2.getAge()-o1.getAge());
CompareByData compare = new CompareByData();//实例创建对象
// Arrays.sort(students,(o1,o2)->compare.compareByAgeDesc(o1,o2));
Arrays.sort(students,compare::compareByAgeDesc);
System.out.println(Arrays.toString(students));
}
}
package com.d17_method_references;
import com.d15_Arrays.Student;
//静态升序方法
public class CompareByData {
public static int compareByAge(Student o1,Student o2)
{
return o1.getAge()-o2.getAge();//升序排序的规则
}
//实例降序方法
public int compareByAgeDesc(Student o1,Student o2)
{
return o2.getAge()-o1.getAge();
}
}
//构造器引用
CreateCar cc =Car::new;
package com.d17_method_references;
public class Test3 {
public static void main(String[] args) {
//1创建这个接口的匿名内部类
// CreateCar cc = new CreateCar() {
// @Override
// public Car create(String name, double price) {
// return new Car(name,price);
// }
// };
// CreateCar cc =(name,price)->new Car(name,price);
//构造器引用
CreateCar cc =Car::new;
Car c =cc.create("奔驰",49.9);
System.out.println(c);
}
}
interface CreateCar{
Car create(String name,double price);
}
package com.d17_method_references;
public class Car {
private String name;
private double price;
public Car() {
}
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
public Car(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
toCharArray()
要将字符串拆分成单个字符
public class SplitStringToCharacters {
public static void main(String[] args) {
String text = "Hello, World!";
char[] characters = text.toCharArray();
for (char ch : characters) {
System.out.println(ch);
}
}
}
### 访问修饰符
- `public`: 可被所有类访问。
- `private`: 仅限于在同一类中访问。
- `protected`: 可在同一包或子类中访问。
### 类和对象
- `class`: 定义一个类。
- `interface`: 定义一个接口。
- `enum`: 定义一个枚举。
- `new`: 创建对象实例。
- `extends`: 表示继承。
- `implements`: 表示实现接口。
- `abstract`: 定义抽象类或抽象方法。
### 控制流语句
- `if`
- `else`
- `switch`
- `case`
- `default`
- `for`
- `while`
- `do`
- `break`
- `continue`
- `return`
### 异常处理
- `try`
- `catch`
- `finally`
- `throw`
- `throws`
### 数据类型
- `int`
- `short`
- `long`
- `float`
- `double`
- `byte`
- `char`
- `boolean`
- `void`
### 变量和对象修饰符
- `static`: 静态变量或方法。
- `final`: 最终变量、方法或类,不能被修改或继承。
- `transient`: 序列化中忽略的字段。
- `volatile`: 变量被多线程共享。
### 方法和构造函数
- `synchronized`: 同步方法或块。
- `native`: 本地方法,使用非Java代码实现。
### 包相关
- `package`: 定义包。
- `import`: 引用其他包中的类或接口。
### 常用集合 (来自 `java.util` 包)
#### ArrayList
- `add(E e)`: 添加元素。
- `get(int index)`: 获取指定位置的元素。
- `remove(int index)`: 移除指定位置的元素。
- `set(int index, E element)`: 修改指定位置的元素。
- `size()`: 获取集合的大小。
- `clear()`: 清空集合。
- `isEmpty()`: 检查集合是否为空。
- `contains(Object o)`: 检查集合是否包含某个元素。
#### LinkedList
- `addFirst(E e)`: 在头部添加元素。
- `addLast(E e)`: 在尾部添加元素。
- `removeFirst()`: 移除头部元素。
- `removeLast()`: 移除尾部元素。
- `getFirst()`: 获取头部元素。
- `getLast()`: 获取尾部元素。
#### HashMap
- `put(K key, V value)`: 存储键值对。
- `get(Object key)`: 根据键获取值。
- `remove(Object key)`: 移除键值对。
- `containsKey(Object key)`: 检查是否包含键。
- `containsValue(Object value)`: 检查是否包含值。
- `keySet()`: 获取所有键的集合。
- `values()`: 获取所有值的集合。
- `entrySet()`: 获取所有键值对的集合。
#### HashSet
- `add(E e)`: 添加元素。
- `remove(Object o)`: 移除元素。
- `contains(Object o)`: 检查是否包含元素。
- `size()`: 获取集合大小。
- `isEmpty()`: 检查集合是否为空。
- `clear()`: 清空集合。
### 字符串处理方法 (来自 `java.lang` 包)
#### String
- `charAt(int index)`: 返回指定索引处的字符。
- `substring(int beginIndex)`: 返回从指定索引开始的子字符串。
- `substring(int beginIndex, int endIndex)`: 返回从开始到结束索引之间的子字符串。
- `indexOf(String str)`: 返回指定字符串在原字符串中的第一次出现的索引。
- `indexOf(String str, int fromIndex)`: 从指定索引开始查找字符串。
- `lastIndexOf(String str)`: 返回指定字符串在原字符串中的最后一次出现的索引。
- `length()`: 返回字符串的长度。
- `replace(char oldChar, char newChar)`: 替换字符。
- `replace(CharSequence target, CharSequence replacement)`: 替换子字符串。
- `toUpperCase()`: 转为大写。
- `toLowerCase()`: 转为小写。
- `trim()`: 去掉首尾空格。
- `split(String regex)`: 拆分字符串。
- `equals(Object anObject)`: 比较字符串是否相等。
- `equalsIgnoreCase(String anotherString)`: 忽略大小写比较字符串是否相等。
- `contains(CharSequence s)`: 判断是否包含子字符串。
- `startsWith(String prefix)`: 判断是否以指定前缀开始。
- `endsWith(String suffix)`: 判断是否以指定后缀结束。
- `toCharArray()`: 转化为字符数组。
### 集合操作的辅助工具 (来自 `java.util.Collections` 类)
#### Collections
- `sort(List<T> list)`: 排序列表。
- `reverse(List<?> list)`: 反转列表顺序。
- `shuffle(List<?> list)`: 随机排列列表元素。
- `binarySearch(List<? extends Comparable<? super T>> list, T key)`: 二分查找。
- `min(Collection<? extends T> coll)`: 返回最小元素。
- `max(Collection<? extends T> coll)`: 返回最大元素。
- `frequency(Collection<?> c, Object o)`: 统计元素在集合中的出现次数。
### 数组操作的辅助工具 (来自 `java.util.Arrays` 类)
#### Arrays
- `sort(T[] a)`: 排序数组。
- `binarySearch(T[] a, T key)`: 二分查找。
- `equals(int[] a, int[] a2)`: 检查两个数组是否相等。
- `fill(int[] a, int val)`: 将数组的每一个元素赋值为指定值。
- `copyOf(T[] original, int newLength)`: 复制数组。
- `toString(int[] a)`: 将数组转换为字符串形式。
### 多线程相关
#### Thread
- `start()`: 启动线程。
- `run()`: 线程执行的任务内容。
- `sleep(long millis)`: 让线程休眠指定时间。
- `interrupt()`: 中断线程。
#### Runnable
- `run()`: 抽象方法,需实现线程执行的任务。
### 输入输出 (来自 `java.io` 包)
- `File`
- `createNewFile()`: 创建新文件。
- `delete()`: 删除文件。
- `exists()`: 检查文件是否存在。
- `getAbsolutePath()`: 获取文件的绝对路径。
- `FileInputStream`
- `read()`: 读取文件内容。
- `close()`: 关闭输入流。
- `FileOutputStream`
- `write(int b)`: 写入文件内容。
- `close()`: 关闭输出流。
- `BufferedReader`
- `readLine()`: 读取一行内容。
- `close()`: 关闭缓冲阅读器。
- `BufferedWriter`
- `write(String s)`: 写入字符串。
- `newLine()`: 写入新行。
- `close()`: 关闭缓冲写入器。
### 日期和时间 (来自 `java.time` 包)
#### LocalDate
- `now()`: 获取当前日期。
- `of(int year, int month, int dayOfMonth)`: 创建指定日期。
- `plusDays(long daysToAdd)`: 添加天数。
- `minusDays(long daysToSubtract)`: 减少天数。
#### LocalTime
- `now()`: 获取当前时间。
- `of(int hour, int minute)`: 创建指定时间。
#### LocalDateTime
- `now()`: 获取当前日期时间。
- `of(int year, int month, int dayOfMonth, int hour, int minute)`: 创建指定日期时间。
### 数学操作 (来自 `java.lang` 包)
#### Math
- `abs(int a)`: 绝对值。
- `ceil(double a)`: 向上取整。
- `floor(double a)`: 向下取整。
- `max(int a, int b)`: 返回较大值。
- `min(int a, int b)`: 返回较小值。
- `pow(double a, double b)`: 幂运算。
- `sqrt(double a)`: 开平方。
- `random()`: 返回0.0到1.0之间的随机数。
Stream
//案例:通过使用stream去实现以张开头且名字为三个字的
List<String> names =new ArrayList<>();
Collections.addAll(names,"张无系","张三丰","周芷若","李文","张以");
//开始使用stream实现
List<String> list2= names.stream().filter(s -> s.startsWith("张")).
filter(a->a.length()==3).collect(Collectors.toList());
System.out.println(list2);
1.获取Stream流
1.如何处理list集合的Stream流
/1.如何处理list集合的Stream流
List<String> name =new ArrayList<>();
Collections.addAll(name,"张无系","张三丰","周芷若","李文","张以");
Stream<String> s1 = name.stream();
2.如何获取set集合的stream流
//2.如何获取set集合的stream流
Set<String> set =new HashSet<>();
Collections.addAll(set,"刘德华","张曼玉","蜘蛛精","马德");
Stream<String> s2 = set.stream();
s2.filter(s -> s.contains("德")).forEach(s -> System.out.println(s));
3.如何获取map集合的stream流
//3.如何获取map集合的stream流
Map<String,Double> map =new HashMap<>();
map.put("古力娜扎",178.0);
map.put("迪丽热巴",180.0);
map.put("妈惹值啊",130.0);
map.put("卡尔扎巴",178.0);
Set<String> keys=map.keySet();
Stream<String> ks = keys.stream();
Collection<Double> values=map.values();
Stream<Double> vs = values.stream();
//使用entrySet
Set<Map.Entry<String, Double>> entries = map.entrySet();
Stream<Map.Entry<String, Double>> kvs = entries.stream();
kvs.filter(e->e.getKey().contains("巴")).forEach(
e-> System.out.println(e.getKey()+"-->"+e.getValue() ) );
4.如何获取数组的stream流
//如何获取数组的stream流、
String [] names ={"张翠山","东方不败","唐大山","独孤求败",};
Stream<String> S1 = Arrays.stream(names);
//法二
Stream<String> S2 =Stream.of(names);
2.Stram流的常见中间方法
需求:取出身高倒数的2名同学,并输出
问题:students.size()-2怎么计算的
//需求:取出身高倒数的2名同学,并输出
students.stream().sorted((o1, o2) -> Double.compare(
o2.getHeight(), o1.getHeight()))
.skip(students.size()-2).forEach(System.out::println);
System.out.println("-----------------------------------");
List<Double> scores =new ArrayList<>();
Collections.addAll(scores,88.5,34.5,99.0,45.0,34.0,67.0);
//需求一:找出成绩大于60分的数据,升序后,再输出
scores.stream().filter(s->s>=60).forEach(s-> System.out.println(s));
List<Student> students =new ArrayList<>();
Student s1 = new Student("蜘蛛精", 26, 168.0);
Student s2 =new Student("蜘蛛精",26,172.5);
Student s3 =new Student("紫霞",23,167.6);
Student s4 =new Student("白晶晶",25,169.5);
Student s5 =new Student("牛魔王",35,183.6);
Student s6 =new Student("牛夫人",34,168.6);
Collections.addAll(students,s1,s2,s3,s4,s5,s6);
//需求:找出年龄大于等于23,小于30的学生,并按照年龄降序进行排序
students.stream().filter(s->s.getAge()>=23&&s.getAge()<=30).
sorted((o1, o2) -> o2.getAge()- o1.getAge()).
forEach(s-> System.out.println(s));
System.out.println("---------------------------------");
//需求:找出身高最高的前三名同学,并输出
students.stream().sorted((o1, o2) ->
Double.compare(o2.getHeight(), o1.getHeight()))
.limit(3).forEach(System.out::println);
System.out.println("--------------------------------------");
//需求:取出身高倒数的2名同学,并输出
students.stream().sorted((o1, o2) ->
Double.compare(o2.getHeight(), o1.getHeight()))
.skip(students.size()-2).forEach(System.out::println);
System.out.println("-----------------------------------");
//需求:找出身高超过168的学生叫什么名字,要求去除重复的名字,并输出
students.stream().filter(s->s.getHeight()>168).
map(Student::getName)
.distinct().forEach(System.out::println);
//distinct去重复,自定义类型对象(希望内容一样就认为重复)
,重写hasCode,equals方法
students.stream().filter(s->s.getHeight()>168).
distinct().forEach(System.out::println);
Stream<String> st1 =Stream.of("张三","李四");
Stream<String> st2 =Stream.of("张三2","李四2","王五");
Stream<String> allST = Stream.concat(st1, st2);
allST.forEach(System.out::println);
3.stream流常见的终结方法
终结 方法是指调用完成后,不会返回新的stream了,没法继续使用流了。
List<Student> students =new ArrayList<>();
Student s1 = new Student("蜘蛛精", 26, 168.0);
Student s2 =new Student("蜘蛛精",26,172.5);
Student s3 =new Student("紫霞",23,167.6);
Student s4 =new Student("白晶晶",25,169.5);
Student s5 =new Student("牛魔王",35,183.6);
Student s6 =new Student("牛夫人",34,168.6);
Collections.addAll(students,s1,s2,s3,s4,s5,s6);
1.请计算出身高超过168有几个学生有几人
long size = students.stream().filter(s -> s.getHeight()
> 168).count();
System.out.println(size);
2.请找出身高最高的学生对象,并输出
Student s = students.stream().max(((o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight()))).get();
System.out.println(s);
3,找出身高最矮的学生对象
Student ss = students.stream().min(((o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight()))).get();
System.out.println(ss);
流只能收集一次,像这样的将流多次就会报错
//流只能收集一次
Stream<Student> studentStream =
students.stream().filter(w -> w.getHeight() > 170);
List<Student> list = studentStream.collect(Collectors.toList());
System.out.println(list);
//set会去重复
Set<Student> set = studentStream.collect(Collectors.toSet());
System.out.println(set);
4.请找出身高超过170的学生对象,并放到一个新集合中返回
//流只能收集一次List<Student> list = students.stream().filter(w -> w.getHeight() > 170).collect(Collectors.toList());
System.out.println(list);
//set会去重复
Set<Student> set = students.stream().filter(w -> w.getHeight() > 170).collect(Collectors.toSet());
System.out.println(set);
5.请找出身高超过170的学生对象,并放到一个新集合中返回
注:在使用map时要使用distinct去重复
Map<String, Double> map = students.stream().filter(a -> a.getHeight() > 170).distinct().collect(Collectors.toMap(a -> a.getName(), a -> a.getHeight()));
System.out.println(map);
6.如何把流收集到数组中(数组中可以重复)
Object[] array = students.stream().filter(w -> w.getHeight() > 170).toArray();
System.out.println(Arrays.toString(array));强制为学生类
Student [] arr = students.stream().filter(w -> w.getHeight() > 170).toArray(len->new Student[len]);
System.out.println(Arrays.toString(arr));