java中的常用类
- 01 字符串相关的类
- 1.1、常用类-String类的概述
- 1.2、 String不同实例化方式的对比
- 1.3 、String不同拼接操作的对比(1)
- 1. 4、 String的一道面试题
- 1.5、JVM涉及字符串的内存结构
- 1.6、String的常用方法1
- 1.7、String的常用方法2
- 1.8、String的常用方法3
- 1.9、String与基本数据类型包装类的转换
- 1.10、String与char[]之间的转换
- 1.11、String与byte[]之间的转换
- 1.13、面试中String算法考查的说明(有时间的时候再看--面试题)
- 1.14、StringBuffer和StringBuilder的介绍
- 1.15、StringBuffer的源码分析
- 1.16、StringBuffer中的常用方法
- 1.17、String、StringBuffer、StringBuilder效率对比
- 1.18 复习
- 02、JDK 8之前的日期时间API
- 03、JDK 8之前的日期时间API(p480-p488 目前用不到,先跳过)
- 04、JDK8中日期时间API的介绍(目前用不到,先跳过)
- 05、Java比较器(重要,以后遇到了可以再看一下p490)
- 06、System类、Math类、BigInteger与BigDecimal
01 字符串相关的类
1.1、常用类-String类的概述
package hxut1;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/5/1 -16:44
* @Description
*
* String的使用
* String表示的字符串
* 1.String声明为final的,不可被继承
* 2.String实现了Serializable接口:表示字符串是支持序列化的(后面会说)
* 实现了Comparable接口:表示String可以比较大小
* 3.String内部定义了final char[] value用于存储字符串数据
* 4.String:代表不可变的字符序列
* 体现:1.当对字符串重新赋值时,需要重写指定内区区域赋值,不能使用原有的value进行赋值
* 2.当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能在原有的value上赋值
* 3.当调用String的replace()方法修改字符或字符串时,也需要重新指定内存区域赋值
* 5.通过字面量的方式(区别于new的方式) 给一个字符串赋值,此时的字符串值声明再字符常量池中.
* 6.字符串常量值是不会存储相同内容的字符串的
*/
public class StringTest {
@Test
public void test1(){
String s1 = "abc"; //字面量的定义方式
String s2 = "abc";
System.out.println(s1 == s2); //比较s1和s2的地址值 //run result=>true
s1 = "dasda";
System.out.println(s1);//run result=> dasda
System.out.println(s2); //run result=>abc
System.out.println("**********************************");
String s3 = "abc";
s3+="def"; //重新换了一个地方
System.out.println(s3);//run result=> abcdef
System.out.println(s2);//run result=> abc
String s4 = "abc";
String s5 = s4.replace('a','d');
System.out.println(s4);//run result=>abc
System.out.println(s5);//run result=>dbc
}
}
1.2、 String不同实例化方式的对比
1.3 、String不同拼接操作的对比(1)
图片1
package hxut1;
import org.junit.Test;
import java.awt.*;
import java.util.ArrayList;
/**
* @author weijiangquan
* @date 2022/5/1 -23:51
* @Description
*
*
* String的实例的两种方式:
* 方式一:通过字面量的方式
* 方式二:通过 new + 构造器的方式
*
* 面试题: String s = new String("abc"):方式创建对象,在内存中创建了几个对象?
* 两个:一个是堆空间中new的结构,另一个是 char[]对应的常量池中的数据:"abc"
* (记住,在常量池中不会放两个一样的字符串,有的化九会拿到现成的,但是还是创建了两个对象)
*
*/
public class StringTest2 {
@Test
public void test2(){
//此时字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中.
String s1 = "javaEE";
String s2 = "javaEE";
//通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟的空间以后对应的地址值
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1 == s4);
System.out.println(s3 == s4);
Person p1 = new Person("Tom",22);
Person p2 = new Person("Tom",23);
System.out.println(p1.name.equals(p2.name));//run result=>true
System.out.println(p1.name == p2.name);//run result=>true
p1.name = "wei";
System.out.println(p2.name); //run result=>Tom
}
@Test
public void Test3(){
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE"+"hadoop";
String s5 = s1+"hadoop";
String s6 = "javaEE"+s2;
String s7 = s1 + s2; //只要右边有变量就会在堆中创建
System.out.println(s3 == s4); //run result=>true
System.out.println(s3 == s5); //run result=>false
System.out.println(s3 == s6);//run result=>false
System.out.println(s5 == s6);//run result=>false
System.out.println(s5 == s7);//run result=>false
System.out.println(s6 == s7);//run result=>false
String s8 = s5.intern(); //返回值得到的s8使用的常量值中已经存在的"javaEEhadoop"
System.out.println(s3 == s8); //run result=>true
}
}
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
本节掌握的不是很好,后续可以补充 (p454)
1. 4、 String的一道面试题
package hxut1.exer;
/**
* @author weijiangquan
* @date 2022/5/2 -16:17
* @Description 一道面试题
*/
public class StringTest {
String str = new String("good");
char[] ch = {'t','e','s','t'};
public void change(String str,char ch[]){
str = "test ok";
ch[0] = 'b';
}
public static void main(String[] args) {
StringTest ex = new StringTest();
ex.change(ex.str,ex.ch);
System.out.println(ex.str); //run result=> good (String是不可变性,和其它引用的数据类型不一样)
System.out.println(ex.ch); //run result=>
}
}
1.5、JVM涉及字符串的内存结构
1.6、String的常用方法1
总结:
只要是有返回值的字符串本身是不变的,体现了字符串的不可变性,本节的知识点,会用就行了,还有就是下面的方法基本都是比较内容的,和字符串通过字面量还是创建对象的方式创建没有关系.
package hxut1.java2;
/**
* @author weijiangquan
* @date 2022/5/2 -17:02
* @Description
*/
import org.junit.Test;
/**
* int length():返回字符串的长度:return value.length
* char charAt(int index):返回某索引处的字符return value[index]
* boolean isEmpty():判断是否是空字符串:return value.length==0
* String toLowerCase():使用默认语言环境,将String中的所有字符转换为小写
* String toUpperCase():使用默认语言环境,将String中的所有字符转换为大写
* String trim():返回字符串的副本,忽略前导空白和尾部空白
* boolean equals(Object obj):比较字符串的内容是否相同
* boolean equals IgnoreCase(String anotherString):与equals方法类似,忽略大小写
* String concat(String str):将指定字符串连接到此字符串的结尾。等价于用“+”
* int compareTo(String anotherString):比较两个字符串的大小
* String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
* String substring(int beginIndex,int endIndex):返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
*/
public class StringMethodTest {
@Test
public void test2(){
String s1 = "HelloWorld";
String s2 = "helloworld";
System.out.println(s1.equals(s2)); //run result=>false
System.out.println(s1.equalsIgnoreCase(s2));//run result=>true
String s3 = "abc";
String s4 =s3.concat("def");
System.out.println(s4);
String s5 = "abc";
String s6 = new String("adb");
System.out.println(s5.compareTo(s6)); //涉及字符串的排序
String s7 = "ahjskdhajk";
String s8 = s7.substring(3);
System.out.println(s8);
System.out.println(s7);
}
@Test
public void test1(){
String s1 = "helloworld";
System.out.println(s1.length()); //run result=>10
System.out.println(s1.charAt(1)); //run result=>e
System.out.println(s1.isEmpty()); //run result=>false
System.out.println(s1.toLowerCase());//run result=>helloworld
System.out.println(s1.toUpperCase());//run result=>HELLOWORLD
System.out.println(s1); //run result=>helloworld(s1是不可变的,仍是原来的字符串)
String s3 = " hello world ";
String s4 = s3.trim();
System.out.println(s3);//run result=> hello world(s3本身没有变)
System.out.println(s4);//run result=>hello world
}
}
1.7、String的常用方法2
package hxut1.java2;
/**
* @author weijiangquan
* @date 2022/5/2 -17:28
* @Description
*
*
*/
import org.junit.Test;
/**
* boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
* boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
* boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
*
* boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
* int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
* int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
* int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
* int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
*
* 注:indexOf和lastIndexOf方法如果未找到都是返回-1
*
*/
public class StringMethodTest2 {
@Test
public void test3(){
String str1 = "adhsjkka";
System.out.println(str1.endsWith("ka")); //run result=>true
System.out.println(str1.startsWith("KA")); //run result=>false (区分大小写)
System.out.println(str1.startsWith("hs",2)); //run result=>true
String str2 = "adh";
System.out.println(str1.contains(str2)); //run result=>true
System.out.println(str1.indexOf("ad")); //run result=>0
System.out.println(str1.indexOf("dh",3));//run result=>-1 找不到返回-1
String s3 = "hellohello";
System.out.println(s3.lastIndexOf("lo")); //run result=>8 (注意这个地方找的是最右边的那一个)
System.out.println(s3.lastIndexOf("he",4)); //run result=>0
}
}
注意://什么情况下,indexOf(str)和lastIndexOf(str)返回值相同?
//情况一:存在唯一的一个str。情况二:不存在str
1.8、String的常用方法3
package hxut1.java2;
/**
* @author weijiangquan
* @date 2022/5/2 -17:49
* @Description
*/
import org.junit.Test;
/**
* 替换:
* String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
* String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
* String replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
* String replaceFirst(String regex, String replacement):使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
*
* 匹配:
* boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
*
* 切片:
* String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
* String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
*
*/
public class StringMethodTest3 {
@Test
public void test4(){
String str1 = "北京烤鸭的天下北京";
String str2 = str1.replace('北','冬');
System.out.println(str2); //run result=>冬京烤鸭的天下冬京
System.out.println(str1); //run result=>北京烤鸭的天下北京
String str3 = str1.replace("北京","西瓜");
System.out.println(str3); //run result=>西瓜烤鸭的天下西瓜
System.out.println(str1); //run result=> 北京烤鸭的天下北京
System.out.println("*************************");
String str = "12hello34world5java7891mysql456";
//把字符串中的数字替换成,,如果结果中开头和结尾有,的话去掉
String string = str.replaceAll("\\d+", ",").replaceAll("^,|,$", "");
System.out.println(string);
System.out.println("*************************");
str = "12345";
//判断str字符串中是否全部有数字组成,即有1-n个数字组成
boolean matches = str.matches("\\d+");
System.out.println(matches);
String tel = "0571-4534289";
//判断这是否是一个杭州的固定电话
boolean result = tel.matches("0571-\\d{7,8}");
System.out.println(result);
System.out.println("*************************");
System.out.println("*************************");
str = "hello|world|java";
String[] strs = str.split("\\|");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
System.out.println();
str2 = "hello.world.java";
String[] strs2 = str2.split("\\.");
for (int i = 0; i < strs2.length; i++) {
System.out.println(strs2[i]);
}
}
}
1.9、String与基本数据类型包装类的转换
package hxut1.java3;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/5/2 -18:05
* @Description 涉及到String和其它的包装类型的转换
*/
public class StringTest1 {
// String与基本数据类型包装类的转换
// String --> 基本数据类型,包装类 要调用包装类静态方法: parseXxx(str)
// 将借本类型和包装类 --->String:调用String重载的valueOf(xxx)
@Test
public void test1(){
String str1 = "123"; //在常量池中
// int num = (int)str1; 错误的
int num = Integer.parseInt(str1);
System.out.println(num);
// 方式一
String str2 = String.valueOf(num);
// 方式二
String str3 = num + ""; //在堆中
System.out.println(str3 == str1); //run result=>false
// 注意:只要有变量参与了就在堆中
System.out.println(str2); //run result=>123 这个时候是带有引号的数字
}
}
1.10、String与char[]之间的转换
/**
* String和char之间的转换
* String --> char[] 调用toCharArray()
* char[] --->string 调用String的构造器
*/
@Test
public void test2(){
String str1 = "abc123";
char[] charArray = str1.toCharArray();
for (int i =0;i<charArray.length;i++){
System.out.println(charArray[i]);
}
char[] arr = new char[]{'1','s','s','a'};
String str2 = new String(arr);
System.out.println(str2);//run result=>1ssa
}
1.11、String与byte[]之间的转换
p462
/**
* String 与 byte[]之间的转换
*
* String ---> byte[]: 调用String的getBytes()
*/
@Test
public void test3() throws UnsupportedEncodingException {
String str1 = "abc123";
byte[] bytes = str1.getBytes(); //使用默认的字符集,进行转换
System.out.println(bytes); //得到的是地址
System.out.println(Arrays.toString(bytes)); //调用的是重写之后的toString获得是
byte[] gbks = str1.getBytes("GBK");//使用gbk进行编码
System.out.println("*********************");
String s = new String(bytes);
}
1.13、面试中String算法考查的说明(有时间的时候再看–面试题)
常量的算法题
https://blog.csdn.net/PorkBird/article/details/113695807
1.14、StringBuffer和StringBuilder的介绍
package hxut1.java4;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/5/2 -19:33
* @Description 关于String和StringBuilder的使用
*/
public class StringBufferBuilderTest {
/**
* String,StringBuffer,StringBuilder三者的异同(高频面试题)
*
*
* String:不可变的字符序列
* StringBuffer:可变的字符序列:线程安全的,效率低
* StringBuilder:可变的字符序列: JDK5.0新增 线程不安全,效率高
*
* 它们三个底层都是用char[]数组存储的
* tips:如何选择: 如果是的多线程的问题的化,就使用StringBuffer,否则,选择StringBuilder
*/
@Test
public void test1(){
StringBuffer sb1 = new StringBuffer("abc");
sb1.setCharAt(0,'m');
System.out.println(sb1); //run result=>mbc
}
}
1.15、StringBuffer的源码分析
package hxut1.java4;
/**
* @author weijiangquan
* @date 2022/5/2 -19:44
* @Description StringBuffer源码分析
*
*
* 源码分析
* String str = new String(); //new char[0];
* String str1 = new String("abc"); //new char[]{'a','b','c'};
*
* StringBuffer sb1 = new StringBuffer();//char[] value = new char[16] 相当于底层创建了一个长度是16的数组
* System.out.println(sb1.length());
* sb1.append('a'); //value = 'a';
* sb1.append('b'); //value = 'b';
*
* StringBuffer sb2 = new StringBuffer("abc"); //char[] value = new char["abc".length()+16];
*
* 问题1:System.out.println(sb2.length()); //3
* 问题2:扩容问题:如果添加的数据底层数组盛不下了,那就需要扩容底层数组
* 默认情况下,扩容为原来的2倍+2,同时将原有数组中的元素复制到新的数组中
*
* 指导意义:开发中建议大家使用:StringBuffer(int capacity) 或 StringBuilder
*/
public class StringBufferBuilderTest1 {
public static void main(String[] args) {
StringBuffer sb1 = new StringBuffer();
sb1.append('a');
StringBuffer sb2 = new StringBuffer();
System.out.println(sb2.length()); //run result=>0
}
}
注意一点:
虽然底层给了初始的长度,但是当
str.length
的时候只会打印你自己添加的内容的长度,因为对length()
进行了重写
详细源码分析:(p466)
1.16、StringBuffer中的常用方法
package hxut1.java4;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/5/2 -19:44
* @Description StringBuffer源码分析
*
*
* 源码分析
* String str = new String(); //new char[0];
* String str1 = new String("abc"); //new char[]{'a','b','c'};
*
* StringBuffer sb1 = new StringBuffer();//char[] value = new char[16] 相当于底层创建了一个长度是16的数组
* System.out.println(sb1.length());
* sb1.append('a'); //value = 'a';
* sb1.append('b'); //value = 'b';
*
* StringBuffer sb2 = new StringBuffer("abc"); //char[] value = new char["abc".length()+16];
*
* 问题1:System.out.println(sb2.length()); //3
* 问题2:扩容问题:如果添加的数据底层数组盛不下了,那就需要扩容底层数组
* 默认情况下,扩容为原来的2倍+2,同时将原有数组中的元素复制到新的数组中
*
* 指导意义:开发中建议大家使用:StringBuffer(int capacity) 或 StringBuilder
*/
public class StringBufferBuilderTest1 {
public static void main(String[] args) {
StringBuffer sb1 = new StringBuffer();
sb1.append('a');
StringBuffer sb2 = new StringBuffer();
System.out.println(sb2.length()); //run result=>0
}
/**
* StringBuffer的常用方法:
*
* StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
* StringBuffer delete(int start,int end):删除指定位置的内容
* StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
* StringBuffer insert(int offset, xxx):在指定位置插入xxx
* StringBuffer reverse() :把当前字符序列逆转
* public int indexOf(String str)
* public String substring(int start,int end):返回一个从start开始到end索引结束的左闭右开区间的子字符串
* public int length()
* public char charAt(int n )
* public void setCharAt(int n ,char ch)
**/
@Test
public void test2(){
StringBuffer s1 = new StringBuffer("abc");
s1.append(1);;
s1.append('1');
System.out.println(s1);
System.out.println(s1.length());
s1.delete(2,3);
System.out.println(s1); //run result=>ab11
s1.replace(1,3,"weijiangquan");
System.out.println(s1);
s1.insert(2,false);
System.out.println(s1);
}
}
* 总结:
* 增:append(xxx)
* 删:delete(int start,int end)
* 改:setCharAt(int n ,char ch) / replace(int start, int end, String str)
* 查:charAt(int n )
* 插:insert(int offset, xxx)
* 长度:length();
* 遍历:for() + charAt() / toString()
*
1.17、String、StringBuffer、StringBuilder效率对比
import org.junit.Test;
/**
* 关于StringBuffer和StringBuilder的使用
*/
public class StringBufferBuilderTest {
/**
* 对比String、StringBuffer、StringBuilder三者的效率:
* 从高到低排列:StringBuilder > StringBuffer > String
*
*/
@Test
public void test3(){
//初始设置
long startTime = 0L;
long endTime = 0L;
String text = "";
StringBuffer buffer = new StringBuffer("");
StringBuilder builder = new StringBuilder("");
//开始对比
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer的执行时间:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder的执行时间:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
text = text + i;
}
endTime = System.currentTimeMillis();
System.out.println("String的执行时间:" + (endTime - startTime));
}
}
字符串类学习的总结:
对于字符串对于应用部分可以灵活的使用,但是对于底层的源码不够熟悉,有待提高
1.18 复习
更多的复习:(p472-p478)
02、JDK 8之前的日期时间API
2.1、System类中获取时间戳的方法
System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
此方法适于计算时间差。
计算世界时间的主要标准有:
- UTC(Coordinated Universal Time)
- GMT(Greenwich Mean Time)
- CST(Central Standard Time)
package hxut1.java5;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/5/2 -20:40
* @Description JDK8之日期和时间的API测试
*/
public class DateTimeTest {
//1.System类中currentTimeMillis()方法
@Test
public void test1(){
long time = System.currentTimeMillis();
//返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差
//称为时间戳
System.out.println(time);
}
}
2.2、Java中两个Date类的使用
package hxut1.java5;
import org.junit.Test;
import java.util.Date;
/**
* @author weijiangquan
* @date 2022/5/2 -20:40
* @Description JDK8之日期和时间的API测试
*/
public class DateTimeTest {
/**
* java.util.Date类
* |--java.sql.Date类
*
* 1.两个构造器的使用
* >
*
*
* 2.两个方法使用
* > toString() 显示当前的年,月,日,时,分,秒
* > getTime():或取毫秒数相距1970年
* 3.java.lang.Date对应的时数据库中日期类型的变量
* > 如何实例化
* > 如何将java.util.Data对象转换为java.sql.Date对象
*/
@Test
public void test2(){
//构造器一: Date():创建一个对应当前时间的Date对象
Date date1 = new Date();
System.out.println(date1.toString()); //等同于下面的方式
System.out.println(date1); //println会帮忙调用toString()方法
System.out.println(date1.getTime()); //毫秒
// 构造器二:创建指定毫秒数的Date对象
Date date2 = new Date(16514962802111L); //run result=>Sun May 03 17:40:02 CST 2493
System.out.println(date2);
System.out.println(date2.toString());
java.sql.Date date4 = new java.sql.Date(11212112121L);
System.out.println(date4);
// 如何将java.util.Data对象转换为java.sql.Date对象
// 情况一
java.util.Date date12 = new java.sql.Date(1623478L);
java.sql.Date dates = (java.sql.Date) date12;
// 情况二
Date date33 = new Date();
java.sql.Date date222 = new java.sql.Date(date33.getTime());
System.out.println(date222);
}
//1.System类中currentTimeMillis()方法
@Test
public void test1(){
long time = System.currentTimeMillis();
//返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差
//称为时间戳
System.out.println(time);
}
}
2.3、idea中debug的使用
package hxut1.java6;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/5/2 -22:17
* @Description debug的使用
*/
public class javaStringBuffer {
@Test
public void testStringBuffer(){
String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);
System.out.println(str.length()); //4
System.out.println(sb); //"null"
StringBuffer sb1 = new StringBuffer(str); //抛出空指针异常
System.out.println(sb1);
}
}
03、JDK 8之前的日期时间API(p480-p488 目前用不到,先跳过)
3.1、SimpleDateFormat的使用
04、JDK8中日期时间API的介绍(目前用不到,先跳过)
4.1 idea中如何导入module的方式
05、Java比较器(重要,以后遇到了可以再看一下p490)
5.1、概述
Java中的对象,正常情况下,只能进行比较:==或 != 。不能使用 >或<的,但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。 如何实现?使用两个接口中的任何一个:Comparable或 Comparator
Java实现对象排序的方式有两种:
- 自然排序:java.lang.Comparable
- 定制排序:java.util.Comparator
5.2、Comparable自然排序举例
package hxut2.java1;
import org.junit.Test;
import java.util.Arrays;
/**
* @author weijiangquan
* @date 2022/5/3 -17:04
* @Description
* 一:说明,java中的对象,正常情况下,只能进行比较: == 或 !=,不能使用 > 或 <的
* 但是在开发的场景中又需要对多个对象进行排序,就需要比较对象的大小.
* 如何实现?使用两个接口中的任何一个:Comparable 或 Comparator
*
* 二.Comparable接口的使用
*
*
*/
public class CompareTest {
/**
* comparable接口的使用
* 1.像String,包装类等实现了Comparable接口,重写了compareTo()方法,给出比较两个对象大小的方式
* 2.像String,包装类重写compareTo()方法以后,进行了从小到大的排序
* 3. 重写compareTo(obj)的规则:
* 如果当前对象this大于形参对象obj,则返回正整数,
* 如果当前对象this小于形参对象obj,则返回负整数,
* 如果当前对象this等于形参对象obj,则返回零。
**/
@Test
public void test1(){
String[] arr = new String[]{"AA","CC","MM","GG","JJ","DD","ZZ","KK"};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
5.3、自定义类实现Comparable自然排序
1 测试类
import org.junit.Test;
import java.util.Arrays;
public class CompareTest {
/**
* 4.对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。
* 在compareTo(obj)方法中指明如何排序
*/
@Test
public void test2(){
Goods[] arr = new Goods[5];
arr[0] = new Goods("lenovoMouse",34);
arr[1] = new Goods("dellMouse",43);
arr[2] = new Goods("xiaomiMouse",12);
arr[3] = new Goods("huaweiMouse",65);
arr[4] = new Goods("microsoftMouse",43);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
2、Goods类
/**
* 商品类
*/
public class Goods implements Comparable{
private String name;
private double price;
public Goods() {
}
public Goods(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;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
//指明商品比较大小的方式:按照价格从低到高排序,再按照产品名称从高到低排序
@Override
public int compareTo(Object o) {
// System.out.println("**************");
if(o instanceof Goods){
Goods goods = (Goods)o;
//方式一:
if(this.price > goods.price){
return 1;
}else if(this.price < goods.price){
return -1;
}else{
// return 0;
return -this.name.compareTo(goods.name);
}
//方式二:
// return Double.compare(this.price,goods.price);
}
// return 0;
throw new RuntimeException("传入的数据类型不一致!");
}
}
5.4、使用Comparator实现定制排序
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
/**
* 一、说明:Java中的对象,正常情况下,只能进行比较:== 或 != 。不能使用 > 或 < 的
* 但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。
* 如何实现?使用两个接口中的任何一个:Comparable 或 Comparator
*
* 二、Comparable接口与Comparator的使用的对比:
* Comparable接口的方式一旦一定,保证Comparable接口实现类的对象在任何位置都可以比较大小。
* Comparator接口属于临时性的比较。
*/
public class CompareTest {
/**
* Comparator接口的使用:定制排序
* 1.背景:
* 当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,
* 或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,
* 那么可以考虑使用 Comparator 的对象来排序
* 2.重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
* 如果方法返回正整数,则表示o1大于o2;
* 如果返回0,表示相等;
* 返回负整数,表示o1小于o2。
*/
@Test
public void test3(){
String[] arr = new String[]{"AA","CC","KK","MM","GG","JJ","DD"};
Arrays.sort(arr,new Comparator(){
//按照字符串从大到小的顺序排列
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof String && o2 instanceof String){
String s1 = (String) o1;
String s2 = (String) o2;
return -s1.compareTo(s2);
}
// return 0;
throw new RuntimeException("输入的数据类型不一致");
}
});
System.out.println(Arrays.toString(arr));
}
@Test
public void test4(){
Goods[] arr = new Goods[6];
arr[0] = new Goods("lenovoMouse",34);
arr[1] = new Goods("dellMouse",43);
arr[2] = new Goods("xiaomiMouse",12);
arr[3] = new Goods("huaweiMouse",65);
arr[4] = new Goods("huaweiMouse",224);
arr[5] = new Goods("microsoftMouse",43);
Arrays.sort(arr, new Comparator() {
//指明商品比较大小的方式:按照产品名称从低到高排序,再按照价格从高到低排序
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Goods && o2 instanceof Goods){
Goods g1 = (Goods)o1;
Goods g2 = (Goods)o2;
if(g1.getName().equals(g2.getName())){
return -Double.compare(g1.getPrice(),g2.getPrice());
}else{
return g1.getName().compareTo(g2.getName());
}
}
throw new RuntimeException("输入的数据类型不一致");
}
});
System.out.println(Arrays.toString(arr));
}
Comparable接口与Comparator的使用的对比:
- Comparable接口的方式一旦一定,保证Comparable接口实现类的对象在任何位置都可以比较大小。
- Comparator接口属于临时性的比较。
06、System类、Math类、BigInteger与BigDecimal
6.1、System类
package hxut3;
import org.junit.Test;
/**
* @author weijiangquan
* @date 2022/5/3 -18:27
* @Description
*
* 其它常用类的使用
* 1.System
* 2.Math
* 3.BIgInteger 和 BigDecimal
*
*/
public class OtherClassTest{
@Test
public void test1(){
String javaVersion = System.getProperty("java.version");
System.out.println("java的version:" + javaVersion);
String javaHome = System.getProperty("java.home");
System.out.println("java的home:" + javaHome);
String osName = System.getProperty("os.name");
System.out.println("os的name:" + osName);
String osVersion = System.getProperty("os.version");
System.out.println("os的version:" + osVersion);
String userName = System.getProperty("user.name");
System.out.println("user的name:" + userName);
String userHome = System.getProperty("user.home");
System.out.println("user的home:" + userHome);
String userDir = System.getProperty("user.dir");
System.out.println("user的dir:" + userDir);
}
}
6.2、Math类
java.lang.Math提供了一系列静态方法用于科学计算。其方法的参数和返回值类型一般为double型。
- abs 绝对值
- acos,asin,atan,cos,sin,tan 三角函数
- sqrt 平方根
- pow(double a,doble b) a的b次幂
- log 自然对数
- exp e为底指数
- max(double a,double b)
- min(double a,double b)
- random() 返回0.0到1.0的随机数
- long round(double a) double型数据a转换为long型(四舍五入)
- toDegrees(double angrad) 弧度—>角度
- toRadians(double angdeg) 角度—>弧度
6.3、BigInteger与BigDecimal
- Integer类作为int的包装类,能存储的最大整型值为2^31 -1,Long类也是有限的,最大为2^63 -1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。
- java.math包的BigInteger可以表示不可变的任意精度的整数。BigInteger提供所有Java 的基本整数操作符的对应物,并提供java.lang.Math 的所有相关方法。另外,BigInteger还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。
构造器 - BigInteger(String val):根据字符串构建BigInteger对象
import org.junit.Test;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* 其他常用类的使用
* 1.System
* 2.Math
* 3.BigInteger 和 BigDecimal
*/
public class OtherClassTest {
@Test
public void test2() {
BigInteger bi = new BigInteger("1243324112234324324325235245346567657653");
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bi);
// System.out.println(bd.divide(bd2));
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2, 25, BigDecimal.ROUND_HALF_UP));
}
}