Collection为集合层级的根接口。 一个集合表明一组对象,这些对象即为它的元素。 Java平台不提供这个接口任何直接的实现。
Set是一个不能包含重复元素的集合。 这个接口对数学集合抽象进行建模,被用来表明集合,就如一副牌。
List是一个有序集合,能够包含重复元素。 你能够经过它的索引来访问任何元素。List更像长度动态变换的数组。
Map是一个将key映射到value的对象.
一个Map不能包含重复的key:每一个key最多只能映射一个value。
一些其它的接口有Queue、Dequeue、SortedSet、SortedMap和ListIterator
Iterator:只能正向遍历集合,只能够向前遍历,适用于获取移除元素。
ListIerator:ListIerator能够双向遍历,ListIterator从Iterator接口继承,而后添加了一些额外的功能,好比添加一个元素、替换一个元素、获取前面或后面元素的索引位置。java
咱们可使用Iterator来遍历Set和List集合,而ListIterator只能遍历List。
同步意味着在一个时间点只能有一个线程能够修改哈希表,任何线程在执行hashtable的更新操做前须要获取对象锁,其余线程等待锁的释放。web
HashMap能够经过Map m = Collections.synchronizedMap(hashMap)来达到同步的效果。数组
第一种 这是最多见的用法,缓存
优势:这种用法能够同时拿到key和value值。
缺点:若是map是空,将会出现空指针异常,那么每次在对map遍历之前,就要先进行判空
public static void forEachMap(Map<String,String> map) { for ( Map.Entry<String,String> entry : map.entrySet()) { System.out.println(entry.getKey()+entry.getValue()); } }
第二种安全
只遍历key或者value。
比第一种方法的效率略微有提高,并且代码也能简洁一点。
一样,这种方法也须要判断map是否为空数据结构
public static void forEachMap2(Map<String,String> map){ for (String str :map.keySet()){ System.out.println(str); } for (String str :map.values()){ System.out.println(str); } }
第三种多线程
使用迭代器的方式并发
public static void forEachMap1(Map<String, String> map) { Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, String> entry = iterator.next(); System.out.println(entry.getKey() + entry.getValue()); } } // 使用迭代器可是不适用泛型 public static void forEachMap4(Map<String, String> map) { Iterator iterator = map.entrySet().iterator(); while (iterator.hasNext()){ Map.Entry entry= (Map.Entry) iterator.next(); //这里的类型转换的缘由是,若是不加String,那么背默认为两个object,不能相加 System.out.println((String)entry.getKey() + entry.getValue()); } }
第四种框架
先拿到map的key值,再拿取value值。 这种方式效率比较低,通常不推荐使用svg
for (Integer key : map.keySet()) { Integer value = map.get(key); System.out.println("Key = " + key + ", Value = " + value); }
1.ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。 2.对于随机访问的get和set方法,ArrayList要优于LinkedList,由于LinkedList要移动指针。 3.对于新增和删除操做add和remove,LinkedList比较占优点,由于ArrayList要移动数据。
LinkedList常常用在增删操做较多而查询操做不多的状况下,ArrayList则相反。
这三个类都继承自List接口,内部元素能够重复但有序。都在java.util包中,都是可伸缩的数组,也就是说能够动态改变数组的长度。
ArrayList和Vector:都是基于Object[] 对象数组实现的。它们在建立的时候会申请连续的存储空间来存储数据。总结:
他们支持使用下标来访问元素,索引数据的速度回比较快。
由于是顺序存储,插入数据的时候须要移动容器中的数据,因此对数据的插入操做效率会比较慢。
ArrayList和Vector都有一个初始化的容量值,当添加
进入容易中的数据长度大于容器的长度时,它们会自动动态扩充
他们的存储单元。Vector默认扩充为原来的2倍,而ArrayList扩充为原来的1.5倍。
区别:
它俩最大的区别就是同步的使用。ArrayList中的方法都是非同步的,因此ArrayList不是安全的,Vector中的大多数方法都是直接或者间接同步的,因此Vector是线程安全的。相对而言,由于Vector是线程安全,而ArrayList线程不安全,因此ArrayList性能较Vector高。
LinkedList是采用双向列表实现的,对数据的索引须要从列表头开始遍历,所以用于随机访问则效率比较低。可是由于插入元素是不须要对数据进行移动,所以插入操做的效率较高。同时LinkedList是非线程安全容器。
List的选择:
当进行索引或在集合的末端增长和删除元素时,使用ArrayList和Vector的效率较高;
当进行特定位置的插入和删除元素的操做时,LinkedList的效率较高;由于LinkedList不须要移动元素。当在多线程中使用容器时,选择Vector比较安全。由于Vector是线程安全。
foreach的语法只是对iterator进行了简单的包装,使用起来更加方便而已,可是若是在foreach循环体内,对集合元素进行删除添加操做的时候,会报出ConcurrentModificationException,并发修改异常。
若是须要在遍历集合的时候对象集合中元素进行删除操做,须要使用iterator的遍历方式,iterator自带的remove删除方式不会报出异常。
import java.util.List; import java.util.ArrayList; import java.util.List; public class UseForeach { public static void main(String[] args) { List<String> list=new ArrayList<String>(); //遍历集合 list.add("abc"); list.add("def"); list.add("hjj"); list.add("klm"); list.add("nop"); list.add("qrs"); System.out.println("foreach example\n"); for(String string:list) { System.out.println(string); } System.out.println(); String[] strs=new String[list.size()]; //遍历数组 list.toArray(strs); for(String string:list) { System.out.println(string); } } }
import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Test_1 { public Test_1() { // TODO Auto-generated constructor stub } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub List l = new ArrayList(); l.add("aa"); l.add("bb"); l.add("cc"); for (Iterator i = l.iterator(); i.hasNext();) { String str = (String) i.next(); System.out.println(str); } System.out.print("\n"); Iterator it = l.iterator(); while (it.hasNext()) { String str = (String) it.next(); System.out.println(str); } }//main } 运行结果: //aa //bb //cc // //aa //bb //cc //
CopyOnWriteArrayList是ArrayList的一个线程安全的变体,其中全部可变操做(add、set等等)都是经过对底层数组进行一次新的复制来实现的。相比较于ArrayList它的写操做要慢一些,由于它须要实例的快照。
CopyOnWriteArrayList中写操做须要大面积复制数组,因此性能确定不好,可是读操做由于操做的对象和写操做不是同一个对象,读之间也不须要加锁,读和写之间的同步处理只是在写完后经过一个简单的"="将引用指向新的数组对象上来,这个几乎不须要时间,这样读操做就很快很安全,适合在多线程里使用,绝对不会发生ConcurrentModificationException ,所以CopyOnWriteArrayList适合使用在读操做远远大于写操做的场景里,好比缓存。
文章持续更新:欢迎各位小伙伴关注个人公众号:菜丸的程序屋。但愿将个人不足之处给予指点,谢谢你们。