集合遍历和数组排序

一、集合遍历
  集合:OC中提供的容器类,数组,字典,集合。
  遍历:对集合中元素一次取出的过程叫做遍历。
  三种方式:
  1. for循环遍历
  2. NSEnumerator遍历
  3. for…in遍历
二、for循环遍历
  数组遍历:通过for循环的循环变量用作数组元素下标来获取不同下标的元素。循环次数就是数组元素的个数。
 示例:

NSArray *arr = @[@"aaa", @"bbb", @"ccc", @"ddd", @"eee"];
for (NSUInteger i = 0; i < arr.count; i++)
{
    NSLog(@"%@", arr[i]);
}

  字典遍历:先获取字典中所有的key,存储到数组中,遍历数组依次取出每一个key,然后根据key从字典中取出对应的value。循环次数等于字典的元素个数。
  示例:

NSDictionary *dic = @{@"name":@"盖伦", @"age":@"123", @"gender":@"w"};
NSArray *keysArr = [dic allKeys];
for (NSUInteger i = 0; i < keysArr.count; i++)
{
    NSString *key = keysArr[i];
    NSLog(@"%@", dic[key]);
}

  集合遍历:用集合的allObjects属性先取到集合的所有元素存储到数组中,再通过for循环的循环变量用作下标来取到每个元素。
  示例:

NSSet *set = [NSSet setWithObjects:@"element1",@"element2", @"element3", @"element4", nil];
NSArray *objects = set.allObjects;
for (NSUInteger i = 0; i < objects.count; i++)
{
    NSString *value = [objects objectAtIndex:i];
    NSLog(@"value:%@", value);
}

三、NSEnumerator
  NSEnumerator:枚举器,遍历集合中的元素。其没有创建对象的接口,要想生成其对象,必须依赖于集合类(数组,字典,集合)。枚举器的nextObject方法,可以取到其依附的集合对象中的每一个对象,如果取完返回nil,枚举器对象经常与while循环一起使用。
  注意:在使用枚举器进行遍历时,不可以对正在遍历的可变集合对象进行删除,添加操作。
  数组枚举:

//正序枚举
NSArray *arr = @[@"1", @"2", @"3", @"4"];
NSEnumerator *enumerator = [arr objectEnumerator];
id value = nil;
while (value = [enumerator nextObject])
{
    NSLog(@"%@", value);
}    
//反序遍历
NSArray *arr = @[@"1", @"2", @"3", @"4"];
//创建枚举器对象(反序)
NSEnumerator *reverse = [arr reverseObjectEnumerator];
id value = nil;
while (value = [reverse nextObject])
{
    NSLog(@"%@", value);
}

  字典枚举遍历:

//字典是无序的,所有没有反序遍历
//对字典进行枚举器遍历得到的值就是value
NSDictionary *dictionary = @{@"key1":@"value1", @"key2":@"value2", @"key3":@"value3", @"key4":@"value4"};
NSEnumerator *enumerator = [dictionary objectEnumerator];
d value = nil;
while (value = [enumerator nextObject])
{
    NSLog(@"%@", value);
}

  集合枚举遍历:

//字典是无序的,所有没有反序遍历
NSSet *set = [NSSet setWithObjects:@"aa", @"bb", @"cc", @"dd", nil];
NSEnumerator *enumerator = [set objectEnumerator];
id value = nil;
while (value = [enumerator nextObject]) 
{
    NSLog(@"%@", value);
}

四、for…in
  for…in:快速枚举,是在NSEnumerator的基础上封装的更加方便的快速的遍历集合元素的方式。
  格式:

for (集合中对象的类型 *元素名 in 被遍历的集合)
{
    语句;
}

  数组的快速枚举:

NSMutableArray *arr = [@[@"1", @"2", @"3", @"4"] mutableCopy];
for (id value in arr)
{
    if ([value isEqualToString:@"4"])
    {
        [arr removeObject:value];
    }
    NSLog(@"%@", arr);
}

  字典的快速枚举:

//对字典的快速枚举得到的是字典中的key值!
NSDictionary *dic = @{@"name":@"lihua", @"age":@20, @"gender":@"man"};
for (id key in dic) 
{
    NSLog(@"%@", dic[key]);
}

  集合的快速遍历:

//得到的是集合中的每个元素
NSSet *set = [NSSet setWithObjects:@"1", @"2", @"3", @"4",@"5", nil];
for (NSString *str in set)
{
    NSLog(@"%@", str);
}

五、数组排序
  数组是有序容器,因此集合中只有数组才能排序。
  NSSortDescriptor:该类能够方便的实现对数组中的对象进行升序或者降序的排序。它可以把元素的某个属性作为key进行升序或降序的排序,每个NSSortDescriptor对象就是一个排序条件。
  示例:

//1.按姓名排序
NSSortDescriptor *sortName = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
//2.按年龄排序
NSSortDescriptor *sortAge = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:YES];
//ascending:排序标志,YES-升序,NO-降序.
//数组排序:如果该参数中存储了由name和age两个属性参与创建的NSSortDescriptor对象,在按name进行排序的同时,如果遇到姓名相同的就会按照age进行排序.
NSArray *newArr = [arr sortedArrayUsingDescriptors:@[sortName,sortAge]];
NSLog(@"%@", newArr);

  其他数组排序方法:

//不可变数组排序方法(排序结果生成新数组,原数组无改变)
NSArray *arr = @[@"aaa", @"yyy", @"ccc", @"rrr"];
NSArray *newArr = [arr sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"%@", newArr);

//可变数组排序方法(直接对原数组操作,无新数组生成)
NSMutableArray *mArr = [@[@"aaa", @"yyy", @"ccc", @"rrr"]mutableCopy];
[mArr sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"%@", mArr);
<think>好的,我现在需要回答用户关于List集合数组的区别的问题,包括功能、使用场景性能差异。首先,我得回想一下之前学过的相关知识,以及用户提供的引用内容。 首先,根据引用[1],数组集合在Java中是两种不同的数据结构,各有特点。用户现在问的是List集合数组的区别,可能需要扩展到其他语言,但引用里提到了JavaC#,所以可能需要分语言讨论,但用户可能主要关注通用区别,或者特定于某一种语言?不过问题没有明确,所以应该以通用为主,结合引用中的例子。 引用[2]提到数组可以使用Arrays类的方法,集合使用Collections类的方法,这说明功能上的差异,比如集合可能提供更多内置方法。而引用[3]中C#的List数组比较,提到数组访问更快,因为内存连续,而List可能分散,但性能差异通常可以忽略。引用[4]则说明数组适合固定大小高性能场景,比如游戏中的固定数量敌人。 接下来,我需要整理这些点,分功能、使用场景、性能差异几个方面。功能方面,数组大小固定,类型固定,而List动态扩容,提供更多操作方法。使用场景的话,数组适合元素数量固定、注重性能;List适合需要动态增减元素的场景。性能方面,数组在访问内存使用上更高效,而List在插入删除时可能更高效,特别是对于动态调整的情况。 然后需要确保用LaTeX格式,行内用$,独立公式用$$。比如数组的访问时间复杂度是O(1),List的访问可能也是O(1)(如果是ArrayList),但如果是LinkedList则是O(n)。但根据引用[3],数组的访问更快因为内存连续,所以可能即使同样是O(1),数组更快。 还需要生成相关问题,比如适用场景的例子,如何选择两者,性能优化方法等。要确保引用正确,比如在提到性能时引用[3][4]。 可能需要注意不同编程语言的实现差异,比如Java的ArrayListC#的List,但用户的问题可能更偏向于通用概念,所以需要一般化回答,但引用中的例子来自不同语言,可能需要说明语言特定情况,或者指出这些是通用差异。 现在开始组织内容: 1. 功能差异:数组固定大小,类型固定;List动态大小,支持泛型,提供更多方法如add/remove。 2. 使用场景:数组用于固定大小高性能需求;List用于需要动态调整的情况。 3. 性能差异:数组在访问内存上更优;List在增删元素时更高效,特别是避免大量数据搬移。 然后每个部分需要结合引用内容,例如引用[3]提到数组访问性能更好,引用[4]说明数组适合固定大小高性能场景。 最后生成相关问题,例如如何选择数组List,优化性能的方法,各自的应用实例等。 需要确保回答结构清晰,分点说明,正确使用LaTeX格式,比如时间复杂度用$O(1)$,并添加引用标记。</think>### List集合数组的区别对比 #### 一、功能差异 1. **容量固定性** - **数组**:长度固定,声明时需明确大小(例如:`int[] arr = new int[5];`),无法动态扩展[^4]。 - **List**:长度动态可变(如Java的`ArrayList`或C#的`List<T>`),自动扩容(例如:`List<Integer> list = new ArrayList<>();`)[^1][^3]。 2. **操作方法** - **数组**:仅支持基础操作(如索引访问),需依赖工具类(如`Arrays.sort()`)实现排序、搜索等[^2]。 - **List**:内置丰富方法(如`add()`、`remove()`、`contains()`),可直接调用集合工具类(如`Collections.sort()`)[^2]。 3. **类型支持** - **数组**:可存储基本类型(如`int`)或对象类型,类型固定。 - **List**:仅支持对象类型(Java中需用包装类),且支持泛型约束(如`List<String>`)[^1]。 --- #### 二、性能差异 1. **访问效率** - 数组通过连续内存实现$O(1)$时间复杂度的随机访问,性能更优[^3][^4]。 - List(如`ArrayList`)底层基于数组,访问效率与数组接近;但`LinkedList`需遍历链表,随机访问为$O(n)$。 2. **增删操作** - 数组增删元素需手动移动数据,时间复杂度为$O(n)$(例如删除中间元素需整体前移)。 - List的`ArrayList`在尾部增删为$O(1)$,中间操作仍需$O(n)$;`LinkedList`通过指针操作实现$O(1)$插入删除[^3]。 3. **内存占用** - 数组内存分配一次完成,无额外开销。 - List(如`ArrayList`)预留扩容空间,可能存在内存浪费;动态扩容时(如Java扩容1.5倍)会触发数据复制[^3]。 --- #### 三、使用场景 1. **适用数组的场景** - **数据量固定**:例如存储固定数量的配置参数或游戏中的固定对象池[^4]。 - **高频访问**:科学计算、图像处理等需要快速随机读写的场景[^3][^4]。 - **内存敏感**:嵌入式系统等资源受限环境。 2. **适用List的场景** - **动态数据**:如用户动态添加的日志记录或购物车商品。 - **频繁增删**:任务队列、实时数据流处理(优先选择`LinkedList`)。 - **功能扩展**:需要直接调用现成方法(如排序、过滤)的业务逻辑[^2]。 --- #### 四、代码示例对比 **数组操作** ```java int[] scores = new int[10]; // 固定大小 scores[0] = 90; // 直接赋值 Arrays.sort(scores); // 依赖工具类 ``` **List操作** ```java List<Integer> scores = new ArrayList<>(); scores.add(90); // 动态扩展 scores.remove(0); // 直接删除 Collections.sort(scores); // 内置方法 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值