diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenDictionary.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenDictionary.cs
index 8582703ffdcb73..11a2db81912d57 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenDictionary.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenDictionary.cs
@@ -229,15 +229,15 @@ private static FrozenDictionary<TKey, TValue> ChooseImplementationOptimizedForRe
             if (typeof(TKey) == typeof(string) &&
                 (ReferenceEquals(comparer, EqualityComparer<TKey>.Default) || ReferenceEquals(comparer, StringComparer.Ordinal) || ReferenceEquals(comparer, StringComparer.OrdinalIgnoreCase)))
             {
-                Dictionary<string, TValue> stringEntries = (Dictionary<string, TValue>)(object)source;
                 IEqualityComparer<string> stringComparer = (IEqualityComparer<string>)(object)comparer;
 
-                // this array is needed for every strategy
-                string[] entries = (string[])(object)source.Keys.ToArray();
+                // keys and values are needed for every strategy
+                string[] keys = (string[])(object)source.Keys.ToArray();
+                TValue[] values = source.Values.ToArray();
 
                 // Calculate the minimum and maximum lengths of the strings in the dictionary. Several of the analyses need this.
                 int minLength = int.MaxValue, maxLength = 0;
-                foreach (string key in entries)
+                foreach (string key in keys)
                 {
                     if (key.Length < minLength) minLength = key.Length;
                     if (key.Length > maxLength) maxLength = key.Length;
@@ -245,14 +245,14 @@ private static FrozenDictionary<TKey, TValue> ChooseImplementationOptimizedForRe
                 Debug.Assert(minLength >= 0 && maxLength >= minLength);
 
                 // Try to create an implementation that uses length buckets, where each bucket contains up to only a few strings of the same length.
-                FrozenDictionary<string, TValue>? frozenDictionary = LengthBucketsFrozenDictionary<TValue>.CreateLengthBucketsFrozenDictionaryIfAppropriate(stringEntries, stringComparer, minLength, maxLength, entries);
+                FrozenDictionary<string, TValue>? frozenDictionary = LengthBucketsFrozenDictionary<TValue>.CreateLengthBucketsFrozenDictionaryIfAppropriate(keys, values, stringComparer, minLength, maxLength);
                 if (frozenDictionary is not null)
                 {
                     return (FrozenDictionary<TKey, TValue>)(object)frozenDictionary;
                 }
 
                 // Analyze the keys for unique substrings and create an implementation that minimizes the cost of hashing keys.
-                KeyAnalyzer.AnalysisResults analysis = KeyAnalyzer.Analyze(entries, ReferenceEquals(stringComparer, StringComparer.OrdinalIgnoreCase), minLength, maxLength);
+                KeyAnalyzer.AnalysisResults analysis = KeyAnalyzer.Analyze(keys, ReferenceEquals(stringComparer, StringComparer.OrdinalIgnoreCase), minLength, maxLength);
                 if (analysis.SubstringHashing)
                 {
                     if (analysis.RightJustifiedSubstring)
@@ -260,14 +260,14 @@ private static FrozenDictionary<TKey, TValue> ChooseImplementationOptimizedForRe
                         if (analysis.IgnoreCase)
                         {
                             frozenDictionary = analysis.AllAsciiIfIgnoreCase
-                                ? new OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveAsciiSubstring<TValue>(stringEntries, entries, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount)
-                                : new OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveSubstring<TValue>(stringEntries, entries, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount);
+                                ? new OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveAsciiSubstring<TValue>(keys, values, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount)
+                                : new OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveSubstring<TValue>(keys, values, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount);
                         }
                         else
                         {
                             frozenDictionary = analysis.HashCount == 1
-                                ? new OrdinalStringFrozenDictionary_RightJustifiedSingleChar<TValue>(stringEntries, entries, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex)
-                                : new OrdinalStringFrozenDictionary_RightJustifiedSubstring<TValue>(stringEntries, entries, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount);
+                                ? new OrdinalStringFrozenDictionary_RightJustifiedSingleChar<TValue>(keys, values, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex)
+                                : new OrdinalStringFrozenDictionary_RightJustifiedSubstring<TValue>(keys, values, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount);
                         }
                     }
                     else
@@ -275,14 +275,14 @@ private static FrozenDictionary<TKey, TValue> ChooseImplementationOptimizedForRe
                         if (analysis.IgnoreCase)
                         {
                             frozenDictionary = analysis.AllAsciiIfIgnoreCase
-                                ? new OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveAsciiSubstring<TValue>(stringEntries, entries, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount)
-                                : new OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveSubstring<TValue>(stringEntries, entries, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount);
+                                ? new OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveAsciiSubstring<TValue>(keys, values, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount)
+                                : new OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveSubstring<TValue>(keys, values, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount);
                         }
                         else
                         {
                             frozenDictionary = analysis.HashCount == 1
-                                ? new OrdinalStringFrozenDictionary_LeftJustifiedSingleChar<TValue>(stringEntries, entries, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex)
-                                : new OrdinalStringFrozenDictionary_LeftJustifiedSubstring<TValue>(stringEntries, entries, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount);
+                                ? new OrdinalStringFrozenDictionary_LeftJustifiedSingleChar<TValue>(keys, values, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex)
+                                : new OrdinalStringFrozenDictionary_LeftJustifiedSubstring<TValue>(keys, values, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff, analysis.HashIndex, analysis.HashCount);
                         }
                     }
                 }
@@ -291,12 +291,12 @@ private static FrozenDictionary<TKey, TValue> ChooseImplementationOptimizedForRe
                     if (analysis.IgnoreCase)
                     {
                         frozenDictionary = analysis.AllAsciiIfIgnoreCase
-                            ? new OrdinalStringFrozenDictionary_FullCaseInsensitiveAscii<TValue>(stringEntries, entries, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff)
-                            : new OrdinalStringFrozenDictionary_FullCaseInsensitive<TValue>(stringEntries, entries, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff);
+                            ? new OrdinalStringFrozenDictionary_FullCaseInsensitiveAscii<TValue>(keys, values, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff)
+                            : new OrdinalStringFrozenDictionary_FullCaseInsensitive<TValue>(keys, values, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff);
                     }
                     else
                     {
-                        frozenDictionary = new OrdinalStringFrozenDictionary_Full<TValue>(stringEntries, entries, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff);
+                        frozenDictionary = new OrdinalStringFrozenDictionary_Full<TValue>(keys, values, stringComparer, analysis.MinimumLength, analysis.MaximumLengthDiff);
                     }
                 }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs
index 72cf9adb16a2e8..15ba7478de2310 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/FrozenHashTable.cs
@@ -36,8 +36,7 @@ private FrozenHashTable(int[] hashCodes, Bucket[] buckets, ulong fastModMultipli
         }
 
         /// <summary>Initializes a frozen hash table.</summary>
-        /// <param name="entriesLength">The number of entries to track from the hash table.</param>
-        /// <param name="hashAtIndex">A delegate that produces a hash code for a given entry. It's passed the index of the entry and returns that entry's hash code.</param>
+        /// <param name="hashCodes">Pre-calculated hash codes.</param>
         /// <param name="storeDestIndexFromSrcIndex">A delegate that assigns the index to a specific entry. It's passed the destination and source indices.</param>
         /// <param name="optimizeForReading">true to spend additional effort tuning for subsequent read speed on the table; false to prioritize construction time.</param>
         /// <remarks>
@@ -48,18 +47,8 @@ private FrozenHashTable(int[] hashCodes, Bucket[] buckets, ulong fastModMultipli
         /// then uses this index to reference individual entries by indexing into <see cref="HashCodes"/>.
         /// </remarks>
         /// <returns>A frozen hash table.</returns>
-        public static FrozenHashTable Create(int entriesLength, Func<int, int> hashAtIndex, Action<int, int> storeDestIndexFromSrcIndex, bool optimizeForReading = true)
+        public static FrozenHashTable Create(ReadOnlySpan<int> hashCodes, Action<int, int> storeDestIndexFromSrcIndex, bool optimizeForReading = true)
         {
-            Debug.Assert(entriesLength != 0);
-
-            // Calculate the hashcodes for every entry.
-            int[] arrayPoolHashCodes = ArrayPool<int>.Shared.Rent(entriesLength);
-            Span<int> hashCodes = arrayPoolHashCodes.AsSpan(0, entriesLength);
-            for (int i = 0; i < entriesLength; i++)
-            {
-                hashCodes[i] = hashAtIndex(i);
-            }
-
             // Determine how many buckets to use.  This might be fewer than the number of entries
             // if any entries have identical hashcodes (not just different hashcodes that might
             // map to the same bucket).
@@ -124,7 +113,6 @@ public static FrozenHashTable Create(int entriesLength, Func<int, int> hashAtInd
             Debug.Assert(count == hashtableHashcodes.Length);
 
             ArrayPool<int>.Shared.Return(arrayPoolBuckets);
-            ArrayPool<int>.Shared.Return(arrayPoolHashCodes);
 
             return new FrozenHashTable(hashtableHashcodes, hashtableBuckets, fastModMultiplier);
         }
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenDictionary.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenDictionary.cs
index bedcbb6bd080aa..e98715887adddc 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenDictionary.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenDictionary.cs
@@ -1,6 +1,7 @@
 ﻿// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Buffers;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
@@ -27,10 +28,18 @@ internal Int32FrozenDictionary(Dictionary<int, TValue> source) : base(EqualityCo
 
             _values = new TValue[entries.Length];
 
+            int[] arrayPoolHashCodes = ArrayPool<int>.Shared.Rent(entries.Length);
+            Span<int> hashCodes = arrayPoolHashCodes.AsSpan(0, entries.Length);
+            for (int i = 0; i < entries.Length; i++)
+            {
+                hashCodes[i] = entries[i].Key;
+            }
+
             _hashTable = FrozenHashTable.Create(
-                entries.Length,
-                index => entries[index].Key,
+                hashCodes,
                 (destIndex, srcIndex) => _values[destIndex] = entries[srcIndex].Value);
+
+            ArrayPool<int>.Shared.Return(arrayPoolHashCodes);
         }
 
         /// <inheritdoc />
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenSet.cs
index 7f1da9dfa5522e..4317b319abfccd 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenSet.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/Int32/Int32FrozenSet.cs
@@ -26,9 +26,8 @@ internal Int32FrozenSet(HashSet<int> source) : base(EqualityComparer<int>.Defaul
             source.CopyTo(entries);
 
             _hashTable = FrozenHashTable.Create(
-                count,
-                index => entries[index],
-                delegate { });
+                new ReadOnlySpan<int>(entries, 0, count),
+                static delegate { });
 
             ArrayPool<int>.Shared.Return(entries);
         }
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/ItemsFrozenSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/ItemsFrozenSet.cs
index abf91889fe46b1..db94a1a8e38f64 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/ItemsFrozenSet.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/ItemsFrozenSet.cs
@@ -1,6 +1,7 @@
 ﻿// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Buffers;
 using System.Collections.Generic;
 using System.Diagnostics;
 
@@ -22,11 +23,19 @@ protected ItemsFrozenSet(HashSet<T> source, bool optimizeForReading = true) : ba
 
             _items = new T[entries.Length];
 
+            int[] arrayPoolHashCodes = ArrayPool<int>.Shared.Rent(entries.Length);
+            Span<int> hashCodes = arrayPoolHashCodes.AsSpan(0, entries.Length);
+            for (int i = 0; i < entries.Length; i++)
+            {
+                hashCodes[i] = entries[i] is T t ? Comparer.GetHashCode(t) : 0;
+            }
+
             _hashTable = FrozenHashTable.Create(
-                entries.Length,
-                index => entries[index] is T t ? Comparer.GetHashCode(t) : 0,
+                hashCodes,
                 (destIndex, srcIndex) => _items[destIndex] = entries[srcIndex],
                 optimizeForReading);
+
+            ArrayPool<int>.Shared.Return(arrayPoolHashCodes);
         }
 
         /// <inheritdoc />
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/KeysAndValuesFrozenDictionary.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/KeysAndValuesFrozenDictionary.cs
index fb168cf1b65ecc..ab0cba77c2f10d 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/KeysAndValuesFrozenDictionary.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/KeysAndValuesFrozenDictionary.cs
@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Buffers;
 using System.Collections.Generic;
 using System.Diagnostics;
 
@@ -24,15 +25,23 @@ protected KeysAndValuesFrozenDictionary(Dictionary<TKey, TValue> source, bool op
             _keys = new TKey[entries.Length];
             _values = new TValue[entries.Length];
 
+            int[] arrayPoolHashCodes = ArrayPool<int>.Shared.Rent(entries.Length);
+            Span<int> hashCodes = arrayPoolHashCodes.AsSpan(0, entries.Length);
+            for (int i = 0; i < entries.Length; i++)
+            {
+                hashCodes[i] = Comparer.GetHashCode(entries[i].Key);
+            }
+
             _hashTable = FrozenHashTable.Create(
-                entries.Length,
-                index => Comparer.GetHashCode(entries[index].Key),
+                hashCodes,
                 (destIndex, srcIndex) =>
                 {
                     _keys[destIndex] = entries[srcIndex].Key;
                     _values[destIndex] = entries[srcIndex].Value;
                 },
                 optimizeForReading);
+
+            ArrayPool<int>.Shared.Return(arrayPoolHashCodes);
         }
 
         /// <inheritdoc />
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs
index 9da8b3c61e5739..51e70f3f63ba34 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/KeyAnalyzer.cs
@@ -225,7 +225,7 @@ private static bool HasSufficientUniquenessFactor(HashSet<string> set, ReadOnlyS
         {
             set.Clear();
 
-            // SufficientUniquenessFactor of 95% is good enough.
+            // Sufficient uniqueness factor of 95% is good enough.
             // Instead of ensuring that 95% of data is good, we stop when we know that at least 5% is bad.
             int acceptableNonUniqueCount = uniqueStrings.Length / 20;
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBucketsFrozenDictionary.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBucketsFrozenDictionary.cs
index 4a83ac05485b0a..ce0687b2e8c4b9 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBucketsFrozenDictionary.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/LengthBucketsFrozenDictionary.cs
@@ -36,25 +36,25 @@ private LengthBucketsFrozenDictionary(
         }
 
         internal static LengthBucketsFrozenDictionary<TValue>? CreateLengthBucketsFrozenDictionaryIfAppropriate(
-            Dictionary<string, TValue> source, IEqualityComparer<string> comparer, int minLength, int maxLength, string[] keys)
+            string[] keys, TValue[] values, IEqualityComparer<string> comparer, int minLength, int maxLength)
         {
-            Debug.Assert(source.Count != 0);
+            Debug.Assert(keys.Length != 0 && keys.Length == values.Length);
             Debug.Assert(comparer == EqualityComparer<string>.Default || comparer == StringComparer.Ordinal || comparer == StringComparer.OrdinalIgnoreCase);
             Debug.Assert(minLength >= 0 && maxLength >= minLength);
 
             // If without even looking at the keys we know that some bucket will exceed the max per-bucket
             // limit (pigeon hole principle), we can early-exit out without doing any further work.
             int spread = maxLength - minLength + 1;
-            if (source.Count / spread > MaxPerLength)
+            if (keys.Length / spread > MaxPerLength)
             {
                 return null;
             }
 
             // Iterate through all of the inputs, bucketing them based on the length of the string.
             var groupedByLength = new Dictionary<int, List<KeyValuePair<string, TValue>>>();
-            foreach (KeyValuePair<string, TValue> pair in source)
+            for (int i = 0; i < keys.Length; i++)
             {
-                string s = pair.Key;
+                string s = keys[i];
                 Debug.Assert(s.Length >= minLength && s.Length <= maxLength);
 
 #if NET6_0_OR_GREATER
@@ -72,7 +72,7 @@ private LengthBucketsFrozenDictionary(
                     return null;
                 }
 
-                list.Add(pair);
+                list.Add(new KeyValuePair<string, TValue>(s, values[i]));
             }
 
             // If there would be too much empty space in the lookup array, bail.
@@ -81,7 +81,6 @@ private LengthBucketsFrozenDictionary(
                 return null;
             }
 
-            var values = new TValue[keys.Length];
             var lengthBuckets = new KeyValuePair<string, int>[spread][];
 
             // Iterate through each bucket, filling the keys/values arrays, and creating a lookup array such that
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary.cs
index b9f7dfd89cd10d..2cb519ead4521b 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary.cs
@@ -1,6 +1,7 @@
 ﻿// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Buffers;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
@@ -17,8 +18,8 @@ internal abstract class OrdinalStringFrozenDictionary<TValue> : FrozenDictionary
         private readonly int _maximumLengthDiff;
 
         internal OrdinalStringFrozenDictionary(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff,
@@ -26,28 +27,35 @@ internal OrdinalStringFrozenDictionary(
             int hashCount = -1) :
             base(comparer)
         {
-            Debug.Assert(source.Count != 0);
+            Debug.Assert(keys.Length != 0 && keys.Length == values.Length);
             Debug.Assert(comparer == EqualityComparer<string>.Default || comparer == StringComparer.Ordinal || comparer == StringComparer.OrdinalIgnoreCase);
 
-            var entries = new KeyValuePair<string, TValue>[source.Count];
-            ((ICollection<KeyValuePair<string, TValue>>)source).CopyTo(entries, 0);
+            // we need an extra copy, as the order of items will change
+            _keys = new string[keys.Length];
+            _values = new TValue[values.Length];
 
-            _keys = keys;
-            _values = new TValue[entries.Length];
             _minimumLength = minimumLength;
             _maximumLengthDiff = maximumLengthDiff;
 
             HashIndex = hashIndex;
             HashCount = hashCount;
 
+            int[] arrayPoolHashCodes = ArrayPool<int>.Shared.Rent(keys.Length);
+            Span<int> hashCodes = arrayPoolHashCodes.AsSpan(0, keys.Length);
+            for (int i = 0; i < keys.Length; i++)
+            {
+                hashCodes[i] = GetHashCode(keys[i]);
+            }
+
             _hashTable = FrozenHashTable.Create(
-                entries.Length,
-                index => GetHashCode(entries[index].Key),
+                hashCodes,
                 (destIndex, srcIndex) =>
                 {
-                    _keys[destIndex] = entries[srcIndex].Key;
-                    _values[destIndex] = entries[srcIndex].Value;
+                    _keys[destIndex] = keys[srcIndex];
+                    _values[destIndex] = values[srcIndex];
                 });
+
+            ArrayPool<int>.Shared.Return(arrayPoolHashCodes);
         }
 
         private protected int HashIndex { get; }
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_Full.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_Full.cs
index 9ef93cac7fb068..56ce7ff720bd52 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_Full.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_Full.cs
@@ -8,12 +8,12 @@ namespace System.Collections.Frozen
     internal sealed class OrdinalStringFrozenDictionary_Full<TValue> : OrdinalStringFrozenDictionary<TValue>
     {
         internal OrdinalStringFrozenDictionary_Full(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff)
-            : base(source, keys, comparer, minimumLength, maximumLengthDiff)
+            : base(keys, values, comparer, minimumLength, maximumLengthDiff)
         {
         }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_FullCaseInsensitive.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_FullCaseInsensitive.cs
index 0ec65c06b1d67f..3f09ba59dc7eee 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_FullCaseInsensitive.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_FullCaseInsensitive.cs
@@ -8,12 +8,12 @@ namespace System.Collections.Frozen
     internal sealed class OrdinalStringFrozenDictionary_FullCaseInsensitive<TValue> : OrdinalStringFrozenDictionary<TValue>
     {
         internal OrdinalStringFrozenDictionary_FullCaseInsensitive(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff)
-            : base(source, keys, comparer, minimumLength, maximumLengthDiff)
+            : base(keys, values, comparer, minimumLength, maximumLengthDiff)
         {
         }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_FullCaseInsensitiveAscii.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_FullCaseInsensitiveAscii.cs
index c814f2b3f9556d..b029567243ced4 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_FullCaseInsensitiveAscii.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_FullCaseInsensitiveAscii.cs
@@ -8,12 +8,12 @@ namespace System.Collections.Frozen
     internal sealed class OrdinalStringFrozenDictionary_FullCaseInsensitiveAscii<TValue> : OrdinalStringFrozenDictionary<TValue>
     {
         internal OrdinalStringFrozenDictionary_FullCaseInsensitiveAscii(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff)
-            : base(source, keys, comparer, minimumLength, maximumLengthDiff)
+            : base(keys, values, comparer, minimumLength, maximumLengthDiff)
         {
         }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveAsciiSubstring.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveAsciiSubstring.cs
index 166ae6a025989b..401b0f2dc0b121 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveAsciiSubstring.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveAsciiSubstring.cs
@@ -8,14 +8,14 @@ namespace System.Collections.Frozen
     internal sealed class OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveAsciiSubstring<TValue> : OrdinalStringFrozenDictionary<TValue>
     {
         internal OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveAsciiSubstring(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff,
             int hashIndex,
             int hashCount)
-            : base(source, keys, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
+            : base(keys, values, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
         {
         }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveSubstring.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveSubstring.cs
index dad71c443e934e..c533441139918f 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveSubstring.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveSubstring.cs
@@ -8,14 +8,14 @@ namespace System.Collections.Frozen
     internal sealed class OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveSubstring<TValue> : OrdinalStringFrozenDictionary<TValue>
     {
         internal OrdinalStringFrozenDictionary_LeftJustifiedCaseInsensitiveSubstring(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff,
             int hashIndex,
             int hashCount)
-            : base(source, keys, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
+            : base(keys, values, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
         {
         }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedSingleChar.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedSingleChar.cs
index ca03320c8ddeb1..b2bb0bb97b1a6c 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedSingleChar.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedSingleChar.cs
@@ -8,13 +8,13 @@ namespace System.Collections.Frozen
     internal sealed class OrdinalStringFrozenDictionary_LeftJustifiedSingleChar<TValue> : OrdinalStringFrozenDictionary<TValue>
     {
         internal OrdinalStringFrozenDictionary_LeftJustifiedSingleChar(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff,
             int hashIndex)
-            : base(source, keys, comparer, minimumLength, maximumLengthDiff, hashIndex, 1)
+            : base(keys, values, comparer, minimumLength, maximumLengthDiff, hashIndex, 1)
         {
         }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedSubstring.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedSubstring.cs
index d48e4738e9aa21..2812dde4f1027c 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedSubstring.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_LeftJustifiedSubstring.cs
@@ -8,14 +8,14 @@ namespace System.Collections.Frozen
     internal sealed class OrdinalStringFrozenDictionary_LeftJustifiedSubstring<TValue> : OrdinalStringFrozenDictionary<TValue>
     {
         internal OrdinalStringFrozenDictionary_LeftJustifiedSubstring(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff,
             int hashIndex,
             int hashCount)
-            : base(source, keys, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
+            : base(keys, values, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
         {
         }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveAsciiSubstring.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveAsciiSubstring.cs
index b26d2a1abe72b5..22cf6b640af67b 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveAsciiSubstring.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveAsciiSubstring.cs
@@ -8,14 +8,14 @@ namespace System.Collections.Frozen
     internal sealed class OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveAsciiSubstring<TValue> : OrdinalStringFrozenDictionary<TValue>
     {
         internal OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveAsciiSubstring(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff,
             int hashIndex,
             int hashCount)
-            : base(source, keys, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
+            : base(keys, values, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
         {
         }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveSubstring.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveSubstring.cs
index fc348bc437b975..a2fec247a28734 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveSubstring.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveSubstring.cs
@@ -8,14 +8,14 @@ namespace System.Collections.Frozen
     internal sealed class OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveSubstring<TValue> : OrdinalStringFrozenDictionary<TValue>
     {
         internal OrdinalStringFrozenDictionary_RightJustifiedCaseInsensitiveSubstring(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff,
             int hashIndex,
             int hashCount)
-            : base(source, keys, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
+            : base(keys, values, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
         {
         }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedSingleChar.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedSingleChar.cs
index 60c8ecc0180b78..cb7ae5fda7b4d4 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedSingleChar.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedSingleChar.cs
@@ -8,13 +8,13 @@ namespace System.Collections.Frozen
     internal sealed class OrdinalStringFrozenDictionary_RightJustifiedSingleChar<TValue> : OrdinalStringFrozenDictionary<TValue>
     {
         internal OrdinalStringFrozenDictionary_RightJustifiedSingleChar(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff,
             int hashIndex)
-            : base(source, keys, comparer, minimumLength, maximumLengthDiff, hashIndex, 1)
+            : base(keys, values, comparer, minimumLength, maximumLengthDiff, hashIndex, 1)
         {
         }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedSubstring.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedSubstring.cs
index f4dd7ad7bb5bef..cd8fe0602ef7b5 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedSubstring.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenDictionary_RightJustifiedSubstring.cs
@@ -8,14 +8,14 @@ namespace System.Collections.Frozen
     internal sealed class OrdinalStringFrozenDictionary_RightJustifiedSubstring<TValue> : OrdinalStringFrozenDictionary<TValue>
     {
         internal OrdinalStringFrozenDictionary_RightJustifiedSubstring(
-            Dictionary<string, TValue> source,
             string[] keys,
+            TValue[] values,
             IEqualityComparer<string> comparer,
             int minimumLength,
             int maximumLengthDiff,
             int hashIndex,
             int hashCount)
-            : base(source, keys, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
+            : base(keys, values, comparer, minimumLength, maximumLengthDiff, hashIndex, hashCount)
         {
         }
 
diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenSet.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenSet.cs
index f4c7700f0dd88d..1ee4b277b21132 100644
--- a/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenSet.cs
+++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Frozen/String/OrdinalStringFrozenSet.cs
@@ -1,6 +1,7 @@
 ﻿// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Buffers;
 using System.Collections.Generic;
 using System.Runtime.CompilerServices;
 
@@ -30,10 +31,18 @@ internal OrdinalStringFrozenSet(
             HashIndex = hashIndex;
             HashCount = hashCount;
 
+            int[] arrayPoolHashCodes = ArrayPool<int>.Shared.Rent(entries.Length);
+            Span<int> hashCodes = arrayPoolHashCodes.AsSpan(0, entries.Length);
+            for (int i = 0; i < entries.Length; i++)
+            {
+                hashCodes[i] = GetHashCode(entries[i]);
+            }
+
             _hashTable = FrozenHashTable.Create(
-                entries.Length,
-                index => GetHashCode(entries[index]),
+                hashCodes,
                 (destIndex, srcIndex) => _items[destIndex] = entries[srcIndex]);
+
+            ArrayPool<int>.Shared.Return(arrayPoolHashCodes);
         }
 
         private protected int HashIndex { get; }
