JAVA比较器
在Java中经常会涉及到对象数组的排序问题,
那么就涉及到对象之间的比较问题
java实现对象排序的方式有两种:
自然排序: java.lang.Comparable
定制排序: java.lang.Comparator
1.说明:
Java中的对象,正常情况下,只能进行比较==或!=。
不能使用 > 或 < 的。
但是在开发场景中,我们需要对多个对象进行排序,
言外之意,就需要比较对象的大小。
如何实现?
使用两个接口中的任何一个: Comparable 或Comparator
2.Comparable接口的使用举例:自然排序(默认考虑这个)
2.1 像String、包装类等实现了Comparable接口,
重写了compareTo(obj)方法,给出了比较两个对象大小的方式
2.2 像String、包装类重写compareTo()方法以后,进行了从小到大的排列
2.3 重写compareTo(obj)的规则:
如果当前对象this大于形参对象bj,则返回正整数,
如果当前对象this小于形参对象obj,则返回负整数,
如果当前对象this等于形参对象obj,则返回零。
2.4 对于自定义来说,如果需要排序,
我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。
在compareTo(obj)方法中指明如何排序
举例1:
@Test
public void test1(){
String[] arr = new String[]{"A","G","E","B","C","H"};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
结果: [A, B, C, E, G, H]
举例2:(自定义类)
public class Goods implements Comparable {
private String name;
private double price;
//省略无参构造,有参构造,getter和setter
@Override
public String toString() {
return "Goods{" +"name='" + name + '\'' +
", price=" + price + '}';
}
//指明商品比较大小的方式:希望价格从低到高排序,再按照产品名称从高到低排序
@Override
public int compareTo(Object o) {
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("传入的参数类型不一致");
// 运行时异常,可以考虑不去处理
}
}
CompareTest
@Test
public void test2(){
Goods[] arr = new Goods[5];
arr[0] = new Goods("MiTv",3500);
arr[1] = new Goods("SonyTv",6500);
arr[2] = new Goods("HuaWeiTv",5500);
arr[3] = new Goods("SanXing",5000);
arr[4] = new Goods("Tao",3500);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
结果:
[Goods{name=‘Tao’, price=3500.0},
Goods{name=‘MiTv’, price=3500.0},
Goods{name=‘SanXing’, price=5000.0},
Goods{name=‘HuaWeiTv’, price=5500.0},
Goods{name=‘SonyTv’, price=6500.0}]
3.Comparator接口的使用:定制排序
3.1 背景:
当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,
或者实现了java. lang. Comparable接口的排序规则不适合当前的操作,
那么可以考虑使用Comparator的对象来排序
3.2 重写compare(object o1, object o2)方法,比较o1 和o2的大小:
如果方法返回正整数,则表示01大于o2;
如果返回0,表示相等;
返回负整数,表示o1小于o2。
举例1:
@Test
public void test3(){
String[] arr = new String[]{"A","G","E","B","C","H"};
//下面是泛型去掉的操作
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));
}
结果: [H, G, E, C, B, A]
举例2:(自定义类)
引用上方类
@Test
public void test4(){
Goods[] arr = new Goods[6];
arr[0] = new Goods("MiTv",3500);
arr[1] = new Goods("SonyTv",6500);
arr[2] = new Goods("HuaWeiTv",5500);
arr[3] = new Goods("SanXing",5000);
arr[4] = new Goods("SanXing",7000);
arr[5] = new Goods("Tao",3500);
//指明商品比较大小的方式:希望产品名称从低到高排序,再按照价格从高到低排序
//下面是有泛型并用Lambda表达式的操作
Arrays.sort(arr, (o1, o2) -> {
if (o1.getName().equals(o2.getName())){
return -Double.compare(o1.getPrice(),o2.getPrice());
//默认是从低到高,加上负,就变成了从高到底
}else {
return o1.getName().compareTo(o2.getName());
}
});
System.out.println(Arrays.toString(arr));
}
结果:
[Goods{name=‘HuaWeiTv’, price=5500.0},
Goods{name=‘MiTv’, price=3500.0},
Goods{name=‘SanXing’, price=7000.0},
Goods{name=‘SanXing’, price=5000.0},
Goods{name=‘SonyTv’, price=6500.0},
Goods{name=‘Tao’, price=3500.0}]
Comparable接口与Comparator的使用的对比:
1.Comparable接口的方式一旦一定,
保证Comparable接口实现类的对象在任何位置都可以比较大小。
2.Comparator.接口属于临时性的比较。
常用类
Stream类
1.System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
2.由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,所以也可以很方便的进行调用。
3.成员变量
System类内部包含in、out和err三 个成员变量,
分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
4.成员方法
- native long currentTimeMillis():
该方法的作用是返回当前的计算机时间 - void exit(int status):
该方法的作用是退出程序。
其中status的值为0代表正常退出,非零代表异常退出。
使用该方法可以在图形界面编程中实现程序的退出功能等。 - void gc():
该方法的作用是请求系统进行垃圾回收。
至于系统是否立刻回收,
则取决于系统中垃圾回收算法的实现以及系统执行时的情况。 - String getProperty(String key):
该方法的作用是获得系统中属性名为key的属性对应的值。
系统中常见的属性名以及属性的作用如下所示:
java.version》Java运行时环境版本
java.home》Java安装目录
os.name》操作系统的名称
os.version》操作系统的版本
user.name》用户的账户名称
user.home》用户的主目录
user.dir》用户的当前工作目录
举例:
@Test
public void test1(){
String property = System.getProperty("java.version");
System.out.println(property);
String property1 = System.getProperty("java.home");
System.out.println(property1);
String property2 = System.getProperty("os.name");
System.out.println(property2);
String property3 = System.getProperty("os.version");
System.out.println(property3);
}
结果:
1.8.0_241
D:\A\java\jdk\jre
Windows 10
10.0
BigInteger类和BigDecimal类
BigInteger类
Integer类作为int的包装类,能存储的最大整型值为2的31次方整体-1,Long类 也是有限的,最大为2的63次方整体-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。
java.math包的BigInteger可以表示不可变的任意精度的整数。
常用方法
- BigInteger(String val):根据字符串构建BigInteger对象
- BigInteger divide(BigInteger val):返回其值为(this/val)的BigInteger。整数相除只保留整数部分。
BigDecimal类
一般的Float类和Double类可以用来做科学计算或工程计算,
但在商业计算中, 要求数字精度比较高,故用到java.math.BigDecimal类 。
BigDecimal类支持不可变的、任意精度的有符号十进制定点数。
构造器
- public BigDecimal(double val)
- public BigDecimal(String val)
常用方法
- public BigDecimal multiply(BigDecimal multiplicand)
- public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)