容器

迭代器

在使用iterator()时会经常遇到ConcurrentModificationException异常,这通常是由于在使用Iterator遍历的同时又使用Collection.add对容器做增加或者删除的操作所导致的,或者由于多线程操作导致的。

        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

当调用iterator()返回Iterator对象时,expectedModCount等于此刻容器中元素的个数。在调用next()时会比较modCount != expectedModCount。因此在使用Iterator遍历容器的过程中,如果对容器进去增加或删除操作,就会改变容器中元素的数量,即modCount。

解决方法:

  • 使用ListIterator.add
  • 使用Iterator.remove或ListIterator.remove
  • 遍历过程中将需要删除的对象保存到另一个集合,遍历结束后调用removeAll()

多线程访问容器的过程中抛出ConcurrentModificationException解决方法:

  • 使用线程安全的容器,比如ConcurrentHashMap和CopyOnWriteArrayList
  • 在使用迭代器遍历容器时对容器的操作放到synchronized代码中,但是当引用程序并发程度比较高时,会严重影响程序的性能。

ArrayList、Vector和LinkedList

Vector是线程安全的,ArrayList不是线程安全的,所以Vector性能上略逊于ArrayList。


HashMap、Hashtable、TreeMap、LinkedHashMap和WeakHashMap

HashMap和Hashtable都采用hash法进行索引,主要区别:

  1. HashMap非线程安全,允许空键值,但最多只允许一条记录的键为null。
  2. HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey。Hashtable继承自Dictionary类。
  3. Hashtable的方法是线程安全的。
  4. Hashtable中Hash数组默认大小是11,增加的方式是old*2+1。在HashMap中,Hash数组默认大小是16,而且一定是2的指数。
  5. 两者采用的hash/rehash算法几乎一样。
  6. hash值的使用不同,Hashtable直接使用对象的hashCode。

WeakHashMap中key采用的是“弱引用”的方式,只要key不再被外部引用,它就可以被垃圾回收器回收。而HashMap中key采用“强引用的方式”,只有key从HashMap中删除后,才会被回收。

如何实现HashMap的同步?
    Map map1 = Collections.synchronizedMap(new HashMap<>());

用自定义类型作为HashMap或Hashtable的key

重写key对象的hashCode()和equals()方法
如果两个对象相等,则其hashCode也相等
package containers;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by mook on 2017/5/3.
 */
class Person {
    String id;
    String name;

    public Person(String id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "id= " + id + ",name= " + name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (id != null ? !id.equals(person.id) : person.id != null) return false;
        return name != null ? name.equals(person.name) : person.name == null;

    }

    @Override
    public int hashCode() {
        int result = id != null ? id.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        return result;
    }
}

public class mapKey {
    public static void test() {
        Map<String,String> map = new HashMap<>();
        map.put(null,null);
        map.put("abc",null);
        map.put("zxc","ni");
        map.put("zxc","huai");
        System.out.println(map);
        Iterator iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
            System.out.println(key + "   " + value);
        }
    }
    public static void testPerson() {
        Map<Person,String> map = new HashMap<>();
        Person p1 = new Person("111", "rose");
        Person p2 = new Person("111", "rose");
        map.put(null,null);
        map.put(p1, "address1");
        map.put(p2, "address2");
        System.out.println(map);
        Iterator iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            Person key = (Person) entry.getKey();
            String value = (String) entry.getValue();
            System.out.println(key + "   " + value);
        }
    }
    public static void main(String[] args) {
        test();
        testPerson();
    }
}
**output:**
{null=null, abc=null, zxc=huai}
null   null
abc   null
zxc   huai
{null=null, id= 111,name= rose=address2}
null   null
id= 111,name= rose   address2

Collection和Collections

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值