我想在Java中使用一组对,但是当我调用contains()
来查看它是否已经包含一个特定的对时,我总是得到一个ClassCastException
。有没有办法避免这种行为?
它实例化如下:
private static final Set<Pair<String, String>> BLACKLIST = new TreeSet<>();
BLACKLIST.add(new Pair<String, String>("anytext", "anytext"));
这里调用contains()会导致以下ClassCastException:
if (!blacklist.contains(new Pair<String, String>(localizedFile.getName(), key)))
java.lang.ClassCastException: .common.util.Pair cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1294)
at java.util.TreeMap.put(TreeMap.java:538)
at java.util.TreeSet.add(TreeSet.java:255)
我使用java.util类而不是我自己的类。是否有一种优雅的方法可以避免实现一个重载common.util.Pair的新类对?
除非在创建Set时将任何显式比较器传递给构造函数,否则TreeSet将使用其元素的自然顺序。
合同说插入到集合中的所有元素都必须实现Comparable接口。此外,所有这些元素必须是可相互比较的.e1.compareTo(e2)
不能为集合中的任何元素e1和e2抛出ClassCastException。
你的代码是
private static final Set<Pair<String, String>> BLACKLIST = new TreeSet<>();
BLACKLIST.add(new Pair<String, String>("anytext", "anytext"));
由于你没有将一个显式的Comparator传递给构造函数,并且你的元素(Pair)都没有实现一个好的Comparable,你在向集合中添加一个元素时会得到一个类转换异常。
我的建议是(i)通过一个明确的比较器
或(ii)使Pair实现可比较如下
public class Pair<T1 extends Comparable<T1>, T2 extends Comparable<T2>> implements Comparable<Pair<T1, T2>> {
T1 firstName;
T2 secondName;
public Pair(T1 firstName, T2 secondName) {
this.firstName = firstName;
this.secondName = secondName;
}
public T1 getFirstName() {
return firstName;
}
public T2 getSecondName() {
return secondName;
}
// elements ordered with first parameter .you can make a better
// comparable as well
@Override
public int compareTo(Pair<T1, T2> o) {
// TODO Auto-generated method stub
return this.firstName.compareTo(o.firstName);
}
}
TreeSet
使用其元素的自然顺序,似乎投向Comparable
来做到这一点。
你可以做些什么来使这个代码工作是给TreeSet
你自己的Comparator
所以它可以使用它而不是自然顺序。
Set<Pair<String, String>> blacklist = new TreeSet<>(
Comparator.comparing(Pair::getFirst)
.thenComparing(Pair::getSecond));
这将是第一个,然后Pair
的第二项。