Java集合架构由几个相关的组件构成: 接口 抽象类以及完全定义的类,其中, 每个完全定义的类继承了一个或多个抽象类,并实现了一个或多个接口
容器能否完全替代数组: 针对数组类型,很多语言都提供了容器类,比如Java中的ArrayList,在项目开发中,什么时候适合用数组,什么时候适合用容器呢?ArrayList最大的优势就是可以将很多数组操作的细节封装起来。比如前面提到的数组插入、删除数据时需要搬移其他数据等。另外,它还有一个优势,就是支持动态扩容。数组本身在定义的时候需要预先指定大小,因为需要分配连续的内存空间,如果使用ArrayList,我们就完全不需要关心底层的扩容逻辑,ArrayList已经帮我们实现好了。每次存储空间不够的时候,它都会将空间自动扩容为1.5倍大小,不过,这里需要注意一点,因为扩容操作涉及内存申请和数据搬移,是比较耗时的。所以,如果事先能确定需要存储的数据大小,最好在创建ArrayList的时候事先指定数据大小。是不是数组就无用武之地了呢?当然不是,有些时候,用数组会更合适些,我总结了几点自己的经验: 1.Java ArrayList无法存储基本类型,比如int、long,需要封装为Integer、Long类,而Autoboxing、Unboxing则有一定的性能消耗,所以如果特别关注性能,或者希 望使用基本类型,就可以选用数组。 2.如果数据大小事先已知,并且对数据的操作非常简单,用不到ArrayList提供的大部分方法,也可以直接使用数组。 3.还有一个是我个人的喜好,当要表示多维数组时,用数组往往会更加直观。比如Object[][] array;而用容器的话则需要这样定义:ArrayList array。对于业务开发,直接使用容器就足够了,省时省力。毕竟损耗一丢丢性能,完全不会影响到系统整体的性能。但如果你是做一些非常底层的开发,比如开发网络框架,性能的优化需要做到极致,这个时候数组就会优于容器,成为首选。
一次性就让我搞懂了Java集合,建议收藏起来! |
---|
Java 集合框架详解---非常好 | Java Collections Tutorial sample | Learn Java Collections with Examples |
---|
Learn Java Collections with Examples | Java Collections Framework |
---|
JAVA集合类型详解 | Java集合与继承树 | Java中的静态数组与动态数组 |
---|
Java 集合框架 | 面试江湖:一招破解 Java 集合类面试题 |
---|
- 枚举(Enumeration)---这种传统接口,在Java 2已被迭代器取代
- 位集合(BitSet)---这是一个传统的类,但它在Java 2中被完全重新设计
- 向量(Vector)---Vector 是同步访问的,Vector 主要用在事先不知道数组的大小,ArrayList不是线程同步的,而Vector是线程同步的,就是说如果两个或两个以上的线程如果同时访问一个ArrayList,就必须把ArrayList加锁,而Vector就不需要了。不过如果不考虑同步的话,ArrayList效率要比Vector高,
- 栈(Stack)---栈是Vector的一个子类,它实现了一个标准的后进先出的栈
- 字典(Dictionary)---是一个抽象类,它定义了键映射到值的数据结构。当你想要通过特定的键而不是整数索引来访问数据的时候,作用和Map类相似,Dictionary类已经过时了。在实际开发中,你可以实现Map接口来获取键/值的存储功能
- 哈希表(Hashtable)---Hashtable现在集成到了集合框架中(Collection)
- 属性(Properties)---Properties 继承于 Hashtable
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据
容器,就是可以容纳其他Java对象的对象,Java容器里只能放对象,对于基本类型(int, long, float, double等),需要将其包装成对象类型后(Integer, Long, Float, Double等)才能放到容器里。很多时候拆包装和解包装能够自动完成。这虽然会导致额外的性能和空间开销,但简化了设计和编程, 容器主要包括 Collection 和 Map 两种,Collection 存储着对象的集合,而 Map 存储着键值对(两个对象)的映射表
Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等
任何对象加入集合类后,自动转变为Object类型,所以在取出的时候,需要进行强制类型转换
- 0. Arrays类
- 1. Iterator接口---一般遍历数组都是采用for循环或者增强for,这两个方法也可以用在集合框架,但是还有一种方法是采用迭代器遍历集合框架,它是一个对象,实现了Iterator 接口或 ListIterator接口
- Java 迭代器Iterator的详解
- ListIterator接口---ListIterator 继承了 Iterator,以允许双向遍历列表和修改元素
- 2. Collection接口---单列数据, 定义了存取一组不唯一,无序的对象
-
子接口List---存储一组不唯一,有序(插入顺序)的对象, 允许有相同的元素, 使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素 *
- 线程安全的List
- 并发性能比较低
- 使用Vector容器
- 使用Collections的静态方法synchronizedList(List< T> list)
- 并发性能比较高
- 采用CopyOnWriteArrayList容器---CopyOnWriteArrayList只适合允许短暂数据不一致的场景,如果希望数据写入可以立即被读到,那CopyOnWriteArrayList就不适合了 从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器非常有用,可以在非常多的并发场景中使用到
- 并发性能比较低
- 非线程安全的List
- ArrayList实现类---基于动态数组实现,支持随机访问,需要一块连续的存储空间,查询快,增删慢,不同步,线程不安全,在多线程的情况下不要使用, 轻量级,ArrayList不是线程同步的,而Vector是线程同步的,就是说如果两个或两个以上的线程如果同时访问一个ArrayList,就必须把ArrayList加锁,而Vector就不需要了。不过如果不考虑同不的话,ArrayList效率要比Vector高,
- LinkedList实现类---链表实现,增删快,查询慢, 允许有null(空)元素。主要用于创建链表数据结构,该类没有同步方法,线程不安全,如果多个线程同时访问一个List,则必须自己实现访问同步,解决方法就是在创建List时候构造一个同步的List
- 线程安全的List
-
子接口Set---不保存重复的元素, 元素无序、不可重复的集合
- 线程安全的Set
- 非线程安全的Set
- HashSet实现类---不允许出现重复元素,不保证集合中元素的顺序,允许包含值为null的元素,但最多只能一个,线程不安全
- LinkedHashSet实现类---具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现,线程不安全
- 子接口SortedSet---对Set排序实现类
- TreeSet--- 该类实现了Set接口,可以实现排序等功能,线程不安全
-
- 线程安全的Queue集合
- 线程安全的阻塞队列
- BlockingQueue
- ArrayBlockingQueue
- LinkedBlockingQueue
- 线程安全的非阻塞队列
- ConcurrentLinkedQueue
- 线程安全的阻塞队列
- 非线程安全的Queue集合
- 线程安全的Queue集合
-
子接口Deque
-
- 3. Map接口--- 双列数据,保存具有映射关系“key-value对”的集合
- 线程安全的Map集合
- 并发性能比较低,这两种方式都是通过在类的方法上添加synchronized同步锁实现线程安全,
- HashTable
- HashTable实现类---线程安全的,不允许null的键或值,Hashtable使用synchronized同步锁修饰put、get、remove等方法,因此在高并发场景下,读写操作只能串行进行,会存在大量锁竞争,并发性能比较低,给系统带来性能开销
- Properties实现类---key和value都是String类型,用来读配置文件;TreeMap:对key排好序的Map; key 就是TreeSet, value对应每个key; key要实现Comparable接口或TreeMap有自己的构造器
- HashTable实现类---线程安全的,不允许null的键或值,Hashtable使用synchronized同步锁修饰put、get、remove等方法,因此在高并发场景下,读写操作只能串行进行,会存在大量锁竞争,并发性能比较低,给系统带来性能开销
- SynchronizedMap---一个同步代理类
- HashTable
- 并发性能高
- ConcurrentHashMap---推荐
- ConcurrentSkipListMap
- 并发性能比较低,这两种方式都是通过在类的方法上添加synchronized同步锁实现线程安全,
- 非线程安全Map集合
- 线程安全的Map集合
- 4 并发容器原理
- 5 Sorting
- 6 Aggregate Operations(Streams)
- 7 Collections Helper/Utility Classes
- 8 Convert Collections Examples
- Conversion Between Array and Set in Java
- Conversion Between Array and List in Java
- Java Convert Map to Set Example
- Java Convert Map to List Example
- Java Convert Map to Array Example
- Convert a Map to an Array, List, and Set in Java
- Java 8 Convert List to Map Example
- Java 8 - Merging Two Maps Example
- Java Convert Array to String [Snippet]
- 9 Collections Difference
- Collections vs Streams in Java
- Difference between Array vs ArrayList in Java
- Difference between LinkedList vs ArrayList in Java
- Difference between List and Set in Java Collection
- Difference between Stack and Queue Data Structure in Java
- Difference between HashMap and HashSet in Java
- Difference between TreeSet, LinkedHashSet, and HashSet in Java with Example
- Difference between EnumMap and HashMap in Java
- Difference between HashMap and HashSet in Java
- Difference between ArrayList and Vector in Java
- Difference between HashMap, LinkedHashMap, and TreeMap in Java
- Difference between PriorityQueue and TreeSet in Java?
- What is the difference between Enumeration and Iterator in Java?
- What is the difference between HashMap and Hashtable in Java?
- Difference between fail-fast Iterator vs fail-safe Iterator in Java
- 10 Collections Examples
- Different Ways to Iterate over List, Set, and Map in Java
- Java Comparator Interface Example
- Java Comparable Interface Example
- Java IdentityHashMap Example
- Java WeakHashMap Example
- Java EnumMap Example
- Java CopyOnWriteArraySet Example
- Java EnumSet Class Example
- Guide to Java 8 forEach Method
- Different Ways to Iterate over a List in Java [Snippet]
- Different Ways to Iterate over a Set in Java [Snippet]
- Different Ways to Iterate over a Map in Java [Snippet]
- Iterate over TreeSet in Java Example
- erate over LinkedHashSet in Java Example
- remove First and Last Elements of LinkedList in Java
- Iterate over LinkedList using an Iterator in Java
- Search an Element in an ArrayList in Java
- Iterate over ArrayList using Iterator in Java
- Remove Element from HashSet in Java
- Iterating over a HashSet using Iterator
-
Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
-
Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。
-
List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> 。
- HashSet和HashMap的负载因子
- 集合实用类 Collections
- 线程安全的集合
- 集合与数组的互换
- 集合的批量操作
- 历史集合类
- 枚举类型
- 枚举类型的构造方法
- EnumSet类和EnumMap类
- hashcode
- 一致性哈希算法