Java集合体系(三)-- 遍历方式和删除异常分析

1、List遍历方式一

import java.util.ArrayList;

/**
 * @author RuiMing Lin
 * @date 2020-03-05 16:38
 */
public class Demo2 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        
        list.add(1);
        list.add(2);
        list.add(2);
        list.add(3);
        //遍历方式一:普通for循环
        for(int i = 0;i < list.size(); i++) {
            System.out.print(list.get(i) + " ");
        }
        System.out.println();
        //使用遍历方式一进行删除所有为2的元素
        for(int i=0; i<list.size(); i++) {
            if (2 == list.get(i)) {
                list.remove(i);
            }
        }
        System.out.println("list.toString() = " + list.toString());
    }
}

结果为:
1 2 2 3
list.toString() = [1, 2, 3]

此时便出现了一个错误:有一个2 未被删除。原因是当删除一个元素时,后面元素的索引就会被修改(index = index - 1),如删除第一个2 时候,此时下一个元素2的索引由原来的索引为2变为1,而此时for循环执行i++,对应索引的位置为2 而新的1索引上的值就不会在读取了,所以结果为【1,2,3】。要解决这个问题很容易,需要把 list.remove(i)改为list.remove(i - -)。

2、List遍历方式二

import java.util.ArrayList;
import java.util.Iterator;

/**
 * @author RuiMing Lin
 * @date 2020-03-05 16:38
 */
public class Demo2 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        
        list.add(1);
        list.add(2);
        list.add(2);
        list.add(3);
        //遍历方式二:使用迭代器
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()){
            Integer next = iterator.next();
            System.out.println("next = " + next);
            if (next == 2){
                //务必使用Iterator的remove()
                iterator.remove();
            }
        }

        System.out.println("list.toString() = " + list.toString());
    }
}

删除元素过程中务必使用Iterator的remove(),若是使用集合的remove(),迭代器便会检测到集合的内容发生改变,便会报出并发修改异常。

3、List遍历方式三

import java.util.ArrayList;
import java.util.Iterator;

/**
 * @author RuiMing Lin
 * @date 2020-03-05 16:38
 */
public class Demo2 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        
        list.add(1);
        list.add(2);
        list.add(2);
        list.add(3);
        //遍历方式三:使用增强for循环
        for (Integer integer : list) {
            System.out.println("integer = " + integer);
        }
        System.out.println("list.toString() = " + list.toString());
    }
}

使用增强for循环无法删除元素,因为集合删除元素需要提供索引。

4、Map遍历方式一

import java.util.LinkedHashMap;
import java.util.Set;

/**
 * @author RuiMing Lin
 * @date 2020-03-05 16:14
 */
public class LinkedHashMapDemo {
    public static void main(String[] args) {
        LinkedHashMap<String,Integer> lsmap = new LinkedHashMap();
        lsmap.put("小明", 18);
        lsmap.put("小红", 19);
        lsmap.put("小刚", 20);
        Set<String> keySet = lsmap.keySet();
        for (String key : keySet) {
            Integer integer = lsmap.get(key);
            System.out.println("integer = " + integer);
        }
    }
}

使用Map集合的keySet()获取所有的key,再通过key获取value

5、Map遍历方式二

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author RuiMing Lin
 * @date 2020-03-05 16:01
 */
public class Person {
    //使用Person类所为key
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;
        Person person = (Person) o;
        return getAge() == person.getAge() &&
                Objects.equals(getName(), person.getName());
    }
    @Override
    public int hashCode() {
        return Objects.hash(getName(), getAge());
    }

    public static void main(String[] args) {
        HashMap<Person, String> hmap = new HashMap<>();
        hmap.put(new Person("小明", 18), "是个坏学生");
        hmap.put(new Person("小红", 17), "是个好学生");
        hmap.put(new Person("小刚", 19), "是个学霸");
        Set<Map.Entry<Person, String>> entrySet = hmap.entrySet();
        for (Map.Entry<Person, String> entry : entrySet) {
            Person person = entry.getKey();
            String string = entry.getValue();
            System.out.println("person = " + person + "..." + "string = " + string);
        }
    }
}

通过获取Map的内部类Entry获取所有的k-v对,再通过Entry的getKey()和getValue()获取key和value。

6、Map遍历两种方式的比较

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author RuiMing Lin
 * @date 2020-02-29 16:03
 */
public class Demo1 {
    public static void main(String[] args) {
        HashMap<Integer, String> map = new HashMap<>();
        for (int i = 0; i < 100000000; i++) {
            // 向map集合添加100w条数据
            map.put(i, "num" + i);
        }
        for (int i = 1; i <= 5; i++) {
            long time = entryTime(map);
            System.out.println("使用entrySet()第" + i + "次花费时间为" + time + "ms");
        }
        for (int i = 1; i <= 5; i++) {
            long time = keyTime(map);
            System.out.println("使用keySet()第" + i + "次花费时间为" + time + "ms");
        }

    }

    public static long entryTime(HashMap<Integer, String> map) {
        long start = System.currentTimeMillis();
        Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
        for (Map.Entry<Integer, String> entry : entrySet) {
            Integer key = entry.getKey();
            String value = entry.getValue();
            //System.out.println("key = " + key +"..." + "value = " + value);
        }
        long end = System.currentTimeMillis();
        return end - start;
    }

    public static long keyTime(HashMap<Integer, String> map) {
        long start = System.currentTimeMillis();
        Set<Integer> keySet = map.keySet();
        for (Integer key : keySet) {
            String value = map.get(key);//keySet()花费时间的原因,需要遍历2次map集合
        }
        long end = System.currentTimeMillis();
        return end - start;
    }
}

结果输出为:
使用entrySet()第1次花费时间为158ms
使用entrySet()第2次花费时间为136ms
使用entrySet()第3次花费时间为153ms
使用entrySet()第4次花费时间为149ms
使用entrySet()第5次花费时间为152ms
使用keySet()第1次花费时间为200ms
使用keySet()第2次花费时间为190ms
使用keySet()第3次花费时间为257ms
使用keySet()第4次花费时间为238ms
使用keySet()第5次花费时间为175ms

分析:结果可以看出使用keySet()获取值所需要的时间较长,原因在于它需要遍历两次map集合

有错误的地方敬请指出!觉得写得可以的话麻烦给个赞!欢迎大家评论区或者私信交流!

发布了30 篇原创文章 · 获赞 72 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Orange_minger/article/details/104678099