- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在使用 Mergesort 对 50.000.000 个字符串进行排序,根据我使用的参数类型,有两种不同的结果。
使用接口(interface) IComparable:
直接使用字符串:
合并排序代码:
public class Mergesort2
{
static private StringComparer comparer1 = StringComparer.Ordinal;
public static void merge(IComparable[] a, IComparable[] aux, int lo, int mid, int hi)
{
for (int k = lo; k <= hi; k++)
{
aux[k] = a[k];
}
// merge back to a[]
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++)
{
if (i > mid)
{
a[k] = aux[j++];
}
else if (j > hi)
{
a[k] = aux[i++];
}
else if (less(aux[j], aux[i]))
{
a[k] = aux[j++];
}
else
{
a[k] = aux[i++];
}
}
}
private static void sort(IComparable[] a, IComparable[] aux, int lo, int hi)
{
if (hi <= lo)
{
return;
}
int mid = lo + (hi - lo) / 2;
sort(a, aux, lo, mid);
sort(a, aux, mid + 1, hi);
merge(a, aux, lo, mid, hi);
}
public static void sort(IComparable[] a)
{
IComparable[] aux = new IComparable[a.Length];
sort(a, aux, 0, a.Length - 1);
}
///*********************************************************************
/// Helper sorting functions
/// **********************************************************************
// is v < w ?
private static bool less(IComparable v, IComparable w)
{
return (comparer1.Compare(v, w) < 0);
}
// exchange a[i] and a[j]
private static void exch(Object[] a, int i, int j)
{
Object swap = a[i];
a[i] = a[j];
a[j] = swap;
}
/// <summary>
///*********************************************************************
/// Index mergesort
/// **********************************************************************
/// </summary>
// stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi]
private static void merge(IComparable[] a, int[] index, int[] aux, int lo, int mid, int hi)
{
// copy to aux[]
for (int k = lo; k <= hi; k++)
{
aux[k] = index[k];
}
// merge back to a[]
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++)
{
if (i > mid)
{
index[k] = aux[j++];
}
else if (j > hi)
{
index[k] = aux[i++];
}
else if (less(a[aux[j]], a[aux[i]]))
{
index[k] = aux[j++];
}
else
{
index[k] = aux[i++];
}
}
}
// return a permutation that gives the elements in a[] in ascending order
// do not change the original array a[]
public static int[] indexSort(IComparable[] a)
{
int N = a.Length;
int[] index = new int[N];
for (int i = 0; i < N; i++)
{
index[i] = i;
}
int[] aux = new int[N];
sort(a, index, aux, 0, N - 1);
return index;
}
// mergesort a[lo..hi] using auxiliary array aux[lo..hi]
private static void sort(IComparable[] a, int[] index, int[] aux, int lo, int hi)
{
if (hi <= lo)
{
return;
}
int mid = lo + (hi - lo) / 2;
sort(a, index, aux, lo, mid);
sort(a, index, aux, mid + 1, hi);
merge(a, index, aux, lo, mid, hi);
}
}
此代码会产生缓慢的运行时间。
如果我将所有 IComparable 类型更改为 String,性能将会提高。为什么使用不同的类型会有如此巨大的性能差异?
最佳答案
要回答有关性能的问题:您的测试使用的字符串足够小,以至于需要额外的类型检查才能使用非通用 IComparable
interface,以及使用 interface-dispatch 而不是 virtual-dispatch(.NET 和 Java VM 等虚拟机的低级细节)比字符串比较更昂贵。如果您使用带有长公共(public)前缀的字符串,比较操作将成为主要的性能成本,并且两种形式之间的差距将会缩小。 编辑:在代码的发布版本上运行测试也可能会缩小差距(没有在本地运行测试,我不确定 OP 用于测试的版本)。 p>
现在更重要的是整个实验,忽略代码的所有其他问题,我将特别指出支持“可比较”项目的常见做法在 .NET 中以通用方式。
T
(可能是也可能不是 string
,如果事实上它可能会或可能不会实现 IComparable
)。IComparer<T>
比较元素。如果用户传递 null
对于 comparer
公共(public)方法之一的参数,默认为 Comparer<T>.Default
.这是更新后的代码:
public class Mergesort2
{
public static void merge<T>(T[] a, T[] aux, int lo, int mid, int hi, IComparer<T> comparer)
{
comparer = comparer ?? Comparer<T>.Default;
for (int k = lo; k <= hi; k++)
{
aux[k] = a[k];
}
// merge back to a[]
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++)
{
if (i > mid)
{
a[k] = aux[j++];
}
else if (j > hi)
{
a[k] = aux[i++];
}
else if (less(aux[j], aux[i], comparer))
{
a[k] = aux[j++];
}
else
{
a[k] = aux[i++];
}
}
}
private static void sort<T>(T[] a, T[] aux, int lo, int hi, IComparer<T> comparer)
{
if (hi <= lo)
{
return;
}
int mid = lo + (hi - lo) / 2;
sort(a, aux, lo, mid, comparer);
sort(a, aux, mid + 1, hi, comparer);
merge(a, aux, lo, mid, hi, comparer);
}
public static void sort<T>(T[] a, IComparer<T> comparer)
{
comparer = comparer ?? Comparer<T>.Default;
T[] aux = new T[a.Length];
sort(a, aux, 0, a.Length - 1, comparer);
}
///*********************************************************************
/// Helper sorting functions
/// **********************************************************************
// is v < w ?
private static bool less<T>(T v, T w, IComparer<T> comparer)
{
return (comparer.Compare(v, w) < 0);
}
// exchange a[i] and a[j]
private static void exch<T>(T[] a, int i, int j)
{
T swap = a[i];
a[i] = a[j];
a[j] = swap;
}
/// <summary>
///*********************************************************************
/// Index mergesort
/// **********************************************************************
/// </summary>
// stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi]
private static void merge<T>(T[] a, int[] index, int[] aux, int lo, int mid, int hi, IComparer<T> comparer)
{
// copy to aux[]
for (int k = lo; k <= hi; k++)
{
aux[k] = index[k];
}
// merge back to a[]
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++)
{
if (i > mid)
{
index[k] = aux[j++];
}
else if (j > hi)
{
index[k] = aux[i++];
}
else if (less(a[aux[j]], a[aux[i]], comparer))
{
index[k] = aux[j++];
}
else
{
index[k] = aux[i++];
}
}
}
// return a permutation that gives the elements in a[] in ascending order
// do not change the original array a[]
public static int[] indexSort<T>(T[] a, IComparer<T> comparer)
{
comparer = comparer ?? Comparer<T>.Default;
int N = a.Length;
int[] index = new int[N];
for (int i = 0; i < N; i++)
{
index[i] = i;
}
int[] aux = new int[N];
sort(a, index, aux, 0, N - 1, comparer);
return index;
}
// mergesort a[lo..hi] using auxiliary array aux[lo..hi]
private static void sort<T>(T[] a, int[] index, int[] aux, int lo, int hi, IComparer<T> comparer)
{
if (hi <= lo)
{
return;
}
int mid = lo + (hi - lo) / 2;
sort(a, index, aux, lo, mid, comparer);
sort(a, index, aux, mid + 1, hi, comparer);
merge(a, index, aux, lo, mid, hi, comparer);
}
}
关于c# - 为什么在比较中使用 IComparable 比使用字符串慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15317894/
我如何实现 IComparer int CompareTo(object obj) 有一个额外的参数,比如 int CompareTo(object obj, Dictionary preferenc
我在正确使用 IComparable<> 时遇到了一些麻烦界面。我还创建了一个实现 IComparer<> 的类.我几乎从一本书中复制了确切的编码示例,但对其进行了重新设计以适应我的情况,但它似乎无法
我是否应该同时实现 IComparable和通用 IComparable ?如果我只实现其中之一,是否有任何限制? 最佳答案 是的,您应该同时实现两者。 如果你实现其中一个,任何依赖于另一个的代码都会
这个问题在这里已经有了答案: When to use IComparable Vs. IComparer (8 个答案) 关闭 4 年前。 IComparable 和IComparer 接口(int
我正在尝试实现此链接的相同示例,但更注重受抚养 child 的数量。 http://www.codeproject.com/Articles/42839/Sorting-Lists-using-ICo
在大多数地方,我读到从 IComparable 继承是个好主意。和 IComparable在你的类中提供与非通用集合的兼容性。我的问题是为什么IComparable不继承自 IComparable那么
我正在使用 WPF 博士的 ObservableSortedDictionary。 构造函数如下所示: public ObservableSortedDictionary(IComparer comp
我知道 IComparable 之间有很大的区别和 IComparable一般情况下,请参阅 this , 但在这种搜索方法中,它不会有任何区别,还是会这样? public static int Se
我是 C# 的新手(6 个月的工作经验),但它看起来与 Java 非常相似,所以我感觉很自在。 但是,今天我尝试实现 IComparer 接口(interface)并想知道为什么它会给我一个错误: p
我有 Employee 类,我需要实现 IComparable 并使用 CompareTo 方法按姓名对员工进行排序。据我所知,我必须返回 1、-1 和 0,但我该如何使用这些字符串? 这是我的。 c
是否可以使用 iComparer 使用对象中的两个值对列表进行排序? 我有一个基于 value1 排序的自定义比较器类。但是对 value1 和 value2 进行排序的最佳方法是什么? 按 valu
我为装箱的 RegistryItem 对象定义了以下 IComparer: public class BoxedRegistryItemComparer : IComparer { publi
我正在尝试在相似值列表中获取唯一值,仅通过管道分隔字符串中的一个元素来区分...我不断得到至少一个对象必须实现 Icomparable。我不明白为什么我总是得到这个。我能够按该值进行分组...为什么我
假设我们有这 3 个类: Class BaseClass : System.IComparable { [int] $Value BaseClass([int] $v) {
所以我在这个错误上画了一个空白。无法比较数组中的两个元素。Array.Sort(患者);是产生错误的地方。我确实有一个 IComparable 接口(interface)和一个包含以下代码的类文件:T
我刚开始尝试使用 IEnumerable 接口(interface)。我总是只编写自定义哈希排序而不是尝试使用 native 语法,因为我对实现有些困惑。我正在尝试确定是否可以使用 BinarySea
我有一个 MyClass 类,我想像这样把它作为字典的键: Dictionary dict = new Dictionary(); 我想确保 MyClass 是唯一键,唯一性是通过查看 MyClass
在下面的代码中,我以 .NET 2.0 Framework 为目标。 我可以将 Programmer(派生)对象传递给需要 Person(基类)的 Compare 方法 但由于程序员是一个人(简单的
我正在尝试使用 IComparer 对对象数组进行排序。 我编写了代码,但它仅适用于特定对象。例如: 这门课 public class Cars { public string Name {
如何实现需要参数的 IComparer(可能不相关,但我在 Linq 查询中使用它)? 我想它应该这样称呼: ListOfObjectsToSort.orderBy(x => x, myCustomC
我是一名优秀的程序员,十分优秀!