前言:因为看到网上关于循环遍历,好多博客内容都比较少,要么只说了list,要么只说了set或者map,我想整理一下,所以就把几个整理到一起。也做了一些总结,希望对大家也有所帮助。以下demo的完整代码可以在github上面下载(链接地址)
(一)遍历List
List<String> list = getArrayList();
/**
* 方式一,使用for循环
*/
for (int i = 0, len = list.size(); i < len; i++) {
String s = list.get(i);
System.out.println(s);
}
/**
* 方式二,使用增强for循环
*/
for (String s : list) {
System.out.println(s);
}
/**
* 方式三,使用for和Iterator
*/
for(Iterator<String> iterator = list.iterator(); iterator.hasNext();){
String value = iterator.next();
System.out.println(value);
}
/**
* 方式四,使用while和Iterator(效率和方式3一样)
*/
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
String s = iterator.next();
System.out.println(s);
}
/**
* 生成一个List,用于遍历
* @return 生成的List
*/
public static List<String> getArrayList() {
List<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
list.add("dd");
return list;
}
PS:
以上就是List遍历的4种方式。
- 个人认为对于android来说,数据量都不会很大,效率都差不多,自己哪个方便就用哪种。
- 理论上,方式1是最快的,但是需要考虑并发问题。而如果要进行删除操作,就只能用iterator。
- foreach 和for:foreach 只能从头到尾,不可以从后面开始遍历。foreach遍历的时候不能给迭代变量赋值(可以给迭代变量里面的内容),比如你不可以修改User引用,可以通过该引用修改User内部数据。
(二)遍历HashSet
public static void main(String[] args) {
Set<String> set = getHashSet();
/**
* 方式1,增强for循环
*/
for (String value : set) {
System.out.println(value);
}
/**
* 方式2,使用迭代器Iterator
*/
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String value = iterator.next();
System.out.println(value);
}
/**
* 方式3,使用for和迭代器Iterator,和方式2一样,写法不一样而已
*/
for (Iterator<String> iterator2 = set.iterator(); iterator2.hasNext(); ) {
String value = iterator.next();
System.out.println(value);
}
}
/**
* 生成一个Set<String>,用于遍历
*
* @return 生成的Set<String>
*/
public static Set<String> getHashSet() {
Set<String> set = new HashSet<>();
set.add("aa");
set.add("bb");
set.add("cc");
return set;
}
PS:
set可以添加null元素,不能添加重复的元素(重复元素以hashCode和equals作为判断依据),当add(Object)的时候,如果set不存在和Object的hashCode一样的元素就直接add.如果存在就会调用equals方法比较两个元素,如果返回true,就当作相同元素,否则当作不同元素,添加元素到集合。具体添加重复元素验证可以参考案例的CollectionsDemo,修改Student类即可验证。
(三)遍历Map
public static void main(String[] args) {
Map<String, String> map = getHashMap();
/**
* 方式1,使用for-each。
*/
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key:" + entry.getKey() + ",value:" + entry.getValue());
}
/**
*方式2,使用Iterator遍历(使用泛型)
*/
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
System.out.println("key:" + entry.getKey() + ",value:" + entry.getValue());
}
/**
*方式3,使用Iterator遍历(不使用泛型)
*/
Iterator iterator1 = map.entrySet().iterator();
while (iterator1.hasNext()) {
Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator1.next();
System.out.println("key:" + entry.getKey() + ",value:" + entry.getValue());
}
/**
* 方式4,通过键遍历(效率低)
*/
for (String key : map.keySet()) {
String value = map.get(key);
System.out.println("key:" + key + ",value:" + value);
}
/**
* 方式5,只需要key集合或者value集合时候使用
*/
for (String key : map.keySet()) {
System.out.println("key:" + key);
}
for (String value : map.values()) {
System.out.println("value:" + value);
}
}
/**
* 生成一个Map<String, String>,用于遍历
*
* @return Map<String, String>
*/
public static Map<String, String> getHashMap() {
Map<String, String> map = new HashMap<>();
map.put("a", "a_value");
map.put("b", "b_value");
map.put("c", "c_value");
return map;
}
PS:
map一般都使用Iterator遍历或者for-each遍历
总结
- 遍历删除问题
遍历的时候要使用删除的话,直接使用集合引用进行删除操作会抛ConcurrentModificationException异常,
需要调用Iterator的remove方法才行。例子:{@link ListTraverseDemo#testTraverseRemove()}
- 添加元素问题
set不能添加重复的元素(重复元素以hashCode和equals作为判断依据),当add(Object)的时候,如果set不存在和Object的hashCode一样的元素就直接add.
map 添加存在相同key的时候,其value会覆盖前面的value。 - 是否可以添加null元素
list和set可以,map的key和value都可以,
PS:set内部是使用map实现的,存放元素的使用,set的value将作为map的key,set引用作为map的value。
- 线城安全问题
ArrayList,HashMap,HashSet 都是不安全的。可以使用Collections中的方法转成安全类型的集合:
synchronizedMap(map),synchronizedList(list),synchronizedSet(set)。
PS:内部其实是使用了 装饰模式:继承了该集合类,增强方法,重写操作的方法中使用了synchronized 调用被装饰对象的操作方法。
我只是粗略总结一下主要注意点,能力有限,如有不当之处,如有欢迎各位指正,如有容易忽略和容易犯错的注意点需要补充也欢迎提出。