容器
来源:互联网 发布:win平板装ubuntu 编辑:程序博客网 时间:2024/06/05 00:46
迭代器
在使用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法进行索引,主要区别:
- HashMap非线程安全,允许空键值,但最多只允许一条记录的键为null。
- HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey。Hashtable继承自Dictionary类。
- Hashtable的方法是线程安全的。
- Hashtable中Hash数组默认大小是11,增加的方式是old*2+1。在HashMap中,Hash数组默认大小是16,而且一定是2的指数。
- 两者采用的hash/rehash算法几乎一样。
- 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 nullabc nullzxc huai{null=null, id= 111,name= rose=address2}null nullid= 111,name= rose address2
Collection和Collections
0 0
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 容器
- 滑动屏幕旋转模型功能实现
- aar包的应用
- MapReduce 计数器
- 【mysql】关于ICP、MRR、BKA等特性
- android 四大组件之Service
- 容器
- 图文笔记,带你走进《未来简史》(26-30)
- grep 或
- spring boot
- Python 基础 —— global 与 nonlocal
- hosts文件的作用
- Struts2第七篇【介绍拦截器、自定义拦截器、执行流程、应用】
- TortoiseGit之配置密钥
- 关于ionic ion-nav-back-button 标题隐藏及修改