Scala中的平等关系

oxb*_*kes 8 scala equality equals scala-2.8 scala-collections

我只是偶然发现了Tony Morris 关于Java博客文章之一以及该语言的一个基本问题:为集合定义一个定制的平等关系.这是我认为是一个大问题,并想知道是否有一些scala解决方案.

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

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

val as = CleverSet[Trade](IdEquality)
val bs = CleverSet[Trade](EconomicsEquality)
Run Code Online (Sandbox Code Playgroud)

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

trait EqualityRelation[T] {
  def equal(t1: T, t2: T) : Boolean
  def hash(t: T) : Int
}
Run Code Online (Sandbox Code Playgroud)

所以问题是:

  • 有没有提供这种能力的图书馆?
  • 有没有办法在Scala中做到这一点?

似乎带有隐含,添加到现有的scala Set类型将是一件非常容易的事情.

Tho*_*ung 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);
Run Code Online (Sandbox Code Playgroud)

输出:

ignoreCase -> [A]
withCase -> [A, a]
Run Code Online (Sandbox Code Playgroud)

这样做的缺点是Comparator的实现功能比需要的更强大,并且您只能使用支持Comparators的集合.正如oxbow_lakes所指出的,Comparator实现打破了Set契约(因为!a.equals(b)它可能就是这样new Set(); set.add(a) == true && set.add(b) == false).

Scala通过A => Ordered [A]的视图转换支持此功能.

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