文章目录
常用类
概述
- 字符串相关类 String类及常用方法
- StringBuffer
- StringBuilder
- JDK8之前的日期时间API
- System静态方法
- Date类
- Calendar类
- SimpleDateFormat类
- JDK8中新日期时间API
- LocalDate.LocalTime,LocalDateTime
- Instant
- DateTimeFormatter
- 其他类
- Java比较器
- Comparable接口
- Comparator接口
- System类
- Math类
- BigInteger,BigDecimal
String类
概述
- String:字符串:使用一对" "引起来表示
- String声明为final的,不可被继承
- String实现了Serializable接口:表示字符串是支持序列化的.
实现了Comparable接口:表示String可以比较大小 - String内部定义了fianl char[ ] value用于存储字符串数据.
- String:代表不可变的字符序列.称为:不可变性
- 当对字符串重新赋值时,需要重新指定内存区域赋值,不能使用原有的value进行赋值.
- 当对现有的字符串进行连接操作时,需要重新指定内存区域赋值,不能使用原有的value进行赋值.
- 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值.
- 通过字面量的方式(区别于new) 给一个字符串赋值,此时的字符串值声明在方法区的字符串常量池中.
- 字符串常量池中是不会存储相同内容的字符串的.
package StringDemo;
import org.junit.Test;
public class StringTest {
@Test
public void test() {
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);//true
s1 = "hello";
System.out.println(s1 == s2);//false
String s3 = "abc";
System.out.println(s1 == s3);//false
System.out.println(s2 == s3);//true
s3 += "def";
System.out.println("s3=" + s3);//abcdef
System.out.println(s2 == s3);//false
String s4 = s2.replace("a", "aa");
System.out.println(s4);//aabc
System.out.println(s4 == s3);//false
}
}
String对象的创建
- String的实例化方式:
- 通过字面量定义的方式
- 通过new+构造器的方式.
package StringDemo;
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
}
public class StringTest2 {
public static void main(String[] args) {
Person person1 = new Person("Tom", 12);
Person person2 = new Person("Tom", 12);
System.out.println(person1==person2);//false
System.out.println(person1.name== person2.name);//true
System.out.println(person1.name.equals(person2.name));//true
}
}
String字符串的特性
- 常量与常量的拼接结果再常量池中,常量池中不会存在相同内容的常量,所以==比较的地址值为true
- 如果其中有一个是变量,结果就在堆中,==比较的地址值就不同了,false
- 如果拼接的结果是调用intern()方法,返回值就在常量池中.
- 分析:涉及值传递与字符
- str是String,因为字符串的不可变性,所以ex.str输出为good
- ch[ ] 为数组,地址值赋值给形参,地址值相同,改变test为best
JVM中字符串的内存结构
- String字符串存储在方法区的常量池中
- 具体学习JVM虚拟机相关知识
面试题
- String s=new String(“abc”);方式创建对象,在内存中创建了几个对象?
* 两个,一个是堆空间中new结构,另一个是char[ ]对应的常量池中的数据"abc".
String类的常用方法
- length():返回字符串长度
- charAt():返回索引处的字符
- isEmpty():判断字符串是否为空
- toLowerCase():将所有字符转换为小写,赋值给新的变量,本身的字符串是不可变的.
- toUpperCase():将所有字符转换为大写,赋值给新的变量,本身的字符串是不可变的.
- trim():去除首尾空格
- equals():比较字符串的内容是否相同
- equalsIgnoreCase():比较字符串的内容是否相同,忽略大小写
- concat():将指定字符串连接到此字符串的结尾,等价于"+".
- compareTo():比较两个字符串的大小,用前一个数减去后一个数,返回int,涉及到字符串排序
- substring(index):字符串切割,从beginIndex(包含)开始截取,返回一个新的字符串.
- substring(index1,index2):字符串切割,从index1(包含)开始,到index2(不包含)结束,返回一个新的字符串,左闭右开.
package string.method;
import org.junit.Test;
public class Demo {
@Test
public void test() {
String s1 = "HelloWorld";
System.out.println(s1.length());
System.out.println(s1.charAt(5));
System.out.println(s1.isEmpty());
System.out.println(s1.toLowerCase());
System.out.println(s1.toUpperCase());
String s2 = " Hel lo Wor ld ";
String s3 = s2.trim();
System.out.println("-------"+s2+"---------");
System.out.println("-------"+s3+"---------");
System.out.println(s2.equals(s3));//false
}
@Test
public void test2(){
String s1="helloworld";
String s2="HelloWorld";
String s3="123";
System.out.println(s1.equalsIgnoreCase(s2));
String s4 = s1.concat(s3);
System.out.println(s4);
}
@Test
public void test3(){
String s1="abc";
String s2="abe";
int num = s1.compareTo(s2);
System.out.println(num);
}
@Test
public void test4(){
String s="a至尊宝的月光宝盒c";
String s1 = s.substring(3);
System.out.println(s1);
String s2 = s.substring(1, s.length() - 1);
System.out.println(s2);
}
}
- endWith(String suffix):判断此字符串是否以指定字符串结束.
- startsWith(String prefix):判断此字符串是否以指定字符串开始.
- startsWith(String prefix,int toffset):判断此字符串是否以指定字符串从指定索引开始.
- contains():判断此字符串是否包含指定字符串,返回boolean.
- indexOf():返回指定字符串在此字符串中第一次出现的索引,如果不包含指定字符串,返回-1
- indexOf(str,fromIndex):返回指定字符串在此字符串在指定位置往后,第一次出现的索引,如果不包含指定字符串,返回-1
- lastIndexOf():返回指定字符串在此字符串中最右边出现的索引.(从右往左搜索,但索引还是从0往后数.)
- lastIndexOf(str,fromIndex):返回指定字符串在此字符串中到指定索引处,最右边出现的索引,从右往左搜索,但索引还是从0往后数.
什么情况下,indexOf和lastIndexOf返回相同?情况一:字符串唯一,情况二:不存在指定字符串.
替换: - replace(char oldChar, char newChar) :返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
- replace(CharSequence target, CharSequence replacement) : 使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
- replaceAll(String regex, String replacement) :使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
- replaceFirst(String regex, String replacement) :使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
- matches(String regex) :判断此字符串是否匹配给定的正则表达式。(补充正则表达式相关知识)
切割 - split(String regex) : 返回根据给定正则表达式的匹配拆分此字符串。(返回string [ ])
- split(String regex, int limit) :返回根据匹配给定的正则表达式来拆分此字符串。(返回 string[ ],limit限制数组中元素的个数,或者说切割几次)
package string.method;
import org.junit.Test;
import java.util.Arrays;
public class Demo2 {
@Test
public void test() {
String s = "helloworld";
boolean s1 = s.endsWith("ld");
System.out.println(s1);
boolean s2 = s.startsWith("he");
System.out.println(s2);
boolean s3 = s.startsWith("ll", 2);
System.out.println(s3);
}
@Test
public void test2() {
String s = "helloworld";
String s1 = "llow";
boolean s2 = s.contains(s1);
System.out.println(s2);
int s3 = s.indexOf(s1);
System.out.println(s3);
int s4 = s.indexOf(s1, 5);
System.out.println(s4);
s = "helloworlld";
System.out.println(s.lastIndexOf("ll"));
System.out.println(s.lastIndexOf("ll", 3));
System.out.println(s.lastIndexOf("ll", 2));
System.out.println(s.lastIndexOf("ll", 1));
}
@Test
public void test3() {
String s1 = "zzb的月光宝盒";
String s2 = "至尊宝";
String s = s1.replace("zzb", s2);
System.out.println(s);
}
@Test
public void test4() {
String s1 = "12345678";
boolean matches = s1.matches("\\d+");
System.out.println(matches);
}
@Test
public void test5() {
String s = "至尊宝|的|月光宝盒";
String[] str = s.split("\\|");
System.out.println(Arrays.toString(str));
for (int i = 0; i < str.length; i++) {
System.out.print(str[i]);
}
System.out.println();
String[] str1 = s.split("\\|", 3);
System.out.println(Arrays.toString(str1));
for (int i = 0; i < str1.length; i++) {
System.out.println(str1[i]);
}
}
}
String类与其他结构之间的转换
String与基本数据类型,包装类之间的转换
- 将String—>基本类型,包装类:调用包装类的静态方法:parseXxx(str)
- 将基本数据类型,包装类—>String类型:调用String重载的valueOf(xxx)或者用字符串拼接基本类型
package string.method;
import org.junit.Test;
public class Demo3 {
@Test
public void test(){
String s="123";
int i = Integer.parseInt(s);
System.out.println(i);
}
@Test
public void test2(){
int i=123;
String s = String.valueOf(i);
System.out.println(s);
System.out.println(""+i);
}
}
String与char[ ]之间的转换
- String—>char[ ]
- char[ ] toCharArray()
将此字符串转换为一个新的字符数组。
- char[ ] toCharArray()
- char[ ]—>String
- 调用String的构造器
package string.method;
import org.junit.Test;
import java.util.Arrays;
public class Demo4 {
@Test
public void test() {
String s = "abc";
char[] chars = s.toCharArray();
for (char c : chars) {
System.out.println(c);
}
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
}
@Test
public void test2() {
char[] c = {'h', 'e', 'l', 'l', 'o'};
String str1 = Arrays.toString(c);
System.out.println(str1);
String str = new String(c);
System.out.println(str);
}
}
String与byte[ ]之间的转换
-
String—>byte[ ]
- 调用String的getBytes()
- byte[ ] getBytes()
使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 - byte[ ] getBytes(String charsetName)
使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
-
byte[ ]—>String
- 调用String的构造器
package string.method;
import org.junit.Test;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Demo5 {
@Test
public void test() throws UnsupportedEncodingException {
String str = "abc123至尊宝";
byte[] bytes = str.getBytes();//使用默认字符集进行转换
System.out.println(Arrays.toString(bytes));
byte[] gbks = str.getBytes("gbk");//使用指定字符集进行转换
System.out.println("gbks = " + Arrays.toString(gbks));
//byte[]--->String
String str1 = new String(bytes);
System.out.println(str1);
String gbk = new String(gbks, "gbk");
System.out.println(gbk);
}
}
面试题
- 字符串拼接
String s1="java";
String s2="javaEE";
String s3=s1+"EE";
//变量拼接,地址值不同
System.out.println(s2==s3);//false
//使用final变为一个常量,属于常量与常量拼接
final String s4="java";
String s5=s4+"EE";
System.out.println(s2==s5);//true
关于StringBuffer和StringBuilder
- String,StringBuffer,StringBuilder三者的区别:
- String:不可变的字符序列,底层使用char[ ]存储.final char [] value
- StringBuffer:可变的字符序列,线程安全的,效率低,底层使用char[ ]存储. char [] value
- StringBuilder:可变的字符序列,jdk5.0新增的,线程不安全的,效率高,底层使用char[ ]存储.char [] value
- StringBuffer和StringBuilder继承和实现的相同.
源码分析:
- String底层是一个不可变的char [] 数组
- StringBuffer和StringBuilder底层是可变的char[],初始化长度为16,扩容为(2倍+2)
package StringBufferAndStringBuilder;
import org.junit.Test;
public class TestDemo {
@Test
public void test1(){
int [] arr1=new int[10];
int i = (arr1.length << 1) + 2;
System.out.println(arr1.length);
System.out.println(i);
}
}
package StringBufferAndStringBuilder;
/**
* 问题一:System.out.println(sb2.length());
* StringBuffer底层是一个长度为16的char[]数组,append是在添加的字符串后保留16的长度,但是 实际长度还是数组中的元素个数.
* 问题二:扩容问题,如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组.
* 默认情况下,扩容为原来容量的2倍+2,同时将原有数组中的元素复制到新的数组中.
*
* 意义:开发中建议使用:StringBuffer(int capacity) 或 StringBuilder(int capacity)
*/
public class Demo {
public static void main(String[] args) {
String str = new String();//char [] value = new char[0];
String str1 = new String("abc");//char [] value = new char[]{'a','b','c'};
StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度是16的数组
// sb1.append('a');//value[0] = 'a';
// sb1.append('b');//value[1] = 'b';
StringBuilder sb2 = new StringBuilder("abc");//char[] value=new char["abc".length()+16];
System.out.println(sb1.length());//0
System.out.println(sb2.length());//3
StringBuilder sb3= new StringBuilder();
System.out.println(sb3.length());//0
}
}
StringBuffer,StringBuilder类的常用方法
-
StringBuffer(返回) append(xxx): 提供了很多的append()方法,用于进行字符串拼接.
-
StringBuffer delete(int start, int end)
移除此序列的子字符串中的字符。 左闭右开,删除元素. -
StringBuffer replace(int start, int end, String str)
使用给定 String 中的字符替换此序列的子字符串中的字符。 开始>结束,替换新的字符串. -
StringBuffer insert(int offset, String str)
将字符串插入此字符序列中。
-
StringBuffer reverse()
将此字符序列用其反转形式取代。 -
int indexOf(String str)
返回第一次出现的指定子字符串在该字符串中的索引。 -
String substring(int start, int end)
返回一个新的字符串,左闭右开. -
char charAt(int index)
返回此序列中指定索引处的 char 值。 -
void setCharAt(int index, char ch)
将给定索引处的字符设置为 ch。
-
总结
- 增 append(xxx)
- 删 delete(int start, int end)
- 改 setCharAt(int index, char ch) / replace(int start, int end, String str)
- 查 charAt(int index)
- 插 insert(int offset, String str)
- 长度: length()
- 遍历: for()+charAt() / Arrays.toString()
-
效率对比:StingBuilder>StringBuffer>String
面试题
- str.length()为空
JDK8之前 日期时间API
-
①java.lang.System类
long time = System.currentTimeMillis();
System类提供的public static long currenTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差.
此方法适用于计算时间差. -
②java.util.Date类(java.sql.Date):表示特定的瞬间,精确到毫秒
两个构造器的使用
- 构造器 Date(): 使用无参构造器创建的对象可以获取本地当前时间.创建一个对应当前时间的Date对象
- 构造器 Date(long date):创建指定毫秒数的Date对象.
- java.sql.Date对应这数据库中的日期类型的变量
如何实例化:java.sql.Date date2 = new java.sql.Date(23554635676L);
两个常用方法的使用:
- long getTime()
获取当前Date对象对应的毫秒数.(时间戳)
返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。 - String toString()
显示年月日时分秒.
把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)。
-
如何将sql.Date对象转换为util.Date对象?
多态,直接转,util是sql的父类 -
如何将java.util.Date对象转换为java.sql.Date对象?
- 强转
Date utildate = new java.sql.Date(23525636L);
java.sql.Date sqldate= (java.sql.Date) utildate; - 方法 getTime()
Date utildate = new Date(55667645634L);
java.sql.Date sqldate = new java.sql.Date(utildate.getTime());//1970-09-30
- 强转
package DateTimeTest;
import org.junit.Test;
import java.util.Date;
/**
* JDK8之前日期和时间的API测试
*/
public class TimeTest {
@Test
public void test1() {
//返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差.
//称为时间戳
long time = System.currentTimeMillis();
System.out.println(time);
}
@Test
public void test2() {
Date date = new Date();
System.out.println(date.toString());//Mon Jul 05 11:54:19 CST 2021
System.out.println(date.getTime());//1625457259989
Date date1 = new Date(13456345245L);
System.out.println(date1);//Sat Jun 06 01:52:25 CST 1970
java.sql.Date date2 = new java.sql.Date(23554635676L);
System.out.println(date2);
// Date utildate = new java.sql.Date(23525636L);
// java.sql.Date sqldate= (java.sql.Date) utildate;
Date utildate = new Date(55667645634L);
java.sql.Date sqldate = new java.sql.Date(utildate.getTime());//1970-09-30
}
}
- ③java.text.SimpleDateFormat类
java.text.SimpleDateFormat类是一个不与语言环境有关的方式来格式化和解析日期的具体类.
它允许进行格式化:日期->文本,解析:文本->日期
SimpleDateFormat的使用: 对日期Date类的格式化和解析
- 格式化: 日期->字符串 fromat()
- 解析:格式化的逆过程,字符串–>日期 parse()
package SimpleDateFormat;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Demo1 {
@Test
public void test1() throws ParseException {
//使用默认的构造器实例化new SimpleDateFormat();
SimpleDateFormat sdf = new SimpleDateFormat();
Date date = new Date();
System.out.println(date);
String format = sdf.format(date);//格式化
System.out.println(format);
//解析:字符串->Date 日期
String str="21-7-5 下午3:50";
Date parse = sdf.parse(str);//解析
System.out.println(parse);
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String format1 = sdf1.format(date);//格式化
System.out.println(format1);
Date parse1 = sdf1.parse("2021-07-05 04:00:53");//解析
System.out.println(parse1);
}
@Test
public void testBirthady() throws ParseException {
String birth="1995-05-01";
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
Date parse = f.parse(birth);
System.out.println(parse);
java.sql.Date date = new java.sql.Date(parse.getTime());
System.out.println(date);
}
}
- ④Calendar(日历类)
Calendar日历类的使用:它是一个抽象类不能实例化
1. 实例化的方式:
1. 使用Calendar.getInstance()方法(常用)
2. 调用它的子类GregorianCalendar 的构造器
2. 常用方法:
1. get()
2. set()
3. add()
4. getTime()
5. setTime()
package DateTimeTest;
import org.junit.Test;
import java.util.Calendar;
import java.util.Date;
public class CalendarTest {
@Test
public void test() {
//1.实例化
//方式一:创建其子类(GregorianCalendar)的对象
//方式二:使用静态方法Calendar.getInstance()方法
Calendar calendar = Calendar.getInstance();
// System.out.println(calendar.getClass());//class java.util.GregorianCalendar
// 2. 常用方法:
// 1. get()
int days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
// 2. set()
calendar.set(Calendar.DAY_OF_MONTH, 25);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
// 3. add()
calendar.add(Calendar.DAY_OF_MONTH, 4);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
// 4. getTime():日历类-->Date
Date date = calendar.getTime();
System.out.println(date);
// 5. setTime():Date->日历类
Date date1 = new Date();
calendar.setTime(date1);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
}
}
注意:获取月份时,一月是0,二月是1,以此类推,12月是11
获取星期时,周日是1,周二是3,周六是7
JDK8中新日期时间API
LocalDate 日期 LocalTime 时间 LocalDateTime
- 相对于LocalDate和LocalTime,LocalDateTime使用频率要高.
- 类似于Calendar日历类
- 常用方法
- now():获取当前的日期,时间,日期+时间
- of():设置指定的年月日,时分秒,没有偏移量.
- getXxx():获取相关的属性
- withXxx(): 设置相关的属性
- plusxxx(): 加
- minusXxx(): 减
package DateTimeTest;
import org.junit.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class JDK8DateTimeTest {
@Test
public void test1() {
//now():获取当前的日期,时间,日期+时间
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
// System.out.println(localDate);
// System.out.println(localTime);
// System.out.println(localDateTime);
//of():设置指定的年月日,时分秒,没有偏移量.
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 12, 31, 23, 55, 30);
// System.out.println(localDateTime1);
System.out.println(localDateTime.getDayOfMonth());
System.out.println(localDateTime.getDayOfWeek());
System.out.println(localDateTime.getMonth());
System.out.println(localDateTime.getMonthValue());
System.out.println(localDateTime.getMinute());
LocalDate localDate1 = localDate.withDayOfMonth(23);
System.out.println(localDate1);
System.out.println(localDate);
LocalDateTime localDateTime2 = localDateTime.withHour(12);
System.out.println(localDateTime2);
System.out.println(localDateTime);
LocalDateTime localDateTime3 = localDateTime.plusMonths(3);
System.out.println(localDateTime3);
System.out.println(localDateTime);
LocalDateTime localDateTime4 = localDateTime.minusDays(1);
System.out.println(localDateTime4);
}
}
Instant类
- 类似于java.util.Date类
- 常用方法:
- now(): 获取本初子午线对应的标准时间
- atOffset(ZoneOffset offset):添加时间偏移量
- toEpochMilli():获取自1970年1月1日0时分秒(UTC)开始的毫秒数—>类似Date类的getTime()
- ofEpochMilli():通过给定的毫秒数,获取Instant实例–>类似Date(long millis)
package Instant;
import org.junit.Test;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class InstantTest {
@Test
public void test1() {
//now(): 获取本初子午线对应的标准时间
Instant instant = Instant.now();
System.out.println(instant); //少8小时
//atOffset(ZoneOffset offset):添加时间偏移量
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);
//获取自1970年1月1日0时分秒(UTC)开始的毫秒数--->类似Date类的getTime()
long l = instant.toEpochMilli();
System.out.println(l);
//ofEpochMilli():通过给定的毫秒数,获取Instant实例-->类似Date(long millis)
Instant instant1 = Instant.ofEpochMilli(45466563463L);
System.out.println(instant1);
}
}
java.time.format.DateTimeFormatter类
- 格式化,或解析日期或时间,类似于SimpleDateFormat
https://www.bilibili.com/video/BV1Kb411W75N?p=487&spm_id_from=pageDriver
Java比较器
说明
- Java中的对象,正常情况下,只能进行比较: == 或 != ,不能使用 > 或 < 的.但是在开发场景中,我们需要对多个对象进行排序,就需要比较对象的大小.
- 如何实现? 使用两个接口中的任何一个:Comparable 或 Comparator
Comparable接口的使用
- 方式一: 自然排序
- 像String,包装类等实现了Comparable接口,重写了compareTo()方法,给出了比较两个对象大小的方式.
- 像String,包装类重写compareTo()方法以后,进行了从小到大的排列.
- 重写compareTo()的规则:
如果当前对象this大于形参对象obj,则返回正整数.
如果当前对象this小于形参对象obj,则返回负整数.
如果当前对象this等于形参对象obj,则返回零. - 对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法.
在compareTo(obj)方法中指明如何排序.
package Java比较器.compare;
import org.junit.Test;
import java.util.Arrays;
class Goods implements Comparable {
private String name;
private double price;
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", 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;
}
public Goods(String name, double price) {
this.name = name;
this.price = price;
}
public Goods() {
}
//指明比较大小的方式:按照价格从低到高排序,再按照产品名称从低到高排序
@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("传入的数据类型不一致");
}
}
public class CompareTest {
@Test
public void test() {
Goods[] arr = new Goods[4];
arr[0] = new Goods("lenove", 234);
arr[1] = new Goods("lianxiang", 462);
arr[2] = new Goods("xiaomi", 394);
arr[3] = new Goods("huawei", 294);
Arrays.sort(arr);//
System.out.println(Arrays.toString(arr));
}
}
java.util.Comparator接口的使用
- 方式二: 定制排序
- 背景:↓
- 使用场景:当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用Comparator的对象来排序
- 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
如果方法返回正整数,则表示o1大于o2
如果返回0,表示相等.
返回负整数,表示o1小于o2
package Java比较器.compare;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
public class CompareTest1 {
@Test
public void test() {
String[] arr = new String[]{"BB", "ii", "ww", "oo", "kk"};
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 test1() {
Goods[] arr = new Goods[4];
arr[0] = new Goods("lenove", 234);
arr[1] = new Goods("lianxiang", 462);
arr[2] = new Goods("xiaomi", 394);
arr[3] = new Goods("huawei", 294);
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接口属于临时性的比较.
System类
Math类
BigInteger与BigDecimal类
- BigInteger整形
- BigDecimal浮点型