Java 怎样通过使用自定义比较器来修复java.lang.ClassCastException问题
TreeSet是Java Collection Framework的一个泛型类,实现了SortedSet接口。它以树结构存储集合的元素。此外,所有元素都以排序方式存储,并且如果我们尝试添加自定义类对象,则它们必须是可相互比较的,否则将会遇到java.lang.ClassCastException异常。在这里,自定义类对象指的是通过构造函数创建的用户定义对象。修复此ClassCastException的一种方法是使用自定义比较器。让我们详细讨论一下。
TreeSet的一般语法如下:
语法
TreeSet<TypeOfSet> nameOfSet = new TreeSet<>();
使用比较器解决TreeSet中的java.lang.ClassCastException问题
在本节中,我们将解释如何使用自定义比较器来解决TreeSet中的ClassCastException问题。让我们从比较器开始讨论。
比较器
如其名,比较器用于比较某些内容。在Java中,Comparator是一个接口,用于对自定义对象进行排序。我们可以在其内置的名为’ compare() ‘的方法中编写我们自己的逻辑来排序指定的对象。该方法接受两个对象作为参数,然后返回一个整数值。通过这个整数值,Comparator决定哪个对象更大。
语法
class nameOfComparator implements Comparator< TypeOfComparator >() {
compare( type object1, type object2 ) {
// logic for comparison
}
}
在这里, class 是创建一个类的关键字, implements 是启用接口提供的特性的关键字。
示例1
在下面的示例中,我们将尝试向TreeSet中添加自定义类的对象,而不使用比较器来展示Java编译器会抛出java.lang.ClassCastException异常。
import java.util.*;
public class ShopBag {
String item;
int price;
ShopBag(String item, int price) { // constructor
// this keyword shows these variables belong to constructor
this.item = item;
this.price = price;
}
public static void main(String[] args) {
// Declaring collection TreeSet
TreeSet<ShopBag> trSet = new TreeSet<ShopBag>();
// Adding object to the collection
trSet.add(new ShopBag("Rice", 59));
trSet.add(new ShopBag("Milk", 60));
// to print the objects
for (ShopBag print : trSet) {
System.out.println("Item: " + print.item + ", " + "Price: " + print.price);
}
}
}
输出
Exception in thread "main" java.lang.ClassCastException: class ShopBag cannot be cast to class java.lang.Comparable (ShopBag is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
at java.base/java.util.TreeMap.compare(TreeMap.java:1569)
at java.base/java.util.TreeMap.addEntryToEmptyMap(TreeMap.java:776)
at java.base/java.util.TreeMap.put(TreeMap.java:785)
at java.base/java.util.TreeMap.put(TreeMap.java:534)
at java.base/java.util.TreeSet.add(TreeSet.java:255)
at ShopBag.main(ShopBag.java:14)
示例2
以下示例说明了在修复ClassCastException时使用Comparator的用法。
步骤
- 首先,导入 ‘java.util’ 包,以便我们可以使用TreeSet。
-
创建一个名为 ‘ShopBag’ 的类。在其中,声明两个变量,并定义一个该类的构造函数,该构造函数具有两个参数 ‘item’ 和 ‘price’,类型分别为字符串和整数。
-
然后,定义另一个名为 ‘Comp’ 的类,该类实现了Comparator接口。在其中,使用 ‘compare()’ 方法按升序对TreeSet进行排序。
-
在 ‘main()’ 方法内,通过传递 ‘Comp’ 类的实例创建一个TreeSet集合,以便它可以被排序。
-
最后,使用 ‘add()’ 方法将一些元素存储到TreeSet集合中,然后使用for-each循环打印集合的元素。
import java.util.*;
class ShopBag {
String item;
int price;
ShopBag(String item, int price) { // constructor
// this keyword shows these variables belong to constructor
this.item = item;
this.price = price;
}
}
// use of comparator interface
class Comp implements Comparator<ShopBag> {
// logic to sort
public int compare(ShopBag i, ShopBag j) {
if(i.price > j.price) {
return 1;
} else {
return -1;
}
}
}
public class Example2 {
public static void main(String[] args) {
// Declaring collection TreeSet
TreeSet<ShopBag> trSet = new TreeSet<ShopBag>(new Comp());
// Adding object to the collection
trSet.add(new ShopBag("Rice", 59));
trSet.add(new ShopBag("Milk", 60));
trSet.add(new ShopBag("Bread", 45));
trSet.add(new ShopBag("Peanut", 230));
trSet.add(new ShopBag("Butter", 55));
System.out.println("Objects of the collection: ");
// to print the objects
for (ShopBag print : trSet) {
System.out.println("Item: " + print.item + ", " + "Price: " + print.price);
}
}
}
输出
Objects of the collection:
Item: Bread, Price: 45
Item: Butter, Price: 55
Item: Rice, Price: 59
Item: Milk, Price: 60
Item: Peanut, Price: 230
结论
我们从定义TreeSet并介绍TreeSet的ClassCastException开始了本文。在接下来的部分,我们介绍了Comparator接口,该接口在解决ClassCastException时非常有帮助。然后,我们讨论了两个示例程序,展示了ClassCastException的具体情况以及如何解决这个异常。