HashSet的基本概念

ashSet的基本概念

 

- HashSet 是C#中用于存储唯一元素的泛型集合类,它基于哈希表实现,具有快速查找、添加和删除元素的特性。

 

- 核心特点:

 

- 不允许存储重复元素

 

- 元素无序排列

 

- 查找、添加、删除操作的平均时间复杂度为O(1)

 

- 实现了 IEnumerable<T> 和 ICollection 接口

 

常用属性和方法

 

 

 

 

- 属性:

 

-  Count :获取HashSet中包含的元素数量

 

- 主要方法:

 

-  Add(T item) :向HashSet中添加元素,若元素已存在则添加失败

 

-  Contains(T item) :判断HashSet是否包含指定元素

 

-  Remove(T item) :从HashSet中移除指定元素

 

-  UnionWith(IEnumerable<T> other) :将两个集合的并集存储到当前集合

 

-  IntersectWith(IEnumerable<T> other) :将两个集合的交集存储到当前集合

 

-  SymmetricExceptWith(IEnumerable<T> other) :将两个集合的对称差集存储到当前集合

 

-  IsSubsetOf(IEnumerable<T> other) :判断当前集合是否为另一个集合的子集

 

在CAD二次开发中的应用场景

 

在AutoCAD二次开发中,HashSet常用于:

 

- 管理图形对象集合(避免重复添加相同对象)

 

- 快速查找和筛选特定类型的图元

 

- 处理图形对象的集合运算(如求交、求并)

 

- 记录已处理的对象,避免重复操作

 

具体应用实例与代码

 

下面是一个在AutoCAD二次开发中使用HashSet的完整示例,演示了如何使用HashSet管理图形对象、进行对象筛选和集合运算:

 

 

using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;

[assembly: CommandClass(typeof(HashSetInCAD.Commands))]

namespace HashSetInCAD
{
    public class Commands
    {
        // 示例命令:使用HashSet管理和操作CAD图形对象
        [CommandMethod("UseHashSetInCAD")]
        public void UseHashSetInCAD()
        {
            // 获取当前文档和数据库
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            try
            {
                // 在事务中处理数据库操作
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    // 获取模型空间
                    BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                    BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                    // 1. 创建HashSet存储圆对象
                    HashSet<ObjectId> circleIds = new HashSet<ObjectId>();
                    
                    // 2. 向模型空间添加多个圆,并将其ID存入HashSet
                    for (int i = 0; i < 5; i++)
                    {
                        // 创建圆
                        Circle circle = new Circle();
                        circle.Center = new Point3d(i * 2, 0, 0);
                        circle.Radius = 1.0;
                        
                        // 添加到模型空间
                        modelSpace.AppendEntity(circle);
                        tr.AddNewlyCreatedDBObject(circle, true);
                        
                        // 将圆的ID添加到HashSet
                        circleIds.Add(circle.ObjectId);
                        ed.WriteMessage($"\n已添加圆,ID: {circle.ObjectId}");
                    }
                    
                    // 3. 尝试添加重复的圆(验证HashSet去重特性)
                    Circle duplicateCircle = new Circle();
                    duplicateCircle.Center = new Point3d(2, 0, 0); // 与i=1时的圆位置相同
                    duplicateCircle.Radius = 1.0;
                    
                    modelSpace.AppendEntity(duplicateCircle);
                    tr.AddNewlyCreatedDBObject(duplicateCircle, true);
                    
                    // 尝试添加到HashSet(由于已有相同位置的圆,添加会失败)
                    bool added = circleIds.Add(duplicateCircle.ObjectId);
                    ed.WriteMessage($"\n添加重复圆结果: {(added ? "成功" : "失败,已存在重复元素")}");
                    
                    // 4. 使用HashSet进行对象筛选 - 查找半径大于1.5的圆(假设存在)
                    // 这里先创建一个半径大于1.5的圆用于演示
                    Circle largeCircle = new Circle();
                    largeCircle.Center = new Point3d(10, 0, 0);
                    largeCircle.Radius = 2.0;
                    
                    modelSpace.AppendEntity(largeCircle);
                    tr.AddNewlyCreatedDBObject(largeCircle, true);
                    
                    // 创建另一个HashSet存储大半径圆
                    HashSet<ObjectId> largeCircles = new HashSet<ObjectId>();
                    
                    // 遍历模型空间所有实体,筛选半径大于1.5的圆
                    foreach (ObjectId objId in modelSpace)
                    {
                        Entity entity = (Entity)tr.GetObject(objId, OpenMode.ForRead);
                        if (entity is Circle circleObj && circleObj.Radius > 1.5)
                        {
                            largeCircles.Add(objId);
                        }
                    }
                    
                    ed.WriteMessage($"\n找到{largeCircles.Count}个半径大于1.5的圆");
                    
                    // 5. 集合运算 - 求两个集合的交集
                    HashSet<ObjectId> intersection = new HashSet<ObjectId>(circleIds);
                    intersection.IntersectWith(largeCircles);
                    
                    ed.WriteMessage($"\n两个集合的交集有{intersection.Count}个元素");
                    
                    // 6. 使用HashSet优化对象遍历 - 快速判断对象是否已处理
                    HashSet<ObjectId> processedIds = new HashSet<ObjectId>();
                    
                    // 模拟处理对象的过程
                    foreach (ObjectId objId in modelSpace)
                    {
                        if (processedIds.Contains(objId))
                            continue; // 已处理过的对象跳过
                            
                        processedIds.Add(objId);
                        // 这里可以添加对象处理逻辑
                        ed.WriteMessage($"\n处理对象: {objId}, 类型: {tr.GetObject(objId, OpenMode.ForRead).GetType().Name}");
                    }
                    
                    tr.Commit();
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage($"\n错误: {ex.Message}");
            }
        }
        
        // 另一个示例:使用HashSet管理图层
        [CommandMethod("ManageLayersWithHashSet")]
        public void ManageLayersWithHashSet()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            try
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    // 获取图层表
                    LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForWrite);
                    
                    // 创建HashSet存储图层名
                    HashSet<string> layerNames = new HashSet<string>
                    {
                        "Layer1",
                        "Layer2",
                        "Layer3"
                    };
                    
                    // 创建图层(如果不存在)
                    foreach (string layerName in layerNames)
                    {
                        if (!lt.Has(layerName))
                        {
                            LayerTableRecord ltr = new LayerTableRecord();
                            ltr.Name = layerName;
                            lt.Add(ltr);
                            tr.AddNewlyCreatedDBObject(ltr, true);
                            ed.WriteMessage($"\n创建图层: {layerName}");
                        }
                    }
                    
                    // 检查是否存在未在HashSet中的图层
                    HashSet<string> existingLayers = new HashSet<string>();
                    foreach (DBDictionaryEntry entry in lt)
                    {
                        existingLayers.Add(entry.Key);
                    }
                    
                    // 找出不在目标集合中的图层
                    HashSet<string> extraLayers = new HashSet<string>(existingLayers);
                    extraLayers.ExceptWith(layerNames);
                    
                    if (extraLayers.Count > 0)
                    {
                        ed.WriteMessage($"\n发现{extraLayers.Count}个多余图层:");
                        foreach (string layer in extraLayers)
                        {
                            ed.WriteMessage($"\n- {layer}");
                            // 这里可以添加删除图层的逻辑
                        }
                    }
                    
                    tr.Commit();
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage($"\n错误: {ex.Message}");
            }
        }
    }
}
代码解析与关键应用点
 
1. 对象唯一性管理:
 
- 通过 HashSet<ObjectId> 存储图形对象ID,自动避免重复添加相同对象
 
- 示例中尝试添加重复圆时,HashSet的 Add 方法返回false,体现了去重特性
 
2. 高效对象筛选:
 
- 遍历模型空间时,利用HashSet的快速查找特性( Contains 方法)判断对象是否已处理
 
- 通过条件筛选(如半径大于1.5的圆),将符合条件的对象存入新的HashSet
 
3. 集合运算应用:
 
- 使用 IntersectWith 方法计算两个对象集合的交集
 
- 还可扩展使用并集( UnionWith )、差集( ExceptWith )等运算
 
4. 图层管理场景:
 
- 第二个示例展示了如何使用HashSet管理图层,确保文档中只存在指定图层
 
- 通过集合运算找出多余图层,为批量处理图层提供了高效方案
 
在CAD开发中使用HashSet的优势
 
1. 性能优势:
 
- 相比List等集合,HashSet的查找、添加、删除操作效率更高,尤其适合处理大量图形对象
 
2. 逻辑简化:
 
- 自动去重特性简化了对象管理逻辑,避免了手动判断重复的繁琐代码
 
3. 集合运算便捷:
 
- 内置的集合运算方法(交、并、差)使复杂的对象筛选和管理变得简单
 
4. 内存优化:
 
- 相比存储完整对象,HashSet存储对象ID更节省内存,适合处理大型CAD文档
 
使用上述代码时,需确保已正确引用AutoCAD相关程序集,并将代码编译为DLL后加载到AutoCAD中使用。根据实际项目需求,还可以进一步扩展HashSet的应用场景,如在块参照管理、图形比较等功能中发挥作用。

 

收集唯一图层名

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using System.Collections.Generic;

public class LayerCollector
{
    public static void CollectUniqueLayers()
    {
        Document doc = Application.DocumentManager.MdiActiveDocument;
        Database db = doc.Database;
        Editor ed = doc.Editor;

        using (Transaction tr = db.TransactionManager.StartTransaction())
        {
            // 创建HashSet存储唯一图层名
            HashSet<string> uniqueLayers = new HashSet<string>();

            // 获取模型空间块表记录
            BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
            BlockTableRecord modelSpace = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;

            // 遍历所有实体
            foreach (ObjectId entityId in modelSpace)
            {
                Entity entity = tr.GetObject(entityId, OpenMode.ForRead) as Entity;
                if (entity != null)
                {
                    // 自动过滤重复图层名
                    uniqueLayers.Add(entity.Layer);
                }
            }

            // 输出结果
            ed.WriteMessage("\n唯一图层数量: {0}", uniqueLayers.Count);
            foreach (string layer in uniqueLayers)
            {
                ed.WriteMessage("\n图层: {0}", layer);
            }

            tr.Commit();
        }
    }
}

 

检测重复块引用

 

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using System.Collections.Generic;

public class BlockDuplicateChecker
{
    public static void CheckDuplicateBlockReferences()
    {
        Document doc = Application.DocumentManager.MdiActiveDocument;
        Database db = doc.Database;

        using (Transaction tr = db.TransactionManager.StartTransaction())
        {
            // 存储块引用位置和块名
            HashSet<string> blockSignatures = new HashSet<string>();

            BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
            BlockTableRecord modelSpace = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;

            foreach (ObjectId id in modelSpace)
            {
                if (id.ObjectClass == General.Class(typeof(BlockReference)))
                {
                    BlockReference br = tr.GetObject(id, OpenMode.ForRead) as BlockReference;
                    string signature = $"{br.Name}_{br.Position.ToString()}"; // 唯一签名

                    // 检测重复
                    if (!blockSignatures.Add(signature))
                    {
                        // 发现重复块引用
                        br.Highlight(); // 高亮显示重复项
                    }
                }
            }

            tr.Commit();
        }
    }
}

 

快速过滤选择集

 

using Autodesk.AutoCAD.EditorInput;
using System.Collections.Generic;

public class FastSelectionFilter
{
    public static void SelectUniqueEntities()
    {
        Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

        // 用户选择对象
        PromptSelectionResult selRes = ed.GetSelection();
        if (selRes.Status != PromptStatus.OK) return;

        // 使用HashSet去重
        HashSet<SelectedObject> uniqueSelection = new HashSet<SelectedObject>();

        foreach (SelectedObject selObj in selRes.Value)
        {
            // 自定义去重逻辑:按句柄去重
            if (selObj != null)
            {
                string handle = selObj.ObjectId.Handle.ToString();
                if (!uniqueSelection.Contains(selObj))
                {
                    uniqueSelection.Add(selObj);
                }
            }
        }

        // 创建新选择集
        ObjectId[] ids = new ObjectId[uniqueSelection.Count];
        int i = 0;
        foreach (SelectedObject selObj in uniqueSelection)
        {
            ids[i++] = selObj.ObjectId;
        }

        // 应用过滤后的选择集
        ed.SetImpliedSelection(ids);
    }
}

 

# **五、与传统集合对比**
| 操作          | HashSet      | List        | Dictionary       |
|---------------|--------------|-------------|------------------|
| 添加元素      | O(1)         | O(1)        | O(1)            |
| 查找元素      | O(1)         | O(n)        | O(1)            |
| 删除元素      | O(1)         | O(n)        | O(1)            |
| 内存占用      | 中等         | 低          | 高              |
| 有序性        | 否           | 是          | 否              |

---

通过合理应用`HashSet`,可以在CAD二次开发中显著提升处理大量实体数据的效率,特别是在需要频繁进行存在性检查或去重操作的场景中表现优异。建议结合具体业务需求选择合适的数据结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/907126.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信号与系统10-综合案例:智能信号处理系统

第7课&#xff1a;综合案例——智能信号处理系统 1. 案例1&#xff1a;基于傅里叶变换与AI的语音信号分类系统 1.1 理论基础 傅里叶变换是信号处理的核心工具之一&#xff0c;能够将时域信号转换为频域表示&#xff08;如频谱图&#xff09;。语音信号的频域特征&#xff08…

详解Kubernetes Scheduler 的调度策略

详解Kubernetes Scheduler 的调度策略 在 Kubernetes(K8s)中,Scheduler(调度器) 负责 决定 Pod 应该运行在哪个 Node(节点)。 👉 调度器的目标是什么? ✅ 最大化资源利用率(让 CPU、内存等资源不浪费) ✅ 保证 Pod 运行在合适的 Node 上(避免超载、满足亲和性)…

在 ElementUI 中实现 Table 单元格合并

在 ElementUI 中实现 Table 单元格合并 在使用 ElementUI 的 Table 组件时&#xff0c;有时我们需要合并相邻的单元格&#xff0c;以提高表格的可读性和简洁性。下面是一个关于如何在 Table 中根据特定字段合并单元格的实现方法。 逻辑分析 spanMethod 方法&#xff1a;这是 …

小土堆pytorch--现有网络模型的使用及修改

现有网络模型的使用及修改 一级目录二级目录三级目录 现有网络模型的使用及修改1.VGG16模型VGG16网络模型简介**核心特点****网络结构细节****优缺点与应用****变种与后续发展** 2. 使用vgg16模型 一级目录 二级目录 三级目录 现有网络模型的使用及修改 1.VGG16模型 VGG16…

Oracle 正则表达式匹配(Oracle 11g)

1、连续2词汉字重复或3词汉字重复&#xff08;不会忽略符号&#xff09; ([^ \u4e00-\u9fa5\S]{2,3})\1 例如&#xff1a;阿富、 SELECT REGEXP_replace(阿富、阿富、 阿富汗、 , ([^ \u4e00-\u9fa5\S]{2,3})\1, 重复) FROM dual结果&#xff1a; 2、连续2词汉字重复或3词…

对话魔数智擎CEO柴磊:昇腾AI赋能,大小模型融合开启金融风控新范式

导读&#xff1a;#昇腾逐梦人# AI已经成为金融机构核心竞争力的关键要素。专注AI金融赛道的魔数智擎&#xff0c;通过大小模型融合&#xff0c;让AI成为银行的“金融风控专家”。 作者 | 小葳 图片来源 | 摄图 在AI涌向产业的时代赛跑中&#xff0c;开发者是绝对的主角。 昇腾…

IDEA使用Git进行commit提交到本地git空间后撤回到commit版本之前

一、前言 Git作为最流行和最全面的版本控制工具&#xff0c;非常好用&#xff0c;但是操作也会比SVN复杂一些。毕竟有得有失嘛&#xff0c;所以我选择Git&#xff0c;最近在工作中&#xff0c;一不小心吧一些无关紧要的文件commit了。还好在Push之前看到&#xff0c;不过就算P…

GitHub 趋势日报 (2025年05月26日)

本日报由 TrendForge 系统生成 https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日整体趋势 Top 10 排名项目名称项目描述今日获星总星数语言1Fosowl/agenticSeek完全本地的马努斯AI。没有API&#xff0c;没有200美元的每…

Matlab实现LSTM-SVM时间序列预测,作者:机器学习之心

Matlab实现LSTM-SVM时间序列预测&#xff0c;作者&#xff1a;机器学习之心 目录 Matlab实现LSTM-SVM时间序列预测&#xff0c;作者&#xff1a;机器学习之心效果一览基本介绍程序设计参考资料 效果一览 基本介绍 该代码实现了一个结合LSTM和SVM的混合模型&#xff0c;用于时间…

深入解析Spring Boot与Redis集成:高效缓存与性能优化实践

深入解析Spring Boot与Redis集成&#xff1a;高效缓存与性能优化实践 引言 在现代Web应用开发中&#xff0c;缓存技术是提升系统性能的重要手段之一。Redis作为一款高性能的内存数据库&#xff0c;广泛应用于缓存、消息队列等场景。本文将深入探讨如何在Spring Boot项目中集成…

Jmeter一些元件使用的详细记录

1、csv数据文件处理 文件放在bin目录下&#xff0c;属于相对路径读取文件&#xff0c;如果使用绝对路径则需要改为l添加盘符的路径&#xff0c;如&#xff1a;D:/apach/jmeter/bin 说明&#xff1a; 当选择False时&#xff0c;如果请求的次数 大于 文件中的有效数据行数&…

使用 Cursor 从 0 到 1 开发一个全栈 chatbox 项目

大家好&#xff0c;我是 luckySnail&#xff0c;你肯定用过 AI 聊天工具。例如&#xff1a; Gemini&#xff0c;ChatGPT&#xff0c;claude AI 等产品&#xff0c;我们通过它们的 web 网站或者手机应用提出问题&#xff0c;得到答案。在之前如果你想要构建一个这样的 AI 聊天应…

嵌入式学习的第二十六天-系统编程-文件IO+目录

一、文件IO相关函数 1.read/write cp #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <stdio.h> #include<unistd.h> #include<string.h>int main(int argc, char **argv) {if(argc<3){fprintf(stderr, …

SCADA|KingSCADA信创4.0-Win10安装过程

哈喽,你好啊,我是雷工! 现如今很多地方开始要求信创版, 最近就遇到一个现场要求用信创。 首先找官方要了最新的信创版安装包。 由于有之前安装组态王授权驱动装蓝屏的经历,此次特意问了下该标识win10的软件是否可以在win11系统上安装。 技术反馈win11专业版上可以安装…

AI时代新词-人工智能伦理审查(AI Ethics Review)

一、什么是人工智能伦理审查&#xff08;AI Ethics Review&#xff09;&#xff1f; 人工智能伦理审查&#xff08;AI Ethics Review&#xff09;是指在人工智能&#xff08;AI&#xff09;系统的开发、部署和使用过程中&#xff0c;对其可能涉及的伦理、法律和社会问题进行系…

GitLab 从 17.10 到 18.0.1 的升级指南

本文分享从 GitLab 中文本 17.10.0 升级到 18.0.1 的完整过程。 升级前提 查看当前安装实例的版本。有多种方式可以查看&#xff1a; 方式一&#xff1a; /help页面 可以直接在 /help页面查看当前实例的版本。以极狐GitLab SaaS 为例&#xff0c;在浏览器中输入 https://ji…

python:基础爬虫、搭建简易网站

一、基础爬虫代码&#xff1a; # 导包 import requests # 从指定网址爬取数据 response requests.get("http://192.168.34.57:8080") print(response) # 获取数据 print(response.text)二、使用FastAPI快速搭建网站&#xff1a; # TODO FastAPI 是一个现代化、快速…

从0开始学习R语言--Day10--时间序列分析数据

在数据分析中&#xff0c;我们经常会看到带有时间属性的数据&#xff0c;比如股价波动&#xff0c;各种商品销售数据&#xff0c;网站的网络用户活跃度等。一般来说&#xff0c;根据需求我们会分为两种&#xff0c;分析历史数据的特点和预测未来时间段的数据。 移动平均 移动平…

倚光科技在二元衍射面加工技术上的革新:引领光学元件制造新方向​

倚光科技二元衍射面加工技术&#xff08;呈现出细腻的光碟反射纹路&#xff09; 在光学元件制造领域&#xff0c;二元衍射面的加工技术一直是行业发展的关键驱动力之一。其精准的光相位调制能力&#xff0c;在诸多前沿光学应用中扮演着不可或缺的角色。然而&#xff0c;长期以来…

【redis原理篇】底层数据结构

SDS Redis是基于C语言实现的&#xff0c;但是Redis中大量使用的字符串并没有直接使用C语言字符串。 一、SDS 的设计动机 传统 C 字符串以 \0 结尾&#xff0c;存在以下问题&#xff1a; 性能瓶颈&#xff1a;获取长度需遍历字符数组&#xff0c;时间复杂度 O(n)。缓冲区溢出…