首页 > 解决方案 > 使用一组对时发生 ClassCastException

问题描述

我想在 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 的新类对?

标签: javasettreeset

解决方案


TreeSet 使用其元素的自然排序,除非您在创建 Set 时将任何显式比较器传递给构造函数。

合同规定,插入集合中的所有元素都必须实现 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 实现 Comparable 如下

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);
    }

}

推荐阅读