`

Collection接口相关知识

    博客分类:
  • Java
 
阅读更多

一.基本概念

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的方法,可能看起来没有多大意义

[java] view plaincopy
 
  1. import java.util.ArrayList;  
  2. import java.util.Iterator;  
  3. import java.util.List;  
  4. public class ExampleForArrayList {  
  5.     public static void main(String[] args) {  
  6.         String[] str = new String[]{"My""name""is""Wang""Yan""tao"};  
  7.         List<String> ls1 = new ArrayList<String>(10);  
  8.         //把数组中的数据添加到ls1中  
  9.         for(int i=0; i<str.length; i++) {  
  10.             ls1.add(str[i]);  
  11.         }  
  12.         //使用ls1来构造ls2  
  13.         List<String> ls2 = new ArrayList<String>(ls1);  
  14.         System.out.println("ls2中元素的个数:" + ls2.size());  
  15.         System.out.println("is在ls2中的位置:" + ls2.indexOf("is"));  
  16.         System.out.println("Wang在ls2中最后一次出现的位置:" + ls2.lastIndexOf("Wang"));  
  17.         System.out.println("ls2中的所有元素:");  
  18.         //这里使用iterator遍历  
  19.         Iterator<String> it = ls2.listIterator();  
  20.         while(it.hasNext()) {  
  21.             System.out.println(it.next());  
  22.         }  
  23.         //我一般使用下面方法遍历,或者基本的for循环遍历  
  24.         for(String tmp : ls2) {  
  25.             System.out.println(tmp);  
  26.         }  
  27.     }  
  28. }  

Ø  LinkedList的特点、实现机制及使用方法

a)      LinkedList的特点:

现在发现java中类的命名真是太好了,比如这个吧,一看就知道它使用链表实现的。链表操作的优点就是插入删除比较快,但是不能按索引直接存取,所以执行更新操作比较快,执行查询操作比较慢。它的整体特性由于ArrayList。

b)      LinkedList实现机制:

查看jdk源码可以得知每个元素在LinkedList中都是一个LinkedList.Entry的实例对象。该类定义如下:

[java] view plaincopy
 
  1. private static class Entry<E> {  
  2.     E element;  
  3.     Entry<E> next;  
  4.     Entry<E> previous;  
  5.     Entry(E element, Entry<E> next, Entry<E> previous) {  
  6.         this.element = element;  
  7.         this.next = next;  
  8.         this.previous = previous;  
  9.     }  
  10. }  

在构造方法中这样的定义:

           header.next = header.previous = header;

              也就是说LinkedList底层使用一个循环双向链表实现的。

LinkedList实现了许多对first和last元素进行操作的方法,比如set、get、remove等。

虽然LinkedList获取指定位置的元素时较ArrayList按索引获取较慢,但是JDK中对get方法做了优化:

[java] view plaincopy
 
  1. if (index < (size >> 1)) {  
  2.      for (int i = 0; i <= index; i++)  
  3.          e = e.next;  
  4. else {  
  5.      for (int i = size; i > index; i--)  
  6.          e = e.previous;  
  7. }  

虽然还是顺序挨个查找,但是已经做了优化。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的使用方法

[java] view plaincopy
 
  1. import java.util.Stack;  
  2. public class ExampleForStack {  
  3.     /* 
  4.      * 这是一个非常简单的例子 
  5.      * 用于展现栈的这种后进先出的特性 
  6.      * 逆序打印一个字符串 
  7.      */  
  8.     public static void main(String[] args) {  
  9.         String str = "abcdefghijklmnopqrstuvwxyz";  
  10.         Stack<Character> stack = new Stack<Character>();  
  11.         for(char ch : str.toCharArray()) {  
  12.             stack.push(ch);  
  13.         }  
  14.         while(!stack.empty()) {  
  15.             System.out.print(stack.pop());  
  16.         }  
  17.     }  
  18. }  

Ø  CopyOnWriteArrayList的特点、实现机制及使用方法

a)      CopyOnWriteArrayList的特点:

CopyOnWriteArrayList是java.util.concurrent包中的一个类,此类是一个线程安全类。由于用到了ReentrantLock(重入锁)同步,所以在修改效率上较ArrayList差。

b)      CopyOnWriteArrayList的实现机制:

刚开始觉得这个名字好长,并且感觉奇怪,为什么要这样命名?首先这是一个为了实现并发同步而设计的类,那么在所有与修改方法相关的地方均会使用lock来保证同步。Copy-on-write的英文释义是“写时拷贝、写时复制”,现在看来觉得这个名字就更容易理解了,那么这个类到底是怎么实现的呢?面试官说:“踏踏实实看源码”。-_-|||

首先说一下写方法:

•           public E set(int index, E element) : 将指定位置的元素使用element替换掉。JDK中的源码如下:

[java] view plaincopy
 
  1. public E set(int index, E element) {  
  2.     final ReentrantLock lock = this.lock;  
  3.     lock.lock();  
  4.     try {  
  5.         Object[] elements = getArray();  
  6.         Object oldValue = elements[index];  
  7.         if (oldValue != element) {  
  8.             int len = elements.length;  
  9.             Object[] newElements = Arrays.copyOf(elements, len);  
  10.             newElements[index] = element;  
  11.             setArray(newElements);  
  12.         } else {  
  13.             setArray(elements);  
  14.         }  
  15.         return (E)oldValue;  
  16.     } finally {  
  17.         lock.unlock();  
  18.     }  
  19. }  

在源码中可以看出,首先执行写入(包括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方法,所以在效率上会有所降低。因此它适合使用在读操作远远大于写操作的场景中。

分享到:
评论

相关推荐

    11.集合框架001-Collection接口1-3

    集合框架001-Collection接口1-3”将深入探讨这一核心概念,旨在帮助开发者更好地理解和运用这个强大的工具。 首先,我们来看Collection接口,它是Java集合框架的顶级接口,位于java.util包下。Collection接口定义了...

    11.集合框架001-Collection接口13-16

    集合框架001-Collection接口13-16",通过四个视频文件来深入学习这个关键接口及其相关概念。 首先,我们来看标题中提到的"Collection接口"。它是Java集合框架的顶级接口,位于`java.util`包下。所有的集合类,无论...

    11.集合框架001-Collection接口4-5

    集合框架001-Collection接口4-5”,聚焦于Collection接口及其相关的泛型概念。Collection接口是所有集合类的根接口,它定义了集合的基本操作,如添加、删除、遍历元素等。 1. **Collection接口**:它是Java集合框架...

    Java软件开发实战 Java基础与案例开发详解 11-2 Collection接口 共9页.pdf

    #### 11-2 Collection接口 **Collection接口**作为Java集合框架的基础部分,在Java编程中扮演着非常重要的角色。它定义了一系列用于处理或操作集合中元素的方法,是所有集合类的根接口。 ### 11.2 Collection接口...

    11.集合框架001-Collection接口10-12

    集合框架001-Collection接口10-12"的主题聚焦于Collection接口及其相关的概念,这包括链表、Vector和Stack的深入分析。下面将详细阐述这些知识点。 **Collection接口**: Collection是Java集合框架中最基础的接口,...

    11.集合框架001-Collection接口6-9

    集合框架001-Collection接口6-9"中涉及的关键知识点,包括`Collection`接口、`ArrayList`源码分析、`Comparator`接口以及`Comparable`接口,以及`Arrays`类中的算法。 首先,`Collection`接口是Java集合框架的根...

    11.集合框架001-Collection接口17-19

    下面将详细解析`Collection`接口以及与其相关的知识点。 首先,我们来谈谈`Collection`接口。它是`java.util`包下的一个接口,定义了集合的基本操作,如添加元素、删除元素、判断是否包含特定元素等。`Collection`...

    Collection集合继承结构图.pdf

    Collection集合类继承结构图向我们展示了Collection接口与其他接口和类之间的关系。 在Java集合框架中,Collection接口位于顶层,它直接继承自Iterable接口。Iterable接口允许对象成为“for-each”循环的目标,它...

    Java基础知识-day02【Collection、泛型】.pdf

    Java基础知识-day02【Collection、泛型】 本节课程主要讲解了 Java 中的 Collection 框架和泛型,涵盖了 Collection 的基本概念、Collection 框架的继承结构、Collection 的常用功能、迭代器的使用和泛型的定义等...

    java集合Collection总结

    以上只是Java集合框架中Collection接口及其相关子接口和实现类的基础知识。在实际开发中,我们需要根据具体需求选择合适的集合类型,合理利用其特性,优化代码性能。通过实例练习,可以更好地理解和掌握这些概念。...

    Java集合类(Collection)学习

    在这个Java集合类的学习资料中,我们将深入探讨`Collection`以及与其相关的`TreeMap`、`Set`和`List`等概念。 首先,我们从`Collection`接口开始。`Collection`接口是`java.util`包下的核心接口,它定义了集合的...

    collection,list,set,map

    不过,从描述和标签中的“源码 工具”可以推测,作者可能在讨论Java中的集合框架,包括Collection接口、List、Set以及Map接口,这是Java开发中经常讨论的集合类型。 在Java编程中,Collection、List、Set和Map是...

    java collection framework

    ### Java Collection Framework 相关知识点 #### 一、引言 在 Java 领域,《Java Collection Framework》这本书被广泛认为是一本优秀的教程,尤其适合初学者了解集合框架的前世今生。通过本书的学习,读者不仅能...

    Collection使用

    Collection接口定义了存储和操作一组对象的基本方法,如添加元素(add)、删除元素(remove)、检查是否包含特定元素(contains)、获取元素数量(size)等。它是所有集合类的父接口,提供了一个统一的接口来处理不同类型的...

    接口文件,相关接口文件

    2. **用户相关接口.postman_collection.json**: 这个集合可能包含了与用户管理相关的API,如注册、登录、修改用户信息、找回密码等操作。这些接口通常涉及身份验证、授权和用户数据的安全存储,使用HTTP请求方法如...

    Collection List Set Map 区别记忆

    下面我们将详细探讨这些接口的区别及其相关知识点。 首先,`Collection`是所有集合类的顶级接口,它是其他集合接口(如`List`和`Set`)的父接口。`Collection`接口定义了基本的添加、删除、查询元素的方法,如`add...

    day03-常用API&异常&Collection;.pdf

    - Collection接口的两个重要的子接口是List和Set。 - **List**:有序集合,允许存储重复元素,可以通过索引来访问元素。常用实现类有ArrayList和LinkedList。 - **Set**:不允许存储重复元素,常见实现类有...

    Collection集合基本练习1

    1. **Collection接口**:Collection是Java集合框架的顶级接口,它定义了集合的基本操作,如添加、删除、判断元素等。其子接口主要有List和Set。 - List接口:特点是元素有序且可重复,允许索引访问,例如ArrayList...

    集合(Collection)文档

    #### Collection接口详解 `Collection`接口是Java集合框架中最基本的接口之一,它提供了存储、检索、修改以及操作元素集合的基本方法。以下列举了`Collection`接口中定义的一些关键方法: 1. **添加方法**: - `...

Global site tag (gtag.js) - Google Analytics