ArrayList

这里关于ArrayList本来都读了一遍源码,并且写了一些了,突然在原来的笔记里面发现了收藏的有相关博客,大致看了一下,这些就是我要写的(╹▽╹),而且估计我还写不到博主的水平,这里直接将收藏的博客列出来:

  1. 从源码角度彻底搞懂ArrayList

    这篇博客的重要内容包括:
    1. ArrayList使用的数据结构;
2. ArrayList的增删改查实现方式和时间复杂度分析;
3. ArrayList的自动扩容机制;
4. ArrayList的随机访问特性;
5. ArrayList与垃圾回收(因为对元素是强引用,在删除元素或移动元素时,被删除/被移动的元素原来的位置需要手动置为null)
6. ArrayList的并发修改,fail-fast机制
7. ArrayList的浅复制
8. ArrayList的序列化和反序列化
  1. ArrayList遍历方式以及效率比较

    这篇博客的关键内容:
    1. 探讨不同遍历方式(foreach iterator for循环)的遍历效率差原因;
2. ArrayList的随机访问特性,并且和顺序访问的LinkedList进行效率比较;
  1. 面试题:Java中ArrayList循环遍历并删除元素的陷阱

    除了上面的博文内容外,这里做些无关痛痒的补充....:

    /**
* ArrayList本身没有同步,如果需要在并发情况下使用,可以通过Collections.synchronizedList(List)进行包装,实现同步;
* @since 1.2
*/
// 这个继承了AbstractList,但是还是实现了List接口,想了半天,实现List接口这一点完全可以去掉.....,没有什么实际意义
// ArrayList实现了RandomAccess接口,证明其具有随机访问
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { // 将当前list中的数组大小缩减到size,以节约空间
public void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (size < oldCapacity) {
elementData = Arrays.copyOf(elementData, size);
}
} ........ }

Vector

其实在jdk中,有一个与ArrayList实现非常相似,且在jdk1.0就已经存在的Vector类,我们来粗略看一下.

首先看一下Vector的类型定义

/**
* @since JDK1.0
*/
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable

Vector与ArrayList同样继承自AbstractList,实现相同的接口,那么其中必然有很多相同的方法,且仔细看,其中实现几乎全部都与ArrayList一致,这里不做多余分析

这里只对一些差异进行分析:

  1. 在jdk1.0,Vector的作者似乎很喜欢element这个单词:



    ArrayList中的size,在Vector中为elementCount,所有的增删改查方法都有以element开头或结尾的方法,如果去看其具体实现,和ArrayList中的相关增删改查方式没有什么区别;
  2. Vector的所有方法都加了锁(有些方法没有加锁,但是是被同步方法调用或内部调用同步方法实现),是线程安全的类;
  3. 除了添加的Iterator和ListIterator之外,Vector还有一个jdk1.0就存在的遍历方式:elments()返回一个Enumeration对象来遍历;
  4. Vector每次扩容时容量扩大的数量,通过一个成员变量:capacityIncrement来控制,如果capacityIncrement<=0,每次扩容后容量为原来的2倍;
  5. Vector的subList()方法返回的list是一个同步的list对象;
  6. 如果细看,Vector的序列化实现方式也和ArrayList不同,应该是为了兼容老代码,没有必要对此进行研究;

因为Vector每次操作都要获取锁,效率太低,因此如果没有线程安全的需求,一般推荐使用 ArrayList(其实如果有线程安全,也没有必要使用Vector,直接使用Collections.synchronizedList(List)包装出一个同步的list使用即可,将Vector踢进历史长河中)

既然讲了Vector这个被抛弃的类,那么也顺带说一下在Java中被公认为设计不良好的Stack类,从名字就可以看出来其预期是表示一个栈,但是我们看一下其类声明:

/**
* @since JDK1.0
*/
public
class Stack<E> extends Vector<E> { public Stack() {
} // 压栈
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);
} // 获得指定对象o离栈顶的距离,如果o就是栈顶元素,则为1;如果栈中不存在元素o,返回-1;
public synchronized int search(Object o) {
int i = lastIndexOf(o); if (i >= 0) {
return size() - i;
}
return -1;
} /** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = 1224463164541339165L;
}

Stack之所以被认为设计不良好,是因为其继承了Vector类:

  1. 所有Vector中可被调用的方法,在相同情况下也可以在Stack中调用,这与Stack本身的定义就不符,Stack本身是一个LIFO的数据结构,只允许在一端压入,同一端取出(也即压栈和弹栈)的操作;
  2. Vector内部使用数组方式实现,有自动扩容机制,Stack继承Vector类,也就同样限制了Stack内部实现方式也是数组,也有动态扩容机制,这对Stack的实现没有必要(完全可以简单地使用链表实现);
  3. 可能是为了保持Vector线程安全的特点,Stack中的方法也全部为同步方法,这使得其效率低;

除此之外,Stack类还要注意pop()和peek()的区别:

  1. pop()是弹栈,及获取栈顶元素,并把栈顶元素删除;
  2. peek()只是获取栈顶元素,相当于查询,并不对栈进行其他操作;

在《Java编程思想》中,提供了另一中Stack实现方式:

// Making a stack from a LinkedList.

import java.util.LinkedList;

public class Stack<T>{

	private LinkedList<T> storage = new LinkedList<T>();

	public void push(T v){
storage.addFirst(v);
} public T peek(){
return storage.getFirst();
} public T pop(){
return storage.removeFirst();
} public boolean empty(){
return storage.isEmpty();
} public String toString(){
return storage.toString();
} }

这个栈的实现方式避免了上面说的Stack继承自Vector的问题;

Stack只含有一个LinkedList对象的引用,而不是继承LinkedList.

奇怪的是,jdk文档推荐使用Deque来代替Stack,如果查看LinkedList的类定义就知道其实现了Deque接口,但是这并不能避免上面的问题(只是非线程安全了,使效率有所提高);

而且jdk在明确了Stack之后,没有提供其他的Stack相关的类,《Java编程思想》中给出的解释"可能是因为Stack这个名字已经被占用",但是这并不能说通,因为完全可以弄出个"ArrayStack,LinkedStack"之类的名字;

Java容器解析系列(4) ArrayList Vector Stack 详解的更多相关文章

  1. Java容器解析系列(6) Queue Deque AbstractQueue 详解

    首先我们来看一下Queue接口: /** * @since 1.5 */ public interface Queue<E> extends Collection<E> { / ...

  2. java基础解析系列(十)---ArrayList和LinkedList源码及使用分析

    java基础解析系列(十)---ArrayList和LinkedList源码及使用分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder jav ...

  3. Java容器解析系列(0) 开篇

    最近刚好学习完成数据结构与算法相关内容: Data-Structures-and-Algorithm-Analysis 想结合Java中的容器类加深一下理解,因为之前对Java的容器类理解不是很深刻, ...

  4. Java容器解析系列(11) HashMap 详解

    本篇我们来介绍一个最常用的Map结构--HashMap 关于HashMap,关于其基本原理,网上对其进行讲解的博客非常多,且很多都写的比较好,所以.... 这里直接贴上地址: 关于hash算法: Ha ...

  5. Java容器解析系列(1) 迭代的进化——从Enumeration到Iterator

    在Java中,对于所有的Collection,都有一个特性,可以通过迭代器来遍历和删除其中的元素,因为Collection接口继承自Iterable接口. public interface Colle ...

  6. Java容器解析系列(7) ArrayDeque 详解

    ArrayDeque,从名字上就可以看出来,其是通过数组实现的双端队列,我们先来看其源码: /** 有自动扩容机制; 不是线程安全的; 不允许添加null; 作为栈使用时比java.util.Stac ...

  7. Java容器解析系列(13) WeakHashMap详解

    关于WeakHashMap其实没有太多可说的,其与HashMap大致相同,区别就在于: 对每个key的引用方式为弱引用; 关于java4种引用方式,参考java Reference 网上很多说 弱引用 ...

  8. Java容器解析系列(10) Map AbstractMap 详解

    前面介绍了List和Queue相关源码,这篇开始,我们先来学习一种java集合中的除Collection外的另一个分支------Map,这一分支的类图结构如下: 这里为什么不先介绍Set相关:因为很 ...

  9. Java容器解析系列(8) Comparable Comparator

    Comparable和Comparator接口是两个用于对对象进行大小比较的接口,在java集合相关类中,也被经常地使用到. 关于其使用,可以参考网络上的其他博客(没什么好说的);这里阐述关于这两个接 ...

随机推荐

  1. java.lang.ClassNotFoundException: com.sun.xml.ws.spi.ProviderImpl解决办法

    问题现象: 这种很可能出现在独立一个简单示例项目中可以用,但是在把webService模块加入系统后,报出这类错误. Exception in thread "main" java ...

  2. 事件冒泡以及onmouseenter 和 onmouseover 的不同

    1. onmouseenter onmouseenter 事件在鼠标指针移动到元素上时触发. 该事件通常与 onmouseleave 事件一同使用, 在鼠标指针移出元素上时触发. onmouseent ...

  3. zabbix部署相关

    一.centos7 安装zabbix 二.zabbix 乱码问题 三.zabbix自动发现自动注册 四.zabbix3.4实现sendEmail邮件报警

  4. 在python中使用正则表达式

    一.转义符 1.在python中的转义符 (1)\\n与\n的区别 (2)r"\next" 通过r来进行转义 (3)"\\\\d"与"\\d" ...

  5. Scala--reduceLeft

    reduceLeft神语法 val a = Array(20, 12, 6, 15, 2, 9) 1 2 3 4 5 6 7 8 scala> a.reduceLeft(_ + _)  // 数 ...

  6. Visual Studio 2015 key 许可证,下载地址

    Visual Studio 2015正式版离线iso及在线下载,附专业版和企业版可用key! Visual Studio Community 2015简体中文版(社区版,针对个人免费): 在线安装ex ...

  7. Docker安装准备

    第一次写作下笔记: 以centos6.5安装yum优先级插件 yum install yum-priorities 1.epel简介: https://fedoraproject.org/wiki/E ...

  8. SAP Hybris电子商务最新功能

    SAP Hybris电子商务最新功能   SAP Hybris 电子商务6.0中国加速器是专为中国市场设计的电子商务平台,可满足企业在全渠道销售和订单履行方面的所有需求.新版的中国加速器基于SAP H ...

  9. Font Awesome字体图标的 用法, 很简单

    http://fontawesome.dashgame.com/ 上面是 官网,  可下载,也可以CDN. 1...  加载 2...  用法

  10. [Hibernate] inner Join和 left Join

    @Test public void test11(){ Session ss=HibernateUtil.getSession(); //根据员工名称(SCOTT)找到和他所在的部门的其他员工的信息 ...