集合中踩到的一些坑
一:List集合不能在指定下标存储位置
- 需求:有时我们需要根据用户输入的编号或对象中的某个值,又或者是随机到的某个值作为下标来在List集合中的指定下标存储数据
- 问题:如果List集合是第一次存储,则会抛出
IndexOutOfBoundsException
异常,示例代码如下:
List<String> list = new ArrayList<>();
list.add(2,"第一次对数据进行存储");
控制台输出如下:
- 原因:List集合的长度是动态增加的,存入一个数据其长度才会增加1,因此在没有存储到该位置时,是无法使用add(index,element)方法将数据存储到此位置上
- 解决方案
- 如果没有动态扩容的需求,可以采用数组进行存储
- 如果有动态扩容的需求,可以使用
TreeMap<Integer,String>
模拟List集合,即将key
当做下标,value
为值,使用TreeMap
这种可以根据key
进行排序的Map集合来保证模拟的集合有序。如果你使用了该方案可能会出现坑二中的情况 - 也可以在使用前对可能使用到的下标进行初始化,对其赋以一个默认值,但不推荐使用此方法,因为你可能无法预测到所有可能需要使用的下标,如果能够预测,可以使用第一种方法,如果有动态扩容的需求,可以使用第二种
二:在使用Map模拟List集合时使用普通for循环可能出现查找不到数据的情况
- 问题:如果你采用了上面所说的第二种解决方案,同时你又使用了普通for循环在
Map
查找数据,就可能导致搜索不到数据的问题。示例代码如下:
Map<Integer,String> map = new TreeMap<>();
map.put(0,"张三");
map.put(1,"李四");
map.put(4,"赵六");
map.put(2,"五五");
//此时,如果你想通过普通for循环查找值为 "赵六" 的key
int index = -1;
for (int i = 0; i < map.size(); i++) {
if ("赵六".equals(map.get(i))){
index = i;
break;
}
}
System.out.println(index);
控制台输出如下:
此时我们就会发现,明明在map
中存在该value却查找不到的情况
- 原因
- 我们使用该
map
模拟List
列表时,有时我们会将该map
看作一个List
列表对待,我们在List
列表采用普通 for 循环时,通常不会出现以上情况,因为List
列表是动态数组,有 n 个数就就可以取到 n-1 个下标,因此采用普通 for 就可以完成对List
列表的遍历 - 但模拟
List
列表的map
对象不同,其 size 方法返回的值代表的是map
对象的元素个数,也就意味着在模拟List
列表,当出现大于其元素个数的key
时,会出现没有遍历完该map
对象的情况,此时就会出现查找不到元素的情况
- 我们使用该
- 解决方案
- 使用增强 for 循环遍历
map
对象的keySet
,即 foreach 循环,keySet
是map
对象 keySet 方法的返回值,为 key 的Set
对象 - 若无需获取 key 值,也可直接通过 values 方法获取 value 的集合对象进行遍历
- 使用增强 for 循环遍历