いくつかのプログラミング言語には、有限集合の数学的概念の実装であると想定される Set コレクションがあります。
ただし、これは必ずしも正しいとは限りません。たとえば、C#
およびJava
では、 の両方の実装で、任意のコレクションをそれ自体のメンバーとしてHashSet<T>
追加できます。HashSet<T>
数学的集合の現代的な定義では、これは許可されていません。
バックグラウンド:
単純集合論によると、集合の定義は次のとおりです。
セットは、個別のオブジェクトのコレクションです。
ただし、この定義は、ラッセルのパラドックスや他のパラドックスにつながることで知られています。便宜上、ラッセルのパラドックスは次のとおりです。
R を、それ自体のメンバーではないすべてのセットのセットとします。R がそれ自体のメンバーでない場合、その定義はそれ自体を含む必要があることを示し、R がそれ自体を含む場合、それ自体のメンバーではないすべてのセットのセットとしての独自の定義と矛盾します。
したがって、現代の集合論 ( ZFCを参照) によると、集合の定義は次のとおりです。
セットは個別のオブジェクトのコレクションであり、そのいずれもセット自体ではありません。
具体的には、これは規則性の公理の結果です。
それで何?これにはどのような意味がありますか?この質問が StackOverflow にあるのはなぜですか?
ラッセルのパラドックスの意味の 1 つは、すべてのコレクションがセットであるとは限らないということです。さらに、これは数学者がセットの定義を通常の英語の定義として落としたポイントでした。したがって、プログラミング言語の設計全般に関して言えば、この質問には大きな重みがあると思います。
質問:
では、何らかの形でこれらの原則を設計そのものに使用しているプログラミング言語が、言語ライブラリの 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の 2 番目のポイントに関しては、計算効率の名目で実行できるということでした。
C# で 2 つのテスト コレクションを作成しました。それらの 1 つの Add メソッドを除いて、それらは同一でした - 次のチェックを追加しました:コレクションに追加される項目はif (this != obj)
どこですか。obj
100,000 のランダムな整数を追加する場所で、両方を別々にクロックしました。
チェックあり: ~ 28 ミリ秒
チェックなし: ~ 21 ミリ秒
これはかなり大きなパフォーマンスの向上です。