how to force HashSet to rehash members?

what is a hash set
hashtable
hashset contains duplicate elements
hashset vs hashmap
hashset example
set and hashset
hashset duplicates
hashing

In this situation where one member is edited to become equal to another, what is the proper way to force the HashSet to recalculate hashes and thereby purge itself of duplicates?

I knew better than to expect this to happen automatically, so I tried such things as intersecting the HashSet with itself, then reassigning it to a constructor call which refers to itself and the same EqualityComparer. I thought for sure the latter would work, but no.

One thing which does succeed is reconstructing the HashSet from its conversion to some other container type such as List, rather than directly from itself.

Class defs:

public class Test {
    public int N;
    public override string ToString() { return this.N.ToString(); }
    }
public class TestClassEquality: IEqualityComparer<Test> {
    public bool Equals(Test x, Test y) { return x.N == y.N; }
    public int GetHashCode(Test obj) { return obj.N.GetHashCode(); }
    }

Test code:

    TestClassEquality eq = new TestClassEquality();
    HashSet<Test> hs = new HashSet<Test>(eq);
    Test a = new Test { N = 1 }, b = new Test { N = 2 };
    hs.Add(a);
    hs.Add(b);
    b.N = 1;
    string fmt = "Count = {0}; Values = {1}";
    Console.WriteLine(fmt, hs.Count, string.Join(",", hs));
    hs.IntersectWith(hs);
    Console.WriteLine(fmt, hs.Count, string.Join(",", hs));
    hs = new HashSet<Test>(hs, eq);
    Console.WriteLine(fmt, hs.Count, string.Join(",", hs));
    hs = new HashSet<Test>(new List<Test>(hs), eq);
    Console.WriteLine(fmt, hs.Count, string.Join(",", hs));

Output:

"Count: 2; Values: 1,1"
"Count: 2; Values: 1,1"
"Count: 2; Values: 1,1"
"Count: 1; Values: 1"

Based on the final approach succeeding, I could probably create an extension method in which the HashSet dumps itself into a local List, clears itself, and then repopulates from said list.

Is that really necessary or is there some simpler way to do this?

c#: how to force HashSet to rehash members?, In this situation where one member is edited to become equal to another, what is the proper way to force the HashSet to recalculate hashes and  In this situation where one member is edited to become equal to another, what is the proper way to force the HashSet to recalculate hashes and thereby purge itself of duplicates? I knew better than to expect this to happen automatically, so I tried such things as intersecting the HashSet with itself, then reassigning it to a constructor call

There is no other way than recreating the HashSet<>. Sadly the HashSet<> constructor has an optimization so that if it is create from another HashSet<> it copies the hash codes... So we can cheat:

hs = new HashSet<Test>(hs.Skip(0), eq);

The hs.Skip(0) is a IEnumerable<>, not an HashSet<>. This defeats the HashSet<> check.

Note that there is no guarantee that in the future the Skip() won't implement a shortcircuit in case of 0, something like:

if (count == 0)
{
    return enu;
}
else
{
    return count elements;
}

(see Lippert's comment, false problem)

The "manual" method to do it is:

var hs2 = new HashSet<Test>(eq);
foreach (var value in hs)
{
    hs2.Add(value);
}
hs = hs2;

So enumerate "manually" and readd.

9. Hash Sets, adapter/ SetAdapter util/ OpenHashSet demo/ ShowHashCodes ShowSets A hash function which produces no collisions for a set of elements is referred to as perfect hash codes, thus forcing an Ω(log(N)) lower bound to compute the hash code. When the load becomes greater than the allowable load factor, a rehash​  In the code, given above, we are creating a simple HashSet of the string type and adding the strings to it. We can also add the string, using the Add method. We will see how we can use the Add method in the snippet, given below. We will now try to add the duplicate string and see what happens.

As you saw, HashSets don't deal with mutable objects when modifying the object affects its hash code or equality to other objects. Just remove it and re-add it:

hs.Remove(b);
b.N = 1;
hs.Add(b);

Modern Java Recipes: Simple Solutions to Difficult Problems in , Sets and Encounter Order HashSet instances have no defined encounter order, but if you Now add and remove enough elements to force a rehash IntStream. Load Factor: The load factor is a measure of how full the HashSet is allowed to get before its capacity is automatically increased. When the number of entries in the hash table exceeds the product of the load factor and the current capacity, the hash table is rehashed (that is, internal data structures are rebuilt)

HashSet.java, Arrays; public class HashSet<E> implements Set<E> { private static final double MAX_LOAD = 0.75; // load factor on which to rehash private Node[] elements;  rehash(int newCapacity) Rehashes the set. boolean: remove(int val) Removes entry from the set. boolean: removeAll(java.util.Collection<?> collection) Removes all of the elements in collection from the set. boolean: removeAll(int[] array) Removes all of the elements in array from the set. boolean

abseil-cpp/flat_hash_set.h at master · abseil/abseil-cpp · GitHub, Insert a new element into the flat hash set. // ducks.insert("donald");. //. // // Force a rehash of the flat hash set. // ducks.rehash(0);. //. // // See if "dewey" is present. The HashSet class also naturally inherits this method. Although you can use that method, the HashSet class provides its own custom method named SetEquals. Its syntax is: public bool SetEquals(IEnumerable<T> other); This method takes as argument another HashSet list and compares both sets. If the sets are the same, the method returns true.

Solved: Our Textbook Provided Class For Hashing HashSet.ja , Answer to Our textbook provided Class for hashing HashSet.java uses a of data, so adding a couple more elements will force it to re-hash and create a very​  how to force HashSet to rehash members? Pointer arithmetics with two different buffers; Automatically delete files created by a library when it is killed; Android – How to unhide soft buttons after programatically hiding them? How to merge multiple rows into single in Oracle; Can I extend variant in C++?

Comments
  • The problem here is that you're doing something that is explicitly not supposed to happen, keys used for hashing and dictionaries are required to not change. Therefore nobody has made it easy to handle this situation.
  • Thanks. The TLDR non-MVCE version is that I originally had a Dictionary<string,Foo> where the key string was also the "Name" property of Foo -- but then realized that was redundant and complicated the unforeseen need to rename said Foo from the calling environment. So I switched to a HashSet with equality based on said Name and had the above problems. Current version uses a wrapper class with a private List<Foo> and accessor functions for the desired by-name lookup, renaming, and avoidance of duplicates. Count is expected to remain too low for linear lookup efficiency to be a concern.
  • The other thing I just discovered is that using a different instance of the same EqualityComparer class will also avoid this optimization. hs = new HashSet<Test>(hs, eq2);
  • @CusterBarnes Yes. See this line of the source of HashSet<>
  • I like that you're thinking carefully about this, but you don't actually have to worry about it. The standard implementation of Skip(0), Select(x=>x) and so on are required to not be reference-equals to the underlying collection, so you don't have to worry that they will change. LINQ was designed so that you cannot "cast away" a query to get back to the original object; the developer may be attempting to conceal an underlying mutable object from its consumer, that needs an immutable view on the collection.
  • Note that you have to do the removal before the mutation, as you've done here. If the object is mutated such that the hash is different then you can't remove it. That's the whole reason why this is illegal in the first place!