在几种编程语言中,存在集合集合,它们应该是有限集合的数学概念的实现。
但是,这不一定是正确的,例如在C#
和中Java
,这两种实现都HashSet<T>
允许您将任何HashSet<T>
集合添加为其自身的成员。根据数学集合的现代定义,这是不允许的。
背景:
根据朴素集合论,集合的定义是:
集合是不同对象的集合。
然而,这个定义导致了著名的罗素悖论以及其他悖论。为方便起见,罗素悖论是:
令 R 是所有不属于它们自己的集合的集合。如果 R 不是它自己的成员,那么它的定义表明它必须包含它自己,如果它包含它自己,那么它与它自己的定义相矛盾,它是所有不属于它自己的集合的集合。
所以根据现代集合论(参见:ZFC),集合的定义是:
集合是不同对象的集合,其中没有一个是集合本身。
具体来说,这是规律性公理的结果。
那么那又怎样?这意味着什么?为什么这个问题出现在 StackOverflow 上?
罗素悖论的含义之一是并非所有集合都是集合。此外,这也是数学家放弃将集合定义为通常的英语定义的地方。所以我相信这个问题在一般的编程语言设计方面有很大的分量。
问题):
那么,为什么以某种形式在他们的设计中使用这些原则的编程语言在他们的语言库中实现 Set 时会忽略它呢?
其次,这在数学概念的其他实现中是否常见?
也许我有点挑剔,但如果这些是集合的真正实现,那么为什么会忽略定义的一部分呢?
更新
添加示例行为的 C# 和 Java 代码片段:
Java 片段:
Set<Object> hashSet = new HashSet<Object>();
hashSet.add(1);
hashSet.add("Tiger");
hashSet.add(hashSet);
hashSet.add('f');
Object[] array = hashSet.toArray();
HashSet<Object> hash = (HashSet<Object>)array[3];
System.out.println("HashSet in HashSet:");
for (Object obj : hash)
System.out.println(obj);
System.out.println("\nPrinciple HashSet:");
for (Object obj : hashSet)
System.out.println(obj);
打印出来:
HashSet in HashSet:
f
1
Tiger
[f, 1, Tiger, (this Collection)]
Principle HashSet:
f
1
Tiger
[f, 1, Tiger, (this Collection)]
C# 代码段:
HashSet<object> hashSet = new HashSet<object>();
hashSet.Add(1);
hashSet.Add("Tiger");
hashSet.Add(hashSet);
hashSet.Add('f');
object[] array = hashSet.ToArray();
var hash = (HashSet<object>)array[2];
Console.WriteLine("HashSet in HashSet:");
foreach (object obj in hash)
Console.WriteLine(obj);
Console.WriteLine("\nPrinciple HashSet:");
foreach (object obj in hashSet)
Console.WriteLine(obj);
打印出来:
HashSet in HashSet:
1
Tiger
System.Collections.Generic.HashSet`1[System.Object]
f
Principle HashSet:
1
Tiger
System.Collections.Generic.HashSet`1[System.Object]
f
更新 2
关于Martijn Courteaux的第二点,它可以以计算效率的名义完成:
我在 C# 中制作了两个测试集合。它们是相同的,除了其中一个的 Add 方法 - 我添加了以下检查:添加到集合中的项目在if (this != obj)
哪里。obj
我分别给他们两个计时,他们要添加 100,000 个随机整数:
带检查: ~ 28 毫秒
无检查: ~ 21 毫秒
这是一个相当显着的性能飞跃。