What is the fastest (built-in) comparison for stri

2020-05-24 19:53发布

What is the fastest built-in comparison-method for string-types in C#? I don't mind about the typographical/semantical meaning: the aim is to use the comparator in sorted lists in order to search fast in large collections. I think there are only two methods: Compare and CompareOrdinal. What's the fastest?

Additionally, is there is a faster method for those string-comparisons?

8条回答
戒情不戒烟
2楼-- · 2020-05-24 20:42

I think there's a few ways most C# developers go about comparing strings, with the following being the most common:

  • Compare - as you mentioned
  • CompareOrdinal - as you mentioned
  • ==
  • String.Equals
  • writing a custom algorithm to compare char by char

If you want to go to extremes, you can use other objects/methods that aren't so obvious:

  • SequenceEqual example:

    c1 = str1.ToCharArray(); c2 = str2.ToCharArray(); if (c1.SequenceEqual(c2))

  • IndexOf example: if (stringsWeAreComparingAgainst.IndexOf(stringsWeWantToSeeIfMatches, 0 , stringsWeWantToSeeIfMatches.Length) == 0)

  • Or you can implement Dictionary and HashSets, using the strings as "keys" and testing to see if they exist already with the string you want to compare against. For instance: if (hs.Contains(stringsWeWantToSeeIfMatches))

So feel free to slice and dice to find your own ways of doing things. Remember though someone is going to have to maintain the code and probably won't want to spend time trying to figure out why you're using whatever method you've decided to use.

As always, optimize as your own risk. :-)

查看更多
淡お忘
3楼-- · 2020-05-24 20:46

I designed a unit test to test string comparison speed using some of the methods mentioned in this post. This test was ran using .NET 4

In short, there isn't much much difference, and I had to go to 100,000,000 iterations to see a significant difference. Since it seems the characters are compared in turn until a difference is found, inevitably how similar the strings are plays a part.

These results actually seem to suggest that using str1.Equals(str2) is the fastest way to compare strings.

These are the results of the test, with the test class included:

######## SET 1 compared strings are the same: 0
#### Basic == compare: 413
#### Equals compare: 355
#### Equals(compare2, StringComparison.Ordinal) compare: 387
#### String.Compare(compare1, compare2, StringComparison.Ordinal) compare: 426
#### String.CompareOrdinal(compare1, compare2) compare: 412

######## SET 2 compared strings are NOT the same: 0
#### Basic == compare: 710
#### Equals compare: 733
#### Equals(compare2, StringComparison.Ordinal) compare: 840
#### String.Compare(compare1, compare2, StringComparison.Ordinal) compare: 987
#### String.CompareOrdinal(compare1, compare2) compare: 776

using System;
using System.Diagnostics;
using NUnit.Framework;

namespace Fwr.UnitTests
{
    [TestFixture]
    public class StringTests
    {
        [Test]
        public void Test_fast_string_compare()
        {
            int iterations = 100000000;
            bool result = false;
            var stopWatch = new Stopwatch();

            Debug.WriteLine("######## SET 1 compared strings are the same: " + stopWatch.ElapsedMilliseconds);

            string compare1 = "xxxxxxxxxxxxxxxxxx";
            string compare2 = "xxxxxxxxxxxxxxxxxx";

            // Test 1

            stopWatch.Start();

            for (int i = 0; i < iterations; i++)
            {
                result = compare1 == compare2;
            }

            stopWatch.Stop();

            Debug.WriteLine("#### Basic == compare: " + stopWatch.ElapsedMilliseconds);

            stopWatch.Reset();

            // Test 2

            stopWatch.Start();

            for (int i = 0; i < iterations; i++)
            {
                result = compare1.Equals(compare2);
            }

            stopWatch.Stop();

            Debug.WriteLine("#### Equals compare: " + stopWatch.ElapsedMilliseconds);

            stopWatch.Reset();

            // Test 3

            stopWatch.Start();

            for (int i = 0; i < iterations; i++)
            {
                result = compare1.Equals(compare2, StringComparison.Ordinal);
            }

            stopWatch.Stop();

            Debug.WriteLine("#### Equals(compare2, StringComparison.Ordinal) compare: " + stopWatch.ElapsedMilliseconds);

            stopWatch.Reset();

            // Test 4

            stopWatch.Start();

            for (int i = 0; i < iterations; i++)
            {
                result = String.Compare(compare1, compare2, StringComparison.Ordinal) != 0;
            }

            stopWatch.Stop();

            Debug.WriteLine("#### String.Compare(compare1, compare2, StringComparison.Ordinal) compare: " + stopWatch.ElapsedMilliseconds);

            stopWatch.Reset();

            // Test 5

            stopWatch.Start();

            for (int i = 0; i < iterations; i++)
            {
                result = String.CompareOrdinal(compare1, compare2) != 0;
            }

            stopWatch.Stop();

            Debug.WriteLine("#### String.CompareOrdinal(compare1, compare2) compare: " + stopWatch.ElapsedMilliseconds);

            stopWatch.Reset();

            Debug.WriteLine("######## SET 2 compared strings are NOT the same: " + stopWatch.ElapsedMilliseconds);

            compare1 = "ueoqwwnsdlkskjsowy";
            compare2 = "sakjdjsjahsdhsjdak";

            // Test 1

            stopWatch.Start();

            for (int i = 0; i < iterations; i++)
            {
                result = compare1 == compare2;
            }

            stopWatch.Stop();

            Debug.WriteLine("#### Basic == compare: " + stopWatch.ElapsedMilliseconds);

            stopWatch.Reset();

            // Test 2

            stopWatch.Start();

            for (int i = 0; i < iterations; i++)
            {
                result = compare1.Equals(compare2);
            }

            stopWatch.Stop();

            Debug.WriteLine("#### Equals compare: " + stopWatch.ElapsedMilliseconds);

            stopWatch.Reset();

            // Test 3

            stopWatch.Start();

            for (int i = 0; i < iterations; i++)
            {
                result = compare1.Equals(compare2, StringComparison.Ordinal);
            }

            stopWatch.Stop();

            Debug.WriteLine("#### Equals(compare2, StringComparison.Ordinal) compare: " + stopWatch.ElapsedMilliseconds);

            stopWatch.Reset();

            // Test 4

            stopWatch.Start();

            for (int i = 0; i < iterations; i++)
            {
                result = String.Compare(compare1, compare2, StringComparison.Ordinal) != 0;
            }

            stopWatch.Stop();

            Debug.WriteLine("#### String.Compare(compare1, compare2, StringComparison.Ordinal) compare: " + stopWatch.ElapsedMilliseconds);

            stopWatch.Reset();

            // Test 5

            stopWatch.Start();

            for (int i = 0; i < iterations; i++)
            {
                result = String.CompareOrdinal(compare1, compare2) != 0;
            }

            stopWatch.Stop();

            Debug.WriteLine("#### String.CompareOrdinal(compare1, compare2) compare: " + stopWatch.ElapsedMilliseconds);

            stopWatch.Reset();
        }
    }
}
查看更多
登录 后发表回答