.net 中有没有按添加顺序排序的不重复的集合? 类似 Java 中的 LinkedHashSet

2022-09-26 20:33:09 +08:00
 bthulu

只找到一个 SortedSet, 想要他按添加顺序排序, 必须给元素包装一下, 添加一个添加序号, 然后再指定一个按此序号排序的比较器, 比如像下面这样, 为了构造一个按添加顺序排序的 string 集合, 写了一堆代码, 实在是太麻烦了

    public void SortedSetSortByAddOrder()
    {
        SortedSet<(int, string)> set = new(new AddComparer())
        {
            (1, "first"),
            (2, "second"),
            (3, "third"),
            (4, "forth"),
            (5, "fifth"),
            (6, "sixth")
        };
    }
    
    public class AddComparer : IComparer<(int, string)>
    {
        public int Compare((int, string) x, (int, string) y)
        {
            return x.Item1.CompareTo(y.Item1);
        }
    }
2085 次点击
所在节点    .NET
15 条回复
sunmker
2022-09-26 20:58:15 +08:00
貌似没有
netnr
2022-09-26 21:20:06 +08:00
声明 两个对象,HashSet List
thinkershare
2022-09-26 21:33:50 +08:00
这样的集合效率必然低下,原生肯定是没有的, 可以自己实现一个, 不过效率嘛, 再怎么优化也不会太高。
geelaw
2022-09-26 21:42:07 +08:00
没有自带的。Microsoft 目前的 Dictionary 实现是用数组作为节点存储、下标作为指针的链表,数组里的顺序是遍历顺序,删除的时候把节点放入空闲链表,加入的时候优先使用空闲链表,其次使用数组之后的空位,最后考虑扩容。因此,加入 1 、2 、3 ,删除 2 ,加入 4 ,此后遍历顺序是 1 、4 、3 。当然,现在的实现不一定是未来的实现。

你可以仿照这个实现一下自己的 Dictionary ,删除的时候不要放入空闲链表,但要考虑碎片整理(例如有 1/2 空间是碎片的时候整理),加入的时候先考虑数组之后的空位,再考虑碎片整理,最后考虑扩容,以数组顺序作为遍历顺序。删除的时候碎片整理是为了提高均摊效率,当然坏处是删除操作会令所有迭代器无效(最新版本的 Dictionary 里,删除操作不会令迭代器无效)。
a33291
2022-09-26 21:59:21 +08:00
FungKao
2022-09-26 22:01:38 +08:00
huang119412
2022-09-27 09:06:35 +08:00
@thinkershare 这样的集合效率必然低下?你是怎么得出这个结论的?从名字看也是 HashSet ,O(1)的查找,效率低? LinkedHashSet 和 SortedSet 根本不是一个类型。SortedSet 和 Hash 比才是效率低下。
thinkershare
2022-09-27 09:15:02 +08:00
@huang119412 我没有义务告诉你为什么.
zhady009
2022-09-27 12:29:03 +08:00
@thinkershare enrty 加两个一前一后的属性 维护起来跟链表一样这也叫效率低下?
zhady009
2022-09-27 12:29:28 +08:00
@zhady009 entry 修正下
bthulu
2022-09-27 13:30:12 +08:00
@zhady009 可以写个测试对比下 java 的 LinkedHashMap 和.net 的 SortedSet 到底哪个快不就知道了
bthulu
2022-09-27 13:31:11 +08:00
@FungKao 这里面的 IntersectWith 方法实现是有问题的, 可以参考我下面这个
public void IntersectWith(IEnumerable<T> other)
{
HashSet<T> intersection = other.Where(Contains).ToHashSet();
T[] removed = this.Where(e => !intersection.Contains(e)).ToArray();
foreach (T item in removed)
{
Remove(item);
}
}
INCerry
2022-09-27 13:36:59 +08:00
zmal
2022-09-27 14:29:48 +08:00
3L 的这位,不懂还爱装 X 。'我没有义务告诉你为什么',很久没见过这么爱装 X 的人了。
zmal
2022-09-27 14:34:38 +08:00
.net 的 SortSet 用红黑树实现的,相当于 Java 里的 TreeMap 、TreeSet 。
LinkedHashSet 相比 HashSet 每个 entry 多维护了两个指针,开销不大。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/883117

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX