Scala中的平等关系

时间:2010-02-26 12:55:37

标签: scala scala-2.8 equals equality scala-collections

我偶然发现了Tony Morris的一个blog-posts about Java以及该语言的一个基本问题:为一个集合定义一个定制的平等关系。这是我认为是大不了的事情,并且想知道是否有一些scala解决方案。

经典问题表现在思考交易。假设我在@ 150p进行了两笔+100沃达丰股票交易。这两笔交易是平等的,是吗?除非他们不是相同的交易。对于普通的真实世界系统,使用持久性或序列化,我不能依赖身份来告诉我两个引用是否属于同一行业

所以我想要的是能够创建一个我可以传递Equality-relation的集合:

val as = CleverSet[Trade](IdEquality)
val bs = CleverSet[Trade](EconomicsEquality)

我如何以有效的方式实现我的集合(除非EqualityRelation还定义了hash机制)?

trait EqualityRelation[T] {
  def equal(t1: T, t2: T) : Boolean
  def hash(t: T) : Int
}

所以问题是:

  • 是否有提供此功能的图书馆?
  • 在Scala中有什么方法可以做到这一点吗?

似乎有了暗示,添加到现有的scala Set类型会非常简单。

3 个答案:

答案 0 :(得分:6)

这已经可以通过Java的TreeSet和Comparator实现来实现:

TreeSet<String> ignoreCase = new TreeSet<String>(new Comparator<String>(){
    @Override
    public int compare(String o1, String o2) {
        return o1.compareToIgnoreCase(o2);
    }});

TreeSet<String> withCase = new TreeSet<String>();

List<String> values = asList("A", "a");
ignoreCase.addAll(values);
withCase.addAll(values);

输出:

ignoreCase -> [A]
withCase -> [A, a]

这样做的缺点是比较器要实现的功能比需要的功能更强大,并且限制为支持比较器的集合。正如oxbow_lakes所指出的,Comparator实现违反了Set契约(!a.equals(b)可能是new Set(); set.add(a) == true && set.add(b) == false)。

Scala通过A =&gt;的视图转换支持此功能。有序[A]。

scala> new scala.collection.immutable.TreeSet[String]()(x=> x.toLowerCase) + "a"
 + "A"
res0: scala.collection.immutable.TreeSet[String] = Set(A)

答案 1 :(得分:2)

您正在描述哈希策略的概念。 Trove library包括可以使用散列策略构建的集合和映射。

答案 2 :(得分:2)

我知道你在询问Scala,但是值得与.Net系列提供的内容进行比较。特别是,所有基于哈希的集合(例如Dictionary<TKey, TValue>HashSet<T>)都可以采用IEqualityComparer<T>的实例。这与Scala的Equiv[T]类似,但也提供自定义哈希码。您可以通过继承Equiv

来创建类似的特征
trait HashEquiv[T] extends Equiv[T] {
  def hashOf(t: T) : Int
}

要完全支持,基于散列的集合需要在其构造中添加HashEquiv隐式参数,并使用隐式导入的equivhashOf方法而不是Object实例方法(如TreeSet等)使用Ordered特征,但反过来)。还需要使用内部AnyHashEquiv实现从equalshashCode的隐式转换。