问题描述
我偶然发现了Tony Morris的和该语言的一个基本问题:为集合定义定制的平等关系。我认为这是一件大事,想知道是否存在一些scala解决方案。
I just stumbled on one of Tony Morris' blog-posts about Java and a fundamental problem with the language: that of defining a bespoke equality-relation for a collection. This is something that I think is a big deal and wondered whether there was some scala solution.
经典问题体现在考虑交易等方面。假设我以150p的价格交易了两笔100股沃达丰股票。这两个行业是平等的,是吗?除非它们不是同一行业。对于具有持久性或序列化功能的常规真实系统,我不能依靠 identity 来告诉我两个引用是否指向同一交易!
The classic issue manifests itself in thinking about, say, a trade. Let's say I make two trades of +100 vodafone shares @150p. The two trades are equal, yes? Except they are not the same trade. In the case of a normal real-world system, with persistence or serialization, I cannot rely on identity to tell me whether two references are to the same trade!
所以我想要的是能够创建一个集合,我可以将一个平等关系传递给:
So what I want is to be able to create a collection which I can pass an Equality-relation to:
val as = CleverSet[Trade](IdEquality)
val bs = CleverSet[Trade](EconomicsEquality)
如何我是否可以高效地实现我的集合(除非 EqualityRelation
也定义了 hash
机制)?
How would I implement my set in an efficient manner (unless the EqualityRelation
also defines a hash
mechanism)?
trait EqualityRelation[T] {
def equal(t1: T, t2: T) : Boolean
def hash(t: T) : Int
}
所以问题是:
- 是否有一个提供此功能的库?
- 在Scala中有某种方法可以很好地做到这一点吗?
使用隐式函数,将它添加到现有的scala Set
It seems that with implicits, it would be quite an easy thing to add to the existing scala Set
type.
推荐答案
这可以通过Java的TreeSet和Comparator实现来实现:
This can already be achieved with Java's TreeSet and a Comparator implementation:
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
)。
This has the drawbacks that the Comparator to implement is more powerful than needed and that you're restricted to collections that support Comparators. As pointed out by oxbow_lakes the Comparator implementation breaks the Set contract (for !a.equals(b)
it could be that new Set(); set.add(a) == true && set.add(b) == false
).
Scala支持使用
scala> new scala.collection.immutable.TreeSet[String]()(x=> x.toLowerCase) + "a"
+ "A"
res0: scala.collection.immutable.TreeSet[String] = Set(A)
这篇关于斯卡拉的平等关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!