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()的读取数据但不修改数据结构),为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。但是类似于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<E> first;
/**
* 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的一个线程安全的变体,其中所有可变操作(add、set 等等)都是通过对底层数组进行一次新的复制来实现的,但并不是通过继承来实现的,却继承了abstractlist,。这一般需要很大的开销,但是当遍历操作的数量大大超过可变操作的数量时,这种方法可能比其他替代方法更 有效。在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时,它也很有用。“快照”风格的迭代器方法在创建迭代器时使用了对数组状态的引用。此数组在迭代器的生存期内不会更改,因此不可能发生冲突,并且迭代器保证不会抛出 ConcurrentModificationException。创建迭代器以后,迭代器就不会反映列表的添加、移除或者更改。在迭代器上进行的元素更改操作(remove、set 和 add)不受支持。这些方法将抛出 UnsupportedOperationException。
相关推荐
源码解析jdk7.0集合:LinkedList的底层实现原理.pdf
主要介绍了java 判断list是否为空过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
全部代码出自电子工业出版社夏先波的《Java JDK实例宝典》一书,本书以J2SE 5.0为开发环境,选取Java应用的典型实例,循序渐进地介绍了Java语言的各种开发方法和技巧,实例代码注释详细规范,思路清晰。 第1章 ...
java解析json字符串。 commons-beanutils-1.9.0 commons-collections-3.2.1 commons-lang-2.6 commons-logging-1.1.3 ezmorph-1.0.6 json-lib-2.4-jdk15 demo: package com; import java.util.ArrayList;...
该项目包含了项目所需要的jar包以及...项目使用环境为eclipse jdk1.8 1.com.webadmin.util.SHPFileReader为测试用例; 2.可读取shp文件坐标并返回list。 3.返回dbf数据,并解决乱码问题。 4.返回prj返回坐标系名称。
java为数据结构中的列表定义了一个接口类java.util.list同时提供了3个实现类,分别是ArrayList、Vector、LinkedList使用; 生成不重复的随机数序列;列表、集合与数组的互相转换;java为数据结构中的映射定义一个接口...
通过dom4j解析配置文件,得到list集合(存放Bean标签的id和class属性) * 3.通过反射实例化得到对应的实例化对象,放置在map中(map是键值对,可根据id获取值)(遍历list获取对应的class属性,利用class。formName...
List相关实现类的源码解析(JDK1.8) 2018.9.22- List的架构图 ArrayList 继承关系: ArrayList -> AbstractList 实现 List接口 ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态...
我们有必要对JDK 5.0新增的注解(Annotation)技术进行简单的学习,因为Spring 支持@AspectJ,而@AspectJ本身是基于JDK 5.0的注解技术。所以学习JDK 5.0的注解知识有助于我们更好地理解和掌握Spring的AOP技术。 ...
JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类? 17 69、文件读写的基本类 17 70、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 17 71、启动一个线程是用run()还是start()? ...
由于实习需要,需要通过ajax来获取后台的List集合里面的值。由于前面没有接触过,所以今天就来研究下了。 一、首先需要下载JSON依赖的jar包。它主要是依赖如下: json-lib-2.2.2-jdk15 ezmorph-1.0.4 commons-...
工具:jdk1.8+maven 知识点:反射+自定义注解+poi使用+使用了一点guava编程(膜拜下谷歌大哥) 功能:可以解析任意List对象-excel表格;解析任意的Excel的表格-》list对象 在 poi包里面
* JSON 时间解析器 * * @param datePattern * @return */ public static JsonConfig configJson(final String datePattern) { JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String...
JEzCSV是用于解析器文件CSV或创建文件CSV的lib Java 8,您可以通过Java库Liz JEzCSV.jar或 如果要直接使用lib,则需要更新jdk,或者可以使用代码源。 如何在您的项目中使用它: Download the JEzCSV.jar and add it ...
DWR有个专门用于解析上面配置语句的解析器,虽然上面的是JDK5中才有的特性,因为有解析器的原因这也可以应用与JDK5之前的版本. 解析规则是不可见的,但有两种例外情况. 一种情况是因为DWR1.0的解析器中有个Bug,在有些...
同时也易于机器解析和生成。它基于 JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999 的一个子集。 JSON 采用完全独立于语言的文本格式,但是也使用了类似于 C 语言家族的习惯...
目前使用的是第三方工具,不是原生的JDK 导入第三方Jar包 2. 设置IDEA 3. Dom4j涉及到的方法 SAXReader(); 解析XML文件使用的核心类 read() --> XML文件Document对象 Document document = new SAXReader...
leetcode题库 一份关于cs向的学习目录 学习目录包含 Java 计算机系统 网络 编码规范 数据库 算法 设计模式与面向对象(oo) 架构设计 [TDD和DDD] 网络安全 ...list JVM完善,jdk源码解析 设计模式,重构设计
也有分析认为,谷歌并不想做一个简单的手机终端制造商或者软件平台开发商,而意在一统传统互联网和 移 动互联网。----------------------------------- Android 编程基础 4 Android Android Android Android 手机新...
7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”advisor 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动代理...