【问题标题】:Compare different object types with comparator使用比较器比较不同的对象类型
【发布时间】:2015-02-16 10:04:49
【问题描述】:

我需要编写一个比较器,它接受一个类型为 A 的对象 A 和一个类型为 B 的对象 B。这两个对象不是公共对象的扩展。它们确实不同,但我需要通过其中的公共字段来比较这两个对象。我必须使用比较器接口,因为对象存储在 Set 中,并且在我必须使用 CollectionUtils 进行操作之后。我用谷歌搜索了一下,我找到了 Comparator 的解决方案,但只有相同的类型。

我试图在这个方向上实施一个想法,但我不知道我是否走在正确的道路上。

public class MyComparator implements Comparator<A>, Serializable {

  private B b;

  public MyComparator(B b){
       this.b = b;
  }

  @Override
  public int compare(A old, A otherOne) {
    int value = 0;
    if (!old.getField().equals(b.getField())) {
        value = 1;
    }
    return value;
  }
}

有可能总是给出答案,但我没有找到合适的词在 Google 中搜索。有人建议吗?

发送

P.S:我将两个对象添加到不同的集合中:

TreeSet<A> setA = new TreeSet<A>(myComparator);
TreeSet<B> setB = new TreeSet<B>(myComparator);

之后我会这样想:

TreeSet<??????> retain = CollectionUtils.retainAll(setA, setB);
TreeSet<??????> remove = CollectionUtils.removeAll(setA, setB);

【问题讨论】:

  • 这里问了一个类似的问题。 stackoverflow.com/questions/12414288/…
  • 您希望如何使用这个比较器?我能想到的所有具有比较器参数的东西都在处理单一类型......

标签: java collections compare


【解决方案1】:

有一种非常老套的方法可以让你使用Objectinstanceof,但是如果你可以实现一个暴露特定接口的代理类,你最好这样做。

class A {

    public String getSomething() {
        return "A";
    }
}

class B {

    public String getSomethingElse() {
        return "B";
    }
}

class C implements Comparator<Object> {

    @Override
    public int compare(Object o1, Object o2) {
        // Which is of what type?
        A a1 = o1 instanceof A ? (A) o1: null;
        A a2 = o2 instanceof A ? (A) o2: null;
        B b1 = o1 instanceof B ? (B) o1: null;
        B b2 = o2 instanceof B ? (B) o2: null;
        // Pull out their values.
        String s1 = a1 != null ? a1.getSomething(): b1 != null ? b1.getSomethingElse(): null;
        String s2 = a2 != null ? a2.getSomething(): b2 != null ? b2.getSomethingElse(): null;
        // Compare them.
        return s1 != null ? s1.compareTo(s2): 0;
    }

}

更可接受的机制是为每个实现公共接口的代理类实现一个代理类,然后可以使用适当的类型安全比较器进行比较。

interface P {

    public String getValue();
}

class PA implements P {

    private final A a;

    PA(A a) {
        this.a = a;
    }

    @Override
    public String getValue() {
        return a.getSomething();
    }
}

class PB implements P {

    private final B b;

    PB(B b) {
        this.b = b;
    }

    @Override
    public String getValue() {
        return b.getSomethingElse();
    }
}

class PC implements Comparator<P> {

    @Override
    public int compare(P o1, P o2) {
        return o1.getValue().compareTo(o2.getValue());
    }

}

【讨论】:

  • Txs。最后我决定采用接口方式。我没有尝试 hack,但 txs 用于提案。
  • 如何调用PA和PB对象的比较方法?
【解决方案2】:

如果您将两种不相关类型的对象存储在Set 中(这让我感到奇怪,因为Sets 通常是无序的),这意味着您使用的是原始Set,这不是非常安全的类型.

您可以定义一个接口CommonAB,其中包含AB 的所有公共属性的getter 方法。 AB 都将实现该接口。您可以将AB 的实例放入Set&lt;CommonAB&gt;

最后,Comparator&lt;CommonAB&gt; 将能够比较两种类型的对象。 Comparator 将仅访问接口的方法。它不会关心它是在比较两个 As、两个 B 还是一个 A 和一个 B。

【讨论】:

  • 我看到了这种方式,但这是唯一的方式吗?因为我不会再添加一个我必须及时维护的对象......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 2022-10-19
  • 2021-04-20
  • 2011-05-04
相关资源
最近更新 更多