iOS-相关集合类
第一:NSArrary
1.1:集合的基本方法
1.创建集合
NSArray 是不可变数组,一旦创建完成就不能够对数组进行,添加,删除等操作
1 | NSArray * array = [[ NSArray alloc] init]; |
2.通过构造方法的方式创建一个NSArray
1 2 3 4 5 6 7 8 9 10 11 12 | //在创建一个NSArray的时候,集合的最后一个元素一定是nil,判断nil决定集合的结尾 NSArray * array1 = [ NSArray arrayWithObjects:@ "one" ,@ "two" ,@ "three" , nil ]; NSArray * array2 = [[ NSArray alloc] initWithObjects:@ "one" ,@ "two" ,number, nil ]; NSArray * karray = @[@ "a" ,@ "b" ,@ "c" ]; NSString * kstr = karray[0]; //访问元素位置 //数组的index时从0开始的 NSString * str = [array objectAtIndex:0]; NSLog (@ "str %@" ,str); //获得数组的元素个数 NSUInteger arrayCount = [array count]; // 判断数组中是否存在某个对象 BOOL isContain = [array containsObject: id ]; |
特性:
1.数组中可以存储不同类型的对象
2.数组实际上存储的时对象的地址,同样也可以存储数组的地址
3.存储自定义的对象 (最好都给我重写 description方法)
4.数组中存储基本数据类型, (如果你要在数组中存储基本数据类型,请包装好了之后再去存 NSNumber)
5.注意不要把nil值存储到NSArray中,会导致数据丢失
1.2:数组排序:
1.使用sortedArrayUsingSelector
1 2 | NSArray * array = @[@ "b" ,@ "d" ,@ "a" ,@ "z" ]; array = [array sortedArrayUsingSelector: @selector (compare:)]; //系统自带 |
2.使用block方式排序
a. 降序
NSArray *tMlist = @[@4,@5,@2,@6,@3,@7,@8];
//降序序8,7,。。
NSArray *tArray = [tMlist sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
NSNumber *tNumber1 = (NSNumber *)obj1;
NSNumber *tNumber2 = (NSNumber *)obj2;
//因为不满足sortedArrayUsingComparator方法的默认排序顺序,则需要交换
if ([tNumber1 integerValue] < [tNumber2 integerValue])
return NSOrderedDescending;
return NSOrderedAscending;
//因为满足sortedArrayUsingComparator方法的默认排序顺序,则不需要交换
if ([tNumber1 integerValue] > [tNumber2 integerValue])
return NSOrderedAscending;
return NSOrderedDescending;
1 | b 升序 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | NSArray *tMlist = @[ @4 , @5 , @2 , @6 , @3 , @7 , @8 ]; //结果:升序2,4,。。 NSArray *tArray = [tMlist sortedArrayUsingComparator:^ NSComparisonResult ( id obj1, id obj2) { NSNumber *tNumber1 = ( NSNumber *)obj1; NSNumber *tNumber2 = ( NSNumber *)obj2; //因为满足sortedArrayUsingComparator方法的默认排序顺序,则不需要交换 if ([tNumber1 integerValue] < [tNumber2 integerValue]) return NSOrderedAscending ; return NSOrderedDescending ; // 因为不满足sortedArrayUsingComparator方法的默认排序顺序,则需要交换。 // if ([tNumber1 integerValue] < [tNumber2 integerValue]) // return NSOrderedAscending ; // return NSOrderedDescending; }]; |
1 | c 数组逆转 |
1 2 3 4 5 6 7 8 9 | NSArray *tMlist = @[ @4 , @5 , @2 , @6 , @3 , @7 , @8 ]; NSArray *tArray = [tMlist sortedArrayUsingComparator:^ NSComparisonResult ( id obj1, id obj2) { NSNumber *tNumber1 = ( NSNumber *)obj1; NSNumber *tNumber2 = ( NSNumber *)obj2; //数组逆转 return NSOrderedDescending ; }]; |
1 | d.数组不变 |
1 2 3 4 5 6 7 8 | NSArray *tMlist = @[ @4 , @5 , @2 , @6 , @3 , @7 , @8 ]; NSArray *tArray = [tMlist sortedArrayUsingComparator:^ NSComparisonResult ( id obj1, id obj2) { NSNumber *tNumber1 = ( NSNumber *)obj1; NSNumber *tNumber2 = ( NSNumber *)obj2; //数组不变 return NSOrderedAscending ; }]; |
总结:
1.sortedArrayUsingComparator这个方法本身就是按递增的方式排序。
2.返回的返回值(NSOrderedAscending 不交换,NSOrderedSame 不交换,NSOrderedDescending 交换)。
例如:object1 < object2 返回:NSOrderedDescending 则交换(变为object2,object1),以保证安方法本身升序。返回NSOrderedAscending,两者不交换。
对于Comparator的返回值文档有下面的说明
NSOrderedAscending
The left operand is smaller than the right operand.
NSOrderedSame
The two operands are equal.
NSOrderedDescending
The left operand is greater than the right operand
如果你期望的是值小的在前而值大的在后(升序),则可以在比较的时候返回NSOrderedAscending(-1),否则,就是NSOrderedDescending(1)。
3.使用自定义对象排序 :如果你向给你自己定义的对象排序,必须根据某一个属性来排序,
1 2 3 4 5 6 7 8 | //sortDescriptorWithKey 参数要的就是你对象中,要依据哪个属性来排序,你就把哪个属性的名字当成key传入 //ascending YES表示正序 NO表示倒叙 NSSortDescriptor * d1 = [ NSSortDescriptor sortDescriptorWithKey:@ "age" ascending: NO ]; NSSortDescriptor * d2 = [ NSSortDescriptor sortDescriptorWithKey:@ "year" ascending: NO ]; //如果你要使用多个属性进行排序,默认在前面的NSSortDescriptor优先级比较高 NSArray * descripts = @[d2,d1]; array3 = [array3 sortedArrayUsingDescriptors:descripts]; |
1.3:遍历数组
遍历数组的三种方式
1>普通方式:
1 2 3 4 | for ( int i = 0; i<array1.count; i++){ if (i ==0) break ; } |
2>将array1数组中的每个对象拿出来赋给obj然后依次打印
1 2 3 4 5 6 | for ( id obj in array1){ // id obj 代表数组中的对象 // 获取obj对象在数组中的索引 NSUInteger index = [array1 indexOfObject:obj]; NSLog (@ "%ld--%@" ,index,obj); } |
3>使用Block 每次从数组中遍历一个元素后就传递给block,block也相应的执行一次
1 2 3 4 5 6 7 8 | // block中的id obj对应数组中的元素,NSUInteger idx对应数组中元素的索引 BOOL用来停止遍历 [array1 enumerateObjectsUsingBlock:^( id obj, NSUInteger idx, BOOL *stop){ NSLog (@ "%ld--%@" ,idx,obj); // 如果索引为0 立即停止遍历 if (idx ==0){ * stop = YES ; } }; |
1.4:可变数组:
1.创建可变数组
1 | NSMutableArray * array = [[ NSMutableArray alloc] initWithCapacity:0]; |
2.数组中加入元素
1 | [array addObject:str1]; |
3.指定对象插入的位置
1 | [array insertObject:str1 atIndex:2]; |
4.删除 会通过对象,删除数组中所有的同一个地址的对象
1 | [array removeObject:str1]; |
4.通过索引的方式删除对象,超出了数组的count值,那么就会导致异常 index beyond bounds
1 2 3 4 | [array removeObjectAtIndex:0]; [array addObject:str2]; [array addObject:str3]; [array addObject:str1]; |
5.删除数组中所有的元素
1 | [array removeAllObjects]; |
第二:NSDictionary
第一:NSDictionary
字典是以键值对的形式来存储数据 key value
字典的顺序不是按照存储时候的顺序。
字典中可以存任意数据类型
1.创建字典
1 | NSDictionary *dic1 = [ NSDictionary dictionaryWithObject:@ "value" forKey:@ "key" ]; |
2.创建多个元素字典
1 2 3 4 5 6 | NSDictionary *dic2 = [ NSDictionary dictionaryWithObjectsAndKeys: @ "value1" , @ "key1" , @ "value2" , @ "key2" , @ "value3" , @ "key3" , @ "value4" , @ "key4" , nil ]; |
3.根据现有的字典创建字典
1 | NSDictionary *dic3 = [ NSDictionary dictionaryWithDictionary:dic2]; |
4.根据key获取value
1 | [dic3 objectForKey:@ "key3" ]); |
5.获取字典数量
1 | NSLog (@ "dic count :%d" , dic3.count); |
6.所有的键集合
1 | NSArray *keys = [dic3 allKeys]; |
7.所有值集合
1 | NSArray *values = [dic3 allValues]; |
1.2 可变字典
1.创建可变字典
1 2 3 | NSMutableDictionary *mutableDic = [[ NSMutableDictionary alloc] initWithObjectsAndKeys: @ "mvalue1" , @ "mkey1" , @ "mvalue2" , @ "mkey2" , nil ]; |
2.添加现有的字典数据
1 | [mutableDic addEntriesFromDictionary:dic3]; |
3.添加新的键值对象
1 | [mutableDic setValue:@ "set1" forKey:@ "setKey1" ]; |
4.以新的字典数据覆盖旧的字典数据
1 | [mutableDic setDictionary:dic2]; |
5.根据key删除value
1 | [mutableDic removeObjectForKey:@ "key1" ]; |
1.3 遍历方法
1.快速遍历
1 2 3 | for ( id key in mutableDic) { NSLog (@ "key :%@ value :%@" , key, [mutableDic objectForKey:key]); } |
2.枚举遍历
1 2 3 4 5 6 | NSEnumerator *enumerator = [mutableDic keyEnumerator]; id key = [enumerator nextObject]; while (key) { NSLog (@ "enumerator :%@" , [mutableDic objectForKey:key]); key = [enumerator nextObject]; } |
3.根据key数组删除元素
1 | [mutableDic removeObjectsForKeys:keys]; |
4.删除所有元素
1 | [mutableDic removeAllObjects]; |
第三:NSSet 集合
1> NSSet是一组单值对象的不可变集合,集合中元素没有顺序;
2> 操作包括:搜索、添加、删除集合中的元素(仅用于可变集合)、比较两个集合,计算两个集合的交集和并集等。
3> 获取元素个数:集合名.count
1.1、NSSet集合常用方法(部分)
1.构造方法
1 | + (instancetype)setWithObjects:obj1, obj2, ..., nil ; |
2.使用一系列对象初始化新分配的集合:
1 | - (instancetype)initWithObjects:( const id [])objects count:( NSUInteger )cnt; |
3.确定集合是否包含anObject对象:
1 | - ( BOOL )containsObject:( id )anObject; |
4.使用member:访问集合中的某一对象,有就返回此元素,没有就返回null:
1 | - ( id )member:( id )object; |
5.为集合中的所有对象返回一个NSEnumerato对象:
1 | - ( NSEnumerator *)objectEnumerator; |
6.确定receiver的每个元素是否都出现在otherSet中:
1 | - ( BOOL )isSubsetOfSet:( NSSet *)otherSet; |
7.确定是否receiver中至少一个元素出现在对象otherSet中:
1 | - ( BOOL )intersectsSet:( NSSet *)otherSet; |
8.确定两个集合是否相等:
1 | - ( BOOL )isEqualToSet:( NSSet *)otherSet; |
1.2,NSMutableSet
NSMutableSet是NSSet的子类,是可变集合;
常用方法(部分):
1.创建新集合,使其具有存储numItems个元素的初始空间:
1 | + (instancetype)setWithCapacity:( NSUInteger )numItems; |
2.将新分配的集合设置为numItems个元素的存储空间:
1 | - (instancetype)initWithCapacity:( NSUInteger )numItems; |
3.将对象object添加到集合中:
1 | - ( void )addObject:( id )object; |
4.从集合中删除对象:
1 | - ( void )removeObject:( id )object; |
5.删除集合中所有对象:
1 | - ( void )removeAllObjects; |
6.将对象otherSet的所有元素添加到接收者:
1 | - ( void )unionSet:( NSSet *)otherSet; |
7.从接收者中删除otherSet的左右元素:
1 | - ( void )minusSet:( NSSet *)otherSet; |
8.从接受者中的所有不属于otherSet的元素删除:
1 | - ( void )intersectSet:( NSSet *)otherSet; |
第四:集合的相互转换
//1.NSArray 转换成 NSMutableArray
1 2 3 | NSArray * array = @[@ "one" ,@ "two" ,@ "three" ]; NSMutableArray * muArray = [ NSMutableArray arrayWithArray:array]; NSLog (@ "muarray %@" ,muArray); |
//2.NSDictonary 转换成 NSMutableDictionary
1 2 3 | NSDictionary * dic = @{@ "one" :@ "1" ,@ "two" :@ "2" }; NSMutableDictionary * muDic = [ NSMutableDictionary dictionaryWithDictionary:dic]; NSLog (@ "mudic %@ " ,muDic); |
//3.NSset 转换成 NSMutableSet
1 2 3 | NSSet * set = [[ NSSet alloc] initWithObjects:@ "one" ,@ "two" , nil ]; NSMutableSet *muSet = [ NSMutableSet setWithSet:set]; NSLog (@ "muSet %@" ,muSet); |
//4.NSArray 转换成NSSet
1 2 | NSMutableSet * muSet2 = [ NSMutableSet setWithArray:array]; NSLog (@ "muSet2 %@" ,muSet2); |
//5.NSDictionary 转化成NSArray
1 2 3 4 | NSArray * allkeys = [dic allKeys]; NSLog (@ "allkeys %@" ,allkeys); NSArray * allValues = [dic allValues]; NSLog (@ "allValues %@" ,allValues); |
//6.字符串转换成数组
1 | NSString * str = @ "www.itacast.cn" ; <br> NSArray * strArray =[str componentsSeparatedByString:@ "." ];<br> NSLog (@ "strArray %@" ,strArray); |
第五:NSPointerArray
NSArray的弱引用版本,也可以存储非oc对象,对应着 NSArray,添加元素操作很慢。
1.1,与NSArray的异同
* 相同点:
1.用于有序的插入或移除;
2.遵循 NSFastEnumeration ,可以通过 for...in 来进行遍历。
* 不同点:
1. 可以存储 NULL,并且 NULL 还参与 count 的计算;
2. count 可以 set,如果直接 set count,那么会使用 NULL 占位;
3.可以存储 weak 来修饰成员;
4.成员可以是所有指针类型;
1.2,初始化
NSPointerArray 与 NSMutableArray 很像,都是可变有序集合。最大的不同就是它们的初始化方法,
NSPointerArray
1.初始化方法:
1 2 | - (instancetype)initWithOptions:( NSPointerFunctionsOptions )options; - (instancetype)initWithPointerFunctions:( NSPointerFunctions *)functions; |
2.类方法:
1 2 | + ( NSPointerArray *)pointerArrayWithOptions:( NSPointerFunctionsOptions )options; + ( NSPointerArray *)pointerArrayWithPointerFunctions:( NSPointerFunctions *)functions; |
枚举:NSPointerFunctionsOptions
主要分为三大类:
* 内存管理
NSPointerFunctionsStrongMemory :缺省值,在 CG 和 MRC 下强引用成员
NSPointerFunctionsZeroingWeakMemory :已废弃,在 GC 下,弱引用指针,防止悬挂指针
NSPointerFunctionsMallocMemory 与 NSPointerFunctionsMachVirtualMemory : 用于 Mach 的虚拟内存管理
NSPointerFunctionsWeakMemory :在 CG 或者 ARC 下,弱引用成员
* 特性,用于标明对象判等方式
NSPointerFunctionsObjectPersonality : hash 、 isEqual 、对象描述
NSPointerFunctionsOpaquePersonality :pointer 的 hash 、直接判等
NSPointerFunctionsObjectPointerPersonality :pointer 的 hash 、直接判等、对象描述
NSPointerFunctionsCStringPersonality :string 的 hash 、 strcmp 函数、UTF-8 编码方式的描述
NSPointerFunctionsStructPersonality :内存 hash 、 memcmp 函数
NSPointerFunctionsIntegerPersonality :值的 hash
* 内存标识
NSPointerFunctionsCopyIn :根据第二类的选择,来具体处理。
如果是 NSPointerFunctionsObjectPersonality ,则根据 NSCopying 来拷贝。
所以在使用时,可以多个组合,
比如:需要强引用成员、使用对象方式对比、并且 add 时 copy 对象:
NSPointerFunctionsOptions *options = NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality | NSPointerFunctionsCopyIn;
NSPointerFunctions
3.添加pointer(NULL也能添加)
1 | - ( void )addPointer:(nullable void *)pointer; // add pointer at index 'count' |
4.通过索引的方式删除pointer
1 | - ( void )removePointerAtIndex:( NSUInteger )index; // everything above index, including holes, slide lower |
5.通过索引的方式添加Pointer
1 | - ( void )insertPointer:(nullable void *)item atIndex:( NSUInteger )index; // everything at & above index, including holes, slide higher |
6.通过索引的方式替换对应Pointer
1 | - ( void )replacePointerAtIndex:( NSUInteger )index withPointer:(nullable void *)item; // NULL item is okay; index must be < count |
7.剔除集合中为 NULL 的成员
1 | - ( void )compact; // eliminate NULLs |
注意:
当我们主动给 NSPointerArray 添加 NULL 时,数组会标记有空元素插入,此时 compact 函数才会生效,也就是说, compact 函数会先判断是否有标记,之后才会剔除。
第六:NSMapTable
对应NSDictionary的弱引用版本,添加元素和存取操作都比NSMutableDictionary慢点。
除了 集合的共有特点以外,比起传统字典,它还有一些优势:
key 可以不用遵循 NSCopying 协议;
key 和 value 的内存管理方式可以分开,如:key 是强引用,value 是弱引用;
相比起 NSPointerArray , NSMapTable 的初始化方法要多得多:
1.实例方法,虽然有 capacity 参数,但实际没用到
1 2 | - (instancetype)initWithKeyOptions:( NSPointerFunctionsOptions )keyOptions valueOptions:( NSPointerFunctionsOptions )valueOptions capacity:( NSUInteger )initialCapacity; - (instancetype)initWithKeyPointerFunctions:( NSPointerFunctions *)keyFunctions valuePointerFunctions:( NSPointerFunctions *)valueFunctions capacity:( NSUInteger )initialCapacity; |
2.便利构造器
1 | + ( NSMapTable <KeyType, ObjectType> *)mapTableWithKeyOptions:( NSPointerFunctionsOptions )keyOptions valueOptions:( NSPointerFunctionsOptions )valueOptions; |
3.返回指定 key、value 内存管理类型的 map
1 2 3 4 | + ( NSMapTable <KeyType, ObjectType> *)strongToStrongObjectsMapTable NS_AVAILABLE (10_8, 6_0); + ( NSMapTable <KeyType, ObjectType> *)weakToStrongObjectsMapTable NS_AVAILABLE (10_8, 6_0); + ( NSMapTable <KeyType, ObjectType> *)strongToWeakObjectsMapTable NS_AVAILABLE (10_8, 6_0); + ( NSMapTable <KeyType, ObjectType> *)weakToWeakObjectsMapTable NS_AVAILABLE (10_8, 6_0); |
其实,这么多的初始化方法就对应着四种搭配:
key 为 strong,value 为 strong
key 为 strong,value 为 weak
key 为 weak,value 为 strong
key 为 weak,value 为 weak
当用 weak 修饰 key 或 value 时,有一方被释放,则该键值对移除。
4. NSMapTable可以使用的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | FOUNDATION_EXPORT void NSFreeMapTable ( NSMapTable *table); FOUNDATION_EXPORT void NSResetMapTable ( NSMapTable *table); FOUNDATION_EXPORT BOOL NSCompareMapTables ( NSMapTable *table1, NSMapTable *table2); FOUNDATION_EXPORT NSMapTable * NSCopyMapTableWithZone ( NSMapTable *table, NSZone *zone); FOUNDATION_EXPORT BOOL NSMapMember ( NSMapTable *table, const void *key, void **originalKey, void **value); FOUNDATION_EXPORT void * NSMapGet ( NSMapTable *table, const void *key); FOUNDATION_EXPORT void NSMapInsert ( NSMapTable *table, const void *key, const void *value); FOUNDATION_EXPORT void NSMapInsertKnownAbsent ( NSMapTable *table, const void *key, const void *value); FOUNDATION_EXPORT void * NSMapInsertIfAbsent ( NSMapTable *table, const void *key, const void *value); FOUNDATION_EXPORT void NSMapRemove ( NSMapTable *table, const void *key); FOUNDATION_EXPORT NSMapEnumerator NSEnumerateMapTable ( NSMapTable *table); FOUNDATION_EXPORT BOOL NSNextMapEnumeratorPair ( NSMapEnumerator *enumerator, void **key, void **value); FOUNDATION_EXPORT void NSEndMapTableEnumeration ( NSMapEnumerator *enumerator); FOUNDATION_EXPORT NSUInteger NSCountMapTable ( NSMapTable *table); FOUNDATION_EXPORT NSString * NSStringFromMapTable ( NSMapTable *table); FOUNDATION_EXPORT NSArray * NSAllMapTableKeys ( NSMapTable *table); FOUNDATION_EXPORT NSArray * NSAllMapTableValues ( NSMapTable *table); |
第七:NSHashTable
可以包含弱引用对象的set集合,通常使用weakObjectsHashTable构造函数 ,它的 API 更为简单,与 NSMapTable 同样,初始化方法的 capacity 并未生效。
1 2 | - (instancetype)initWithOptions:( NSPointerFunctionsOptions )options capacity:( NSUInteger )initialCapacity; - (instancetype)initWithPointerFunctions:( NSPointerFunctions *)functions capacity:( NSUInteger )initialCapacity; |
值得注意的是, NSHashTable 有一个 allObjectes 的属性,返回 NSArray ,即使 NSHashTable 是弱引用成员, allObjects 依然会对成员进行强引用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | typedef struct { NSUInteger _pi; NSUInteger _si; void *_bs;} NSHashEnumerator ; FOUNDATION_EXPORT void NSFreeHashTable ( NSHashTable *table); FOUNDATION_EXPORT void NSResetHashTable ( NSHashTable *table); FOUNDATION_EXPORT BOOL NSCompareHashTables ( NSHashTable *table1, NSHashTable *table2); FOUNDATION_EXPORT NSHashTable * NSCopyHashTableWithZone ( NSHashTable *table, NSZone *zone); FOUNDATION_EXPORT void * NSHashGet ( NSHashTable *table, const void *pointer); FOUNDATION_EXPORT void NSHashInsert ( NSHashTable *table, const void *pointer); FOUNDATION_EXPORT void NSHashInsertKnownAbsent ( NSHashTable *table, const void *pointer); FOUNDATION_EXPORT void * NSHashInsertIfAbsent ( NSHashTable *table, const void *pointer); FOUNDATION_EXPORT void NSHashRemove ( NSHashTable *table, const void *pointer); FOUNDATION_EXPORT NSHashEnumerator NSEnumerateHashTable ( NSHashTable *table); FOUNDATION_EXPORT void * NSNextHashEnumeratorItem ( NSHashEnumerator *enumerator); FOUNDATION_EXPORT void NSEndHashTableEnumeration ( NSHashEnumerator *enumerator); FOUNDATION_EXPORT NSUInteger NSCountHashTable ( NSHashTable *table); FOUNDATION_EXPORT NSString * NSStringFromHashTable ( NSHashTable *table); FOUNDATION_EXPORT NSArray * NSAllHashTableObjects ( NSHashTable *table); |
第八:小结
这NSPointerArray,NSMapTable,NSHashTable类集合类型在 10.5 之后引入,比传统的集合类型更为强大,但是它们的方法却没有传统集合类型多,比如对于 NSPointerArray 来说:
* 操作均基于 index,无法通过 object 来进行操作;
* 无法直接插入 array,或用 array 初始化;
* 查找功能没有 NSArray 强大;
* 没有逆序、排序等 API 提供
以上几点仅仅是举的例子,所以 NSPointerArray 也并没有看起来的那么强大,一切选择标准,都应该依据具体需求。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)