`

JDK list简单解析

    博客分类:
  • java
阅读更多

jdk中list接口继承与collection(放置一组元素的容器,为set与list的父类接口),iterable

list中使用比较多为arraylist,vector,linkedlist,stack(其实没有注意到stack是基于vector实现的),,前面均为abstarctlist的继承实现,后者copyonwritearraylist为list,RandomAccess,cloneable,seriaizable(用于实现以复制方式保证的线程安全),接下来简略,简单的叙述一下各个数据类型怎么实现的,主要从基本数据类型和其中构建的算法
 
1.abstractlist,这个抽象类,首先一如既往的基本实现了list接口的方法,没有什么大的表现
2.Arraylist内部存储数据使用数组形式,内部支持容器操作,排序(因为是数组存储,内部装换成Array,其实就是对array数组进行操作,具体要参考Array的源码),即具有数组特性的list.其他诸如扩容(2倍),添加,删除与map类似,不再阐述
针对几个操作复制,排序
在内部中实际进行操作的Array类,对Objetc[]进行管理,比如mao.toarray操作中实际上是把object[]导入到Array中调用toarray()方法,而在Array类中调用实际处理的是system.arraycopy(native方法)效率非常高,也就是说将list转换成数组(实际上重新复制创建的新数组,并不是返回list内部保存的object[]引用)
 
  private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
 
  public static long[] copyOf(long[] original, int newLength) {
        long[] copy = new long[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
 
  public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);
至于排序实现:在内部中Array.sort,其中自然用到了compator接口已经实现,但是arraylist是不能显示调用sort进行排序,所以需要实现导出array,来进行排序,或者使用collections根据对arraylist进行排序,返回结果依旧正确,网上有许多示例资料,前提是arraylist元素要实现compator接口,这种方式通常是实现自定义的排序方式,不然进行装饰操作的sort没有能力进行计算比较
A.Array.sort(arraylist.toarray())调用native sort进行默认排序
B.collections.sort(list<T entends Comparable>)进行自定义排序(也支持默认排序,两种方式其实都使用了Array,但是没有第一种方便)
 
3.Vector存储元素为Object[] elementData,扩容方式是(1+factor)*capacity,随机访问速度快,实现线程安全的方式是同步机制synchronized,大体的实现和方法类别基本与arraylist差不多,其注意事项有如下(来源于jdk api),其中出现的迭代器快速失败需要非常注意,导致的原因为修改了原来的存储数据的数据结构,比如追加元素;其中有些数据类型,在取数据的时候也会修改数据类型,归于内部实现不一样,比如LinkedHashMap.get(),queue,stack就不可以在出现在迭代器模式下。

Vector 类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。

每个向量会试图通过维护 capacity  capacityIncrement 来优化存储管理。capacity 始终至少应与向量的大小相等;这个值通常比后者大些,因为随着将组件添加到向量中,其存储将按 capacityIncrement 的大小增加存储块。应用程序可以在插入大量组件前增加向量的容量;这样就减少了增加的重分配的量。

由 Vector 的 iterator 和 listIterator 方法所返回的迭代器是快速失败的:如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代器自身的 remove 或 add 方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生不确定行为的风险。Vector 的 elements 方法返回的 Enumeration 不是 快速失败的。 

​4.LinkedList的描叙(jdk api),双向链表的构造(#1),以及对单个节点的实现处理(#2),从中可以看出具有高速度连续访问获取数据的优势,但是随即访问速度没有arraylist高效,此类实现 Deque 接口(本身取数据节点和增加数据节点就已经修改了原来的数据结构,没有类似于get()的读取数据但不修改数据结构),为 addpoll 提供先进先出队列操作,以及其他堆栈和双端队列操作。但是类似于toarray可以通过循环返回其object[]数组,至于linkedlist是双向列表,怎么进行get()?从#3可以得出应该是对index作为循环次数从first开始追寻

AbstractSequentialList:此类提供了 List 接口的骨干实现,从而最大限度地减少了实现受“连续访问”数据存储(如链接列表)支持的此接口所需的工作。对于随机访问数据(如数组),应该优先使用 AbstractList,而不是先使用此类,从某种意义上说,此类与在列表的列表迭代器上实现“随机访问”方法(get(int index)set(int index, E element)add(int index, E element)  remove(int index))的AbstractList 类相对立,而不是其他关系。

#1  transient Node<Efirst;
    /**
     * Pointer to last node.
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last;
#2  private static class Node<E> {//明显是有前驱和后驱节点,以及相应的属性值,所以从可以看出linkedlist是至少具备双向链表的特性(双向链表具体请自修C)
        E item;
        Node<E> next;
        Node<E> prev;
        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }

    }

#3 
   public E get(int index) {
        try {
            return listIterator(index).next();
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }
    /**
     * Returns the (non-null) Node at the specified element index.
     */
    Node<E> node(int index) {
        // assert isElementIndex(index);
        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }
 
5.Stack栈,顾名思义,先进后出的特性,基于vector实现,线程安全,按照JDK API的说法,是通过5个操作类对vector进行扩展得到的
允许将向量视为堆栈。它提供了通常的 push  pop 操作,以及取堆栈顶点的 peek 方法、测试堆栈是否为空的 empty 方法、在堆栈中查找项并确定到堆栈顶距离的 search 方法。 
如下:
  public E push(E item) {//入栈
        addElement(item);
        return item;
    }
 public synchronized E pop() {//出栈
        E       obj;
        int     len = size();
        obj = peek();
        removeElementAt(len - 1);
        return obj;
    }
 
 public synchronized E peek() {//检测栈顶部元素并返回,但不移除
        int     len = size();
        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
    }
 
   public boolean empty() {
        return size() == 0;
    }
  public synchronized int search(Object o) {//查找堆栈中对象序号
        int i = lastIndexOf(o);
        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }
 
6.CopyOnwriteArrayList摘自jdk API,内部操作读取和增加通过vector的synchronized同步控制,至于数组的复制是使用ReentranLock进行控制

ArrayList的一个线程安全的变体,其中所有可变操作(addset 等等)都是通过对底层数组进行一次新的复制来实现的,但并不是通过继承来实现的,却继承了abstractlist,。这一般需要很大的开销,但是当遍历操作的数量大大超过可变操作的数量时,这种方法可能比其他替代方法 有效。在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时,它也很有用。“快照”风格的迭代器方法在创建迭代器时使用了对数组状态的引用。此数组在迭代器的生存期内不会更改,因此不可能发生冲突,并且迭代器保证不会抛出 ConcurrentModificationException。创建迭代器以后,迭代器就不会反映列表的添加、移除或者更改。在迭代器上进行的元素更改操作(removeset  add)不受支持。这些方法将抛出 UnsupportedOperationException

分享到:
评论

相关推荐

    jdk类库详细解析再也找不到更详细的了

    本篇文档将深入解析JDK类库,为初学者提供详尽的指导。 一、基础类库 1. **java.lang**:这是所有Java程序的基础包,包含了一些最基础的类,如String、Object和System。String类用于处理文本,Object是所有类的...

    JDK1.8:JDK1.8源码解析-源码解析

    在深入探讨JDK1.8源码解析之前,先理解一下JDK的含义:Java Development Kit,即Java开发工具包,是Java编程语言的核心组成部分,提供了编写、编译和运行Java应用程序所需的所有工具。JDK1.8是Oracle公司发布的Java ...

    JDK1.8源码,亲测好用。

    **核心组件解析** - **com**: 包含Java标准库的类,如集合框架、网络编程、I/O操作等。 - **org**: 主要包含开源组织提供的类库,例如Apache、JUnit等。 - **launcher**: Java应用程序启动器,负责加载JVM并执行...

    jdk1.8-src

    《深入解析JDK1.8源码》 JDK1.8是Java开发的一个重要版本,它引入了许多新的特性和优化,对开发者来说,理解其源码有助于提升编程技巧和解决问题的能力。本篇将深入探讨JDK1.8源码中的关键知识点。 一、Lambda...

    jdk1.8.0_144.zip

    《深入解析JDK 1.8.0_144》 JDK 1.8.0_144是Java Development Kit的一个重要版本,它在Java 8的基础上进行了若干改进和更新,对于开发者来说,了解这个版本的特性和变化至关重要。本文将详细探讨这个版本中的关键...

    jdk 1.8.chm

    《深入解析Java SDK 1.8 API》 Java Development Kit(JDK)1.8是Java编程语言的一个重要版本,其API(Application Programming Interface)包含了丰富的类库,为开发者提供了强大的功能支持。本篇将围绕"jdk 1.8 ...

    jdk1.8中文文档.rar

    本篇将深入解析JDK 1.8的API中文文档,帮助开发者更好地理解和使用这个版本。 一、新特性解析 1. Lambda表达式:JDK 1.8引入了lambda表达式,这是一种简洁的匿名函数表示方式,使得代码更简洁、可读性更强,尤其在...

    jdk6_api文档 中文版

    《深入解析JDK6 API中文版》 JDK(Java Development Kit)是Oracle公司发布的用于开发Java应用程序的软件包,其中包含了Java运行环境、编译器、类库以及各种工具。JDK6作为Java发展历程中的一个重要版本,为开发者...

    jdk_api chinese

    ### 示例:使用JDK API创建简单的文本文件 ```java import java.io.FileWriter; import java.io.IOException; public class CreateFileExample { public static void main(String[] args) { String fileName = ...

    jdk1.8.0_171.zip

    《深入解析JDK 1.8.0_171在32位Windows系统中的应用》 JDK(Java Development Kit)是Oracle公司提供的用于开发和运行Java应用程序的软件工具包,而JDK 1.8.0_171是Java 8的一个重要更新版本。这个版本对开发者来说...

    jdk1.1源代码

    `java.util`包则包含`ArrayList`和`Vector`等早期的容器类,它们是现代`List`接口的前身。 2. **事件模型** JDK1.1引入了AWT(Abstract Window Toolkit)作为Java的第一个图形用户界面库,其中包含组件、布局管理...

    Jdk1.6 Collections Framework源码解析(2)-LinkedList

    《Jdk1.6 Collections Framework源码解析(2)-LinkedList》 LinkedList是Java集合框架中的一个重要的类,它是List接口的实现,同时继承了AbstractSequentialList,并实现了Deque接口。LinkedList是一种双链表结构,...

    jdk-9_doc-api-google.zip

    本篇将基于"jdk-9_doc-api-google.zip"压缩包中的中文文档,深入解析JDK 9 API的主要内容。 首先,"jdk-9_doc-api-google.CHM"是一个包含中英对照的CHM(Compiled HTML Help)文件,这种格式便于离线浏览和搜索。...

    JAVA解析JSON数据

    在Java编程中,JSON(JavaScript ...总的来说,Java借助第三方库如Jackson,可以轻松地解析和处理JSON数据,使得在Web开发中传递和存储数据变得简单高效。通过熟练掌握这些技能,你可以在各种场景下有效地使用JSON。

    jdk1.6的src文件

    本文将围绕"jdk1.6的src文件"这一主题,解析其中的关键组件和设计理念。 首先,源码文件(src)是Java语言的灵魂所在,它是开发者与Java API进行沟通的桥梁。通过查看源码,我们可以看到类的定义、方法实现以及内部...

    jdk6-jdk7两个版本.zip

    5. **改进的XML处理**:增强了StAX(Streaming API for XML)和DOM解析器的性能。 6. **JDBC 4.0**:更新了数据库连接驱动的自动发现机制,简化了数据库连接的管理。 JDK 7,又称Java SE 7,于2011年发布,是Java...

    java/jdk API 文档

    1. **核心类库**:包括基础类如`Object`,集合框架如`List`、`Set`、`Map`,IO流,网络编程,多线程,异常处理等。例如,`java.lang`包提供了所有Java程序的基础类,如`String`、`Integer`等;`java.util`包提供了...

    JDK1.8.0_101

    《深入解析JDK1.8.0_101:Java 8的革命性变革》 Java 8,官方命名为Java Development Kit (JDK) 1.8.0_101,是Oracle公司发布的一个重要更新,它在Java编程语言的发展历程中具有里程碑式的意义。自2004年Java 5发布...

    jdk api 1.8 中文版

    本文将详细解析JDK 1.8的中文版API,帮助开发者更好地理解和应用这些工具。 一、Lambda表达式 JDK 1.8最大的亮点之一就是引入了Lambda表达式,它简化了函数式编程,使得处理集合操作变得更加简洁。Lambda表达式是...

    jdk1.8 中文开发手册

    **标题与描述解析** 标题"jdk1.8 中文开发手册"表明这是一份针对Java开发者的重要参考资料,主要涵盖Java Development Kit(JDK)的1.8版本,且该手册以中文呈现,方便中文读者理解。 描述同样为"jdk1.8 中文开发...

Global site tag (gtag.js) - Google Analytics