diff --git a/applications/test/HashSet/Test-hashSet.C b/applications/test/HashSet/Test-hashSet.C
index d4b4f0c4f8d7145b24c71e5acc86b309206f289f..4a54de9aed88c24d3ad7a8e21abf086d39bb510b 100644
--- a/applications/test/HashSet/Test-hashSet.C
+++ b/applications/test/HashSet/Test-hashSet.C
@@ -32,6 +32,7 @@ Description
 #include "HashOps.H"
 #include "HashSet.H"
 #include "Map.H"
+#include "MinMax.H"
 #include "labelPairHashes.H"
 #include "FlatOutput.H"
 
@@ -184,6 +185,9 @@ int main(int argc, char *argv[])
         1, 11, 42
     };
 
+    Info<<"Set with min/max:" << minMax(setB)
+        << " min:" << min(setB) << " max:" << max(setB) << nl;
+
     setB = FixedList<label, 4>({1, 2, 3, 4});
     setB = {1, 2, 4};
     setB = List<label>({1, 2, 4});
diff --git a/applications/test/HashTable2/Test-HashTable2.C b/applications/test/HashTable2/Test-HashTable2.C
index 87ed286a8beeeee07301efbe0c99da5ce859b4b5..5507168766fc96351d6ec479aecc6cd516f32f4d 100644
--- a/applications/test/HashTable2/Test-HashTable2.C
+++ b/applications/test/HashTable2/Test-HashTable2.C
@@ -261,14 +261,24 @@ int main(int argc, char *argv[])
 
         labelList list1(identity(4, -4));
 
-        Info<<"move insert " << list1 << nl;
+        Info<< "move insert " << list1 << nl;
 
         ltable1.insert("pqr", std::move(list1));
 
-        Info<<"after insert " << list1 << nl;
+        Info<< "after insert " << list1 << nl;
 
         Info<< nl << "HashTable<labelList>: "
             << ltable1 << nl;
+
+
+        // Use '->' dereferencing
+        const auto iter = ltable1.cfind("ghi");
+
+        if (iter)
+        {
+            Info<< "got with " << iter->size() << nl;
+        }
+
     }
 
     Info<< "\nEnd\n" << endl;
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index 13d86b664ba5f28003e1633ef2508e9ae2a2ddd4..92e60ba056263404263a94b4ca9feb3b2dd15569 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -171,6 +171,7 @@ containers/Bits/bitSet/bitSetIO.C
 containers/Bits/BitOps/BitOps.C
 containers/Bits/PackedList/PackedListCore.C
 containers/HashTables/HashOps/HashOps.C
+containers/HashTables/HashSet/hashSets.C
 containers/HashTables/HashTable/HashTableCore.C
 containers/Lists/SortableList/ParSortableListName.C
 containers/Lists/ListOps/ListOps.C
diff --git a/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H b/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H
index 4790fbcc9edfe63eb462a6026f059603a0f5256d..804ae898cbb102f1713db4c8ecdbe4fcbcad8543 100644
--- a/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H
+++ b/src/OpenFOAM/containers/HashTables/HashSet/HashSet.H
@@ -73,10 +73,7 @@ namespace Foam
 {
 
 // Forward declarations
-template<class Key, class Hash> class HashSet;
-
-template<class Key, class Hash>
-Ostream& operator<<(Ostream& os, const HashSet<Key, Hash>& tbl);
+template<class T> class MinMax;
 
 
 /*---------------------------------------------------------------------------*\
@@ -380,15 +377,6 @@ public:
         inline this_type& operator-=(const this_type& rhs);
 
 
-    // IOstream Operator
-
-        friend Ostream& operator<< <Key, Hash>
-        (
-            Ostream& os,
-            const HashSet<Key, Hash>& tbl
-        );
-
-
     // Housekeeping
 
         //- Not applicable for HashSet
@@ -418,8 +406,36 @@ public:
 };
 
 
+// Typedefs
+
+//- A HashSet with word keys.
+typedef HashSet<word> wordHashSet;
+
+//- A HashSet with label keys and label hasher.
+typedef HashSet<label, Hash<label>> labelHashSet;
+
+
+// Global Functions
+
+//- Find the min value in labelHashSet, optionally limited by second argument.
+//  For an empty set, returns the second argument (eg, labelMax).
+label min(const labelHashSet& set, label minValue = labelMax);
+
+//- Find the max value in labelHashSet, optionally limited by second argument.
+//  For an empty set, returns the second argument (eg, labelMin).
+label max(const labelHashSet& set, label maxValue = labelMin);
+
+//- Find the min/max values of labelHashSet
+MinMax<label> minMax(const labelHashSet& set);
+
+
 // Global Operators
 
+//- Write the list of HashSet keys
+template<class Key, class Hash>
+Ostream& operator<<(Ostream& os, const HashSet<Key, Hash>& tbl);
+
+
 //- Combine entries from HashSets
 template<class Key, class Hash>
 HashSet<Key, Hash> operator|
@@ -447,13 +463,6 @@ HashSet<Key, Hash> operator^
 );
 
 
-//- A HashSet with word keys.
-typedef HashSet<word> wordHashSet;
-
-//- A HashSet with label keys and label hasher.
-typedef HashSet<label, Hash<label>> labelHashSet;
-
-
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 } // End namespace Foam
diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H
index f973c85619328caf7f4120858378bc63ee934e40..f7eb66957c1cd79f3d934acf9343775dea32681e 100644
--- a/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H
+++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTable.H
@@ -104,12 +104,6 @@ template<class T> class UList;
 template<class T, unsigned N> class FixedList;
 template<class T, class Key, class Hash> class HashTable;
 
-template<class T, class Key, class Hash>
-Istream& operator>>(Istream& is, HashTable<T, Key, Hash>& tbl);
-
-template<class T, class Key, class Hash>
-Ostream& operator<<(Ostream& os, const HashTable<T, Key, Hash>& tbl);
-
 
 /*---------------------------------------------------------------------------*\
                           Class HashTable Declaration
@@ -149,10 +143,6 @@ class HashTable
         //  No checks for zero-sized tables.
         inline label hashKeyIndex(const Key& key) const;
 
-        //- Read entry (key, val) and assign
-        //  \return True if the new entry was set.
-        bool addEntry(Istream& is, const bool overwrite = false);
-
         //- Assign a new hash-entry to a possibly already existing key.
         //  \return True if the new entry was set.
         template<class... Args>
@@ -732,7 +722,7 @@ public:
             inline reference operator*() const  { return this->val(); }
             inline reference operator()() const { return this->val(); }
 
-            //- For pointer types, allow direct pointer dereferencing
+            //- Direct pointer dereferencing (pointer types)
             template<class TypeT = T>
             typename std::enable_if
             <
@@ -740,6 +730,14 @@ public:
                 T
             >::type operator->() const { return this->val(); }
 
+            //- Address of iterated value (non-pointer types)
+            template<class TypeT = T>
+            typename std::enable_if
+            <
+                !Detail::isPointer<TypeT>::value,
+                T*
+            >::type operator->() const { return &(this->val()); }
+
             inline iterator& operator++();
             inline iterator operator++(int);
         };
@@ -802,7 +800,7 @@ public:
             inline reference operator*() const  { return this->val(); }
             inline reference operator()() const { return this->val(); }
 
-            //- For pointer types, allow direct pointer dereferencing
+            //- Direct pointer dereferencing (pointer types)
             template<class TypeT = T>
             typename std::enable_if
             <
@@ -810,6 +808,14 @@ public:
                 const T
             >::type operator->() const { return this->val(); }
 
+            //- Address of iterated value (non-pointer types)
+            template<class TypeT = T>
+            typename std::enable_if
+            <
+                !Detail::isPointer<TypeT>::value,
+                const T*
+            >::type operator->() const { return &(this->val()); }
+
             inline const_iterator& operator++();
             inline const_iterator operator++(int);
 
@@ -911,22 +917,16 @@ public:
         //- when length exceeds shortLen.
         //  Using '0' suppresses line-breaks entirely.
         Ostream& writeKeys(Ostream& os, const label shortLen=0) const;
+};
 
 
-    // IOstream Operator
+// IOstream Operators
 
-        friend Istream& operator>> <T, Key, Hash>
-        (
-            Istream& is,
-            HashTable<T, Key, Hash>& tbl
-        );
+template<class T, class Key, class Hash>
+Istream& operator>>(Istream& is, HashTable<T, Key, Hash>& tbl);
 
-        friend Ostream& operator<< <T, Key, Hash>
-        (
-            Ostream& os,
-            const HashTable<T, Key, Hash>& tbl
-        );
-};
+template<class T, class Key, class Hash>
+Ostream& operator<<(Ostream& os, const HashTable<T, Key, Hash>& tbl);
 
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C b/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C
index ec3922f691a5a321755095767fce8b7709177d0c..4023cb5ffb01775419ca6b1bb8b6e5f2b19d7140 100644
--- a/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C
+++ b/src/OpenFOAM/containers/HashTables/HashTable/HashTableIO.C
@@ -29,28 +29,6 @@ License
 #include "Istream.H"
 #include "Ostream.H"
 
-// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
-
-template<class T, class Key, class Hash>
-bool Foam::HashTable<T, Key, Hash>::addEntry(Istream& is, const bool overwrite)
-{
-    typename node_type::key_type key;
-    typename node_type::mapped_type val;
-
-    is >> key >> val;
-
-    const bool ok = this->setEntry(overwrite, key, val);
-
-    is.fatalCheck
-    (
-        "HashTable::addEntry(Istream&) : "
-        "reading entry"
-    );
-
-    return ok;
-}
-
-
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 template<class T, class Key, class Hash>
@@ -168,11 +146,11 @@ template<class T, class Key, class Hash>
 Foam::Istream& Foam::operator>>
 (
     Istream& is,
-    HashTable<T, Key, Hash>& L
+    HashTable<T, Key, Hash>& tbl
 )
 {
     // Anull existing table
-    L.clear();
+    tbl.clear();
 
     is.fatalCheck(FUNCTION_NAME);
 
@@ -193,23 +171,31 @@ Foam::Istream& Foam::operator>>
 
         if (len)
         {
-            if (2*len > L.capacity_)
+            if (delimiter != token::BEGIN_LIST)
             {
-                L.resize(2*len);
+                FatalIOErrorInFunction(is)
+                    << "incorrect first token, '(', found " << firstToken.info()
+                    << exit(FatalIOError);
             }
 
-            if (delimiter == token::BEGIN_LIST)
+            if (2*len > tbl.capacity())
             {
-                for (label i=0; i<len; ++i)
-                {
-                    L.addEntry(is);
-                }
+                tbl.resize(2*len);
             }
-            else
+
+            for (label i=0; i<len; ++i)
             {
-                FatalIOErrorInFunction(is)
-                    << "incorrect first token, '(', found " << firstToken.info()
-                    << exit(FatalIOError);
+                Key key;
+
+                is >> key;          // Read the key
+                T& val = tbl(key);  // Insert nameless T() into table
+                is >> val;          // Read directly into the table value
+
+                is.fatalCheck
+                (
+                    "operator>>(Istream&, HashTable&) : "
+                    "reading entry"
+                );
             }
         }
 
@@ -236,7 +222,17 @@ Foam::Istream& Foam::operator>>
         {
             is.putBack(lastToken);
 
-            L.addEntry(is);
+            Key key;
+
+            is >> key;          // Read the key
+            T& val = tbl(key);  // Insert nameless T() into table
+            is >> val;          // Read directly into the table value
+
+            is.fatalCheck
+            (
+                "operator>>(Istream&, HashTable&) : "
+                "reading entry"
+            );
 
             is >> lastToken;
         }
@@ -250,7 +246,6 @@ Foam::Istream& Foam::operator>>
     }
 
     is.fatalCheck(FUNCTION_NAME);
-
     return is;
 }