Java容器类库的用途是保存对象,根据数据结构不同将其划分为两个不同的概念
(1) Collection,一个独立元素的序列,其中List按照元素的插入顺序保存元素,而set不能有重复元素,Queue按照先进先出(FIFO)的方式来管理数据,Stack按照后进先出(LIFO)的顺序管理数据。
(2) Map,一组键值对(key-value)对象的序列,可以使用key来查找value,其中key是不可以重复的,value可以重复。我们可以称其为字典或者关联数组。其中HashMap是无序的,TreeMap是有序的,WeakHashMap是弱类型的,Hashtable是线程安全的。
下面这张图来自于Thinking in Java Fourth Edition第十七章:
除上面图中画到的内容外在java.util.concurrent包中也实现了大量的线程安全的集合类,可以很方便的使用。如ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet等。
二.Collection接口
Ø 由集合类图结构可以得知Collection接口是Java语言中最基本的集合接口,在JDK中没有直接提供Collection接口的具体实现类,Collection的功能实现类主要是对它的两个更具体的子接口List和Set的具体实现类。但是在Collection接口中定义了一套通用操作的实现方法和命名规则。
Ø 在JDK帮助文档中可以看到Collection接口以及各个子接口、各种形式实现类的说明。
Ø 对Collection接口的实现类构造方法一般至少有下面两种:一个是void(无参数)构造方法,用于创建空的Collection对象实例;另一个是带有一个Collection类型参数的构造方法,用于创建一个具有与其参数相同元素的Collection对象实例。例如HashSet类的构造方法有下面四种:
a) HashSet():构造一个初始容量为16、加载因子为0.75的HashSet类的实例对象;
b) HashSet(Collection<? extends E> c):构造一个包含指定集合对象的HashSet类的对象实例。
c) HashSet(int initialCapacity):构造一个指定初始容量的HashSet类的实例对象。
d) HashSet(int initialCapacity, float loadFactor):构造一个指定初始容量以及指定加载因子的HashSet类的实例对象。
Ø Collection接口中共定义了15个通用的方法:
a) Collection接口方法清单
1. List接口及其实现类
List接口中方法清单
List可以将元素维护在特定的序列中,并且允许一个相同元素在集合中多次出现。List接口在Collection接口的基础上增加了大量的方法,使得可以在List中间插入和移除元素。除了Abstract类之外,在学习中比较常用的类有ArrayList(基于数组实现),LinkedList(基于循环链表实现),Vector(基于数组实现,线程安全),Stack(是Vector的子类,基于数组实现),CopyOnWriteArrayList(基于数组实现,线程安全)
List接口中提供的面向位置操作的各种方法:(集合中已有的方法略去)
• void add(int index, E element) : 在列表的指定位置插入指定元素。
• boolean addAll(int index, Collection<? extends E> c) : 将指定集合中的所有元素插入到集合中的指定位置。
• E get(int index) : 返回集合中指定位置的元素。
• int indexOf(Object o) : 返回指定对象在集合中第一次出现的索引,从0位置开始,返回-1为不存在该元素。
• int lastIndexOf(Object O) : 返回指定对象在集合中最后一次出现的索引位置,返回-1为不存在。
• ListIterator<E> listIterator() : 以正确的顺序返回集合中元素的列表迭代器。
• ListIterator<E> listIterator(int index) : 以正确的顺序返回集合中元素的列表迭代器,从集合中指定的位置开始。
• E remove(int index) : 移除集合中指定位置的元素。
• E set(int index, E element) : 用指定元素替换集合中指定位置的元素。
• List<E> subList(int fromIndex, int toIndex) : 返回集合中指定的fromIndex(包括)和toIndex(不包括)之间的部分视图。
List接口提供了名称为ListIterator的特殊迭代器。
List在数据结构中分别表现为数组、向量、链表、堆栈、队列等形式。
Ø ArrayList的特点、实现机制及使用方法
a) ArrayList特点:
ArrayList顾名思义,它是用数组实现的一种线性表。常规数组不具备自动递增的功能,但是ArrayList在使用时我们不必考虑这个问题。可以直接按位置进行索引,查找和修改速度较快,缺点是插入或者删除速度较慢。在执行插入删除时调用的是System.arraycopy方法,是一个native方法。
b) ArrayList的实现机制:
在JDK源码中可以看到ArrayList总共只有两个属性,一个是Object数组类型的elementData,一个是int型的size。
在构造方法中也可以看到,无参构造方法调用的是this(10),调用的带一个参数的构造方法,默认无参构造方法分配一个size为10的数组。按照Collection接口中定义的构造方法,它必须有一个通过其它集合对象构造自身对象的方法。这是一个相对比较简单的线性表。并且JDK中提供了大量的比较好用的方法可以使用。该动态数组在存储空间不足时按照下面方法重新分配空间:
newCapacity = (oldCapacity*3)/2 + 1;
if(newCapacity < minCapacity) newCapacity = minCapacity;
c) 使用方法(ArrayList的使用方法其实是比较简单,但是也是比较常用和好用的,个人感觉)
下面例子为了尽可能多的用到ArrayList的方法,可能看起来没有多大意义
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- public class ExampleForArrayList {
- public static void main(String[] args) {
- String[] str = new String[]{"My", "name", "is", "Wang", "Yan", "tao"};
- List<String> ls1 = new ArrayList<String>(10);
- //把数组中的数据添加到ls1中
- for(int i=0; i<str.length; i++) {
- ls1.add(str[i]);
- }
- //使用ls1来构造ls2
- List<String> ls2 = new ArrayList<String>(ls1);
- System.out.println("ls2中元素的个数:" + ls2.size());
- System.out.println("is在ls2中的位置:" + ls2.indexOf("is"));
- System.out.println("Wang在ls2中最后一次出现的位置:" + ls2.lastIndexOf("Wang"));
- System.out.println("ls2中的所有元素:");
- //这里使用iterator遍历
- Iterator<String> it = ls2.listIterator();
- while(it.hasNext()) {
- System.out.println(it.next());
- }
- //我一般使用下面方法遍历,或者基本的for循环遍历
- for(String tmp : ls2) {
- System.out.println(tmp);
- }
- }
- }
a) LinkedList的特点:
现在发现java中类的命名真是太好了,比如这个吧,一看就知道它使用链表实现的。链表操作的优点就是插入删除比较快,但是不能按索引直接存取,所以执行更新操作比较快,执行查询操作比较慢。它的整体特性由于ArrayList。
b) LinkedList实现机制:
查看jdk源码可以得知每个元素在LinkedList中都是一个LinkedList.Entry的实例对象。该类定义如下:
- private static class Entry<E> {
- E element;
- Entry<E> next;
- Entry<E> previous;
- Entry(E element, Entry<E> next, Entry<E> previous) {
- this.element = element;
- this.next = next;
- this.previous = previous;
- }
- }
在构造方法中这样的定义:
header.next = header.previous = header;
也就是说LinkedList底层使用一个循环双向链表实现的。
LinkedList实现了许多对first和last元素进行操作的方法,比如set、get、remove等。
虽然LinkedList获取指定位置的元素时较ArrayList按索引获取较慢,但是JDK中对get方法做了优化:
- if (index < (size >> 1)) {
- for (int i = 0; i <= index; i++)
- e = e.next;
- } else {
- for (int i = size; i > index; i--)
- e = e.previous;
- }
虽然还是顺序挨个查找,但是已经做了优化。size>>1 == size/2,移位运算要比除法运算效率高的多。
c) LinkedList和ArrayList的使用方法类似,只是看自己的需要进行选择了。除此之外LinkedList还实现了栈操作的所有方法。
Ø Vector的特点、实现机制及使用方法
a) Vector的特点:
ArrayList实现的是一种动态数组,LinkedList是一种双向循环链表,Vector并未在前两者的基础上做实现,而是直接实现了List接口。Vector中的所有方法前面都有一个synchronized关键字做修饰。Vector是有序可重复的。
b) Vector的实现机制:
我暂时还不理解为什么要实现Vector这个类,和ArrayList基本是一样的,不一样的是Vector是线程安全的,但是Collections里面提供了将非线程安全的集合转换成线程安全的集合的方法。
c) Vector的使用方法(与ArrayList使用方法类似)
Ø Stack的特点、实现机制及使用方法
a) Stack的特点:
Stack(栈)是一种后进先出的序列,主要操作有判空、压栈、退栈、取栈顶元素等。
b) Stack的实现机制:
Stack继承自Vector,同样使用数组保存数据,根据该数据结构的特点进行了限制性操作。JDK中共提供了6个方法用于实现特定要求的操作:
• Stack() : 构造一个空的栈
• empty() : 判断栈是否为空
• peek() : 查看栈顶元素并返回栈顶对象
• pop() : 删除栈顶元素并返回栈顶对象
• push(E element) : 将一个元素压入当前栈中
• search(Object o) : 查看指定对象是否在当前栈中
c) Stack的使用方法
- import java.util.Stack;
- public class ExampleForStack {
- /*
- * 这是一个非常简单的例子
- * 用于展现栈的这种后进先出的特性
- * 逆序打印一个字符串
- */
- public static void main(String[] args) {
- String str = "abcdefghijklmnopqrstuvwxyz";
- Stack<Character> stack = new Stack<Character>();
- for(char ch : str.toCharArray()) {
- stack.push(ch);
- }
- while(!stack.empty()) {
- System.out.print(stack.pop());
- }
- }
- }
Ø CopyOnWriteArrayList的特点、实现机制及使用方法
a) CopyOnWriteArrayList的特点:
CopyOnWriteArrayList是java.util.concurrent包中的一个类,此类是一个线程安全类。由于用到了ReentrantLock(重入锁)同步,所以在修改效率上较ArrayList差。
b) CopyOnWriteArrayList的实现机制:
刚开始觉得这个名字好长,并且感觉奇怪,为什么要这样命名?首先这是一个为了实现并发同步而设计的类,那么在所有与修改方法相关的地方均会使用lock来保证同步。Copy-on-write的英文释义是“写时拷贝、写时复制”,现在看来觉得这个名字就更容易理解了,那么这个类到底是怎么实现的呢?面试官说:“踏踏实实看源码”。-_-|||
首先说一下写方法:
• public E set(int index, E element) : 将指定位置的元素使用element替换掉。JDK中的源码如下:
- public E set(int index, E element) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- Object[] elements = getArray();
- Object oldValue = elements[index];
- if (oldValue != element) {
- int len = elements.length;
- Object[] newElements = Arrays.copyOf(elements, len);
- newElements[index] = element;
- setArray(newElements);
- } else {
- setArray(elements);
- }
- return (E)oldValue;
- } finally {
- lock.unlock();
- }
- }
在源码中可以看出,首先执行写入(包括set,add,remove等)操作时,首先得到一把当前对象的重入锁,其次获得当前对象元素的一个拷贝(写时拷贝),再次用修改后的元素替换掉原来的元素,最终释放锁。
这里引用两个常识:
1、JAVA中“=”操作只是将引用和某个对象关联,假如同时有一个线程将引用指向另外一个对象,一个线程获取这个引用指向的对象,那么他们之间不会发生ConcurrentModificationException,他们是在虚拟机层面阻塞的,而且速度非常快,几乎不需要CPU时间。
2、JAVA中两个不同的引用指向同一个对象,当第一个引用指向另外一个对象时,第二个引用还将保持原来的对象。
• public void add(E e) : 向当前对象中加入指定元素。实现方式与set相同,均是copy-on-write。
• 还有remove等修改内容的操作。
除写方法(修改,删除,添加)外,CopyOnWriteArrayList类还提供了ArrayList相类似和功能更齐全的方法供选择使用。
• public ListIterator<E> listIterator() : 该方法返回一个ListIterator类型的迭代器,但是该迭代器的真正类型是COWIterator类型的,不允许有插入、删除、添加等方法。
使用方法与ArrayList类似,只是用时选择的问题。因为在写操作时大量使用了System.arrayCopy方法,所以在效率上会有所降低。因此它适合使用在读操作远远大于写操作的场景中。
相关推荐
集合框架001-Collection接口1-3”将深入探讨这一核心概念,旨在帮助开发者更好地理解和运用这个强大的工具。 首先,我们来看Collection接口,它是Java集合框架的顶级接口,位于java.util包下。Collection接口定义了...
集合框架001-Collection接口13-16",通过四个视频文件来深入学习这个关键接口及其相关概念。 首先,我们来看标题中提到的"Collection接口"。它是Java集合框架的顶级接口,位于`java.util`包下。所有的集合类,无论...
集合框架001-Collection接口4-5”,聚焦于Collection接口及其相关的泛型概念。Collection接口是所有集合类的根接口,它定义了集合的基本操作,如添加、删除、遍历元素等。 1. **Collection接口**:它是Java集合框架...
#### 11-2 Collection接口 **Collection接口**作为Java集合框架的基础部分,在Java编程中扮演着非常重要的角色。它定义了一系列用于处理或操作集合中元素的方法,是所有集合类的根接口。 ### 11.2 Collection接口...
集合框架001-Collection接口10-12"的主题聚焦于Collection接口及其相关的概念,这包括链表、Vector和Stack的深入分析。下面将详细阐述这些知识点。 **Collection接口**: Collection是Java集合框架中最基础的接口,...
集合框架001-Collection接口6-9"中涉及的关键知识点,包括`Collection`接口、`ArrayList`源码分析、`Comparator`接口以及`Comparable`接口,以及`Arrays`类中的算法。 首先,`Collection`接口是Java集合框架的根...
下面将详细解析`Collection`接口以及与其相关的知识点。 首先,我们来谈谈`Collection`接口。它是`java.util`包下的一个接口,定义了集合的基本操作,如添加元素、删除元素、判断是否包含特定元素等。`Collection`...
Collection集合类继承结构图向我们展示了Collection接口与其他接口和类之间的关系。 在Java集合框架中,Collection接口位于顶层,它直接继承自Iterable接口。Iterable接口允许对象成为“for-each”循环的目标,它...
Java基础知识-day02【Collection、泛型】 本节课程主要讲解了 Java 中的 Collection 框架和泛型,涵盖了 Collection 的基本概念、Collection 框架的继承结构、Collection 的常用功能、迭代器的使用和泛型的定义等...
以上只是Java集合框架中Collection接口及其相关子接口和实现类的基础知识。在实际开发中,我们需要根据具体需求选择合适的集合类型,合理利用其特性,优化代码性能。通过实例练习,可以更好地理解和掌握这些概念。...
在这个Java集合类的学习资料中,我们将深入探讨`Collection`以及与其相关的`TreeMap`、`Set`和`List`等概念。 首先,我们从`Collection`接口开始。`Collection`接口是`java.util`包下的核心接口,它定义了集合的...
不过,从描述和标签中的“源码 工具”可以推测,作者可能在讨论Java中的集合框架,包括Collection接口、List、Set以及Map接口,这是Java开发中经常讨论的集合类型。 在Java编程中,Collection、List、Set和Map是...
### Java Collection Framework 相关知识点 #### 一、引言 在 Java 领域,《Java Collection Framework》这本书被广泛认为是一本优秀的教程,尤其适合初学者了解集合框架的前世今生。通过本书的学习,读者不仅能...
Collection接口定义了存储和操作一组对象的基本方法,如添加元素(add)、删除元素(remove)、检查是否包含特定元素(contains)、获取元素数量(size)等。它是所有集合类的父接口,提供了一个统一的接口来处理不同类型的...
2. **用户相关接口.postman_collection.json**: 这个集合可能包含了与用户管理相关的API,如注册、登录、修改用户信息、找回密码等操作。这些接口通常涉及身份验证、授权和用户数据的安全存储,使用HTTP请求方法如...
下面我们将详细探讨这些接口的区别及其相关知识点。 首先,`Collection`是所有集合类的顶级接口,它是其他集合接口(如`List`和`Set`)的父接口。`Collection`接口定义了基本的添加、删除、查询元素的方法,如`add...
- Collection接口的两个重要的子接口是List和Set。 - **List**:有序集合,允许存储重复元素,可以通过索引来访问元素。常用实现类有ArrayList和LinkedList。 - **Set**:不允许存储重复元素,常见实现类有...
1. **Collection接口**:Collection是Java集合框架的顶级接口,它定义了集合的基本操作,如添加、删除、判断元素等。其子接口主要有List和Set。 - List接口:特点是元素有序且可重复,允许索引访问,例如ArrayList...
#### Collection接口详解 `Collection`接口是Java集合框架中最基本的接口之一,它提供了存储、检索、修改以及操作元素集合的基本方法。以下列举了`Collection`接口中定义的一些关键方法: 1. **添加方法**: - `...