Java集合----List

1.List简介

List接口是Java对线性表(逻辑上的)的特征的抽象。

2.List接口的实现

2.1ArrayList

最常用的List集合实现,是一种动态可增长基于数组的有序集合。

2.1.1基本特征

①数据存储是基于数组实现的(默认数组大小为10);
②添加数据时,会首先检测是否超过数组容量,如果超过了则需要对数组进行扩容(扩容采用Arrays.copyOf()方法,代价很高避免扩容这样的操作);
③删除数据时,需要将删除点+1位置开始到数组末尾的数据全部向前移动一位。
④获取数据很快,根据数组下标可以直接获取。
⑤此实现不是线程安全的;

2.1.2 ArrayList的实现

2.1.2.1 属性

 private transient Object[] elementData;//存储元素 transient标识的属性在序列化时并不会被序列化
 private int size;//数组内元素的数量

2.1.2.2 常用API及特殊API

tip1:因为底层是基于数组的,那么自然的在末尾增加移除元素是较容易的,在指定位置插入移除元素就相对的消耗时间了.
tip2:因为底层是基于数组的,按下标取元素时间复杂度就是常数了

2.1.2.2.1 add()系列
public boolean add(E e);//在末尾加入元素
public void add(int index, E element) ;//在指定位置插入元素,包括当前位置元素在内以后的元素向右移动(index加1)。 
public boolean addAll(int index, Collection<? extends E> c);//在末尾增加元素列表
public boolean addAll(int index, Collection<? extends E> c);//在指定位置插入元素列表
2.1.2.2.2 remove()系列
public boolean remove(Object o);//根据指针去除元素
public boolean remove(int index);//根据游标去除元素
public boolean removeAll(Collection<?> c);//去除c内包含的元素
2.1.2.2.3 set()系列
public E set(int index, E element);//替换指定位置的元素
2.1.2.2.4 get()系列
 public E get(int index);//返回制定位置的元素
2.1.2.2.5 subList(int fromIndex, int toIndex)
public List<E> subList(int fromIndex, int toIndex);
//返回当前List中对于(fromIndex,toIndex)部分的引用

注意:和String.subString()完全不一样,例如:
ArrayList<Object> objs1= new ArrayList<Object>(100);
objs1.subList(0, 5).clear();//objs1 中下标为0,1,2,3,4的数据会变成null;

2.1.2.2.5 trimToSize();
public void trimToSize();//将List的capacity削减到和size大小一致;

2.2LinkedList

LinkedList是List接口基于双向链表的实现,基于链表使得LinkedList在插入和删除时更优于ArrayList,而随机访问则比ArrayList逊色些。

2.2.1数据结构

double-linked.jpg

2.2.2数据结构的代码描述

transient Node<E> first;//LinkedList的首指针
transient Node<E> last;//LinkedList的尾指针
private static class Node<E> {//节点
  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;
  }
}

2.2.2常用API及其实现

2.2.2.1 add()系列:

public boolean add(E e);//末尾追加元素

public boolean add(E e) {
  linkLast(e);
  return true;
}
void linkLast(E e) {
  final Node<E> l = last;//取最后一个元素
  final Node<E> newNode = new Node<>(l, e, null);//构造新节点
  last = newNode;//设置新节点为最后的节点
 if (l == null)//如果为新构造的空链表,则把首指针也设置为尾指针
    first = newNode;
 else
   l.next = newNode;//进行链接
   size++;//元素数量增加
   modCount++;//fast-fail 机制支持
}

objs2.add(index, element);//在指定下标插入元素,涉及到双向列表的遍历

public void add(int index, E element) {
  checkPositionIndex(index);//检测是否查过元素数量
  if (index == size)//如果是在末尾插入,则直接追加
    linkLast(element);
  else
    linkBefore(element, node(index));//在指定位置插入元素
}
//双向链表的遍历
Node<E> node(int index) {
  if (index < (size >> 1)) {//在index小于size的一半时,从first向后遍历
    Node<E> x = first;
    for (int i = 0; i < index; i++)
      x = x.next;
    return x;
  } else {//在index大于size的一半时,从last向前遍历
    Node<E> x = last;
    for (int i = size - 1; i > index; i--)
      x = x.prev;
    return x;
  }
}
//插入元素e在succ前面
void linkBefore(E e, Node<E> succ) {
  // assert succ != null;
  final Node<E> pred = succ.prev;
  final Node<E> newNode = new Node<>(pred, e, succ);
  succ.prev = newNode;
  if (pred == null)
    first = newNode;
  else
    pred.next = newNode;
    size++;
    modCount++;
}

public void addFirst(E e);//首部添加
public void addLast(E e);//尾部添加
public boolean addAll(Collection<? extends E> c);//末尾链接集合
public boolean addAll(int index, Collection<? extends E> c);//在指定位置插入集合,也涉及到index的遍历,可参考上面两个来写,遍历找到index位置节点然后循环追加,然后链接上。

2.2.2.2 clear():

public void clear();//置空双向链表,同时置空每个节点的首尾指针,尽管置空节点的首尾指针比不必要的但是
-helps a generational GC if the discarded nodes inhabit more than one generation
-is sure to free memory even if there is a reachable Iterator
也就是避免 ‘在这个List的某些特定的节点仍有外部引用指向时,导致的其他节点不可被清理’ 涉及到分代GC的原理

public void clear() {
  for (Node<E> x = first; x != null; ) {
    Node<E> next = x.next;
    x.item = null;
    x.next = null;
    x.prev = null;
    x = next;
   }
   first = last = null;
   size = 0;
   modCount++;
}

2.2.2.2 clone()链表的克隆:

克隆链表后把原链表的数据遍历加入

public Object clone() {
  LinkedList<E> clone = superClone();
  // Put clone into "virgin" state
  clone.first = clone.last = null;
  clone.size = 0;
  clone.modCount = 0;
  // Initialize clone with our elements
  for (Node<E> x = first; x != null; x = x.next)
      clone.add(x.item);
   return clone;
}

2.2.2.3 descendingIterator()反向遍历迭代器:

2.2.2.4 remove():删除元素

遍历查找元素然后将前后两个节点链接起来即可。

2.2.3 关于LinkedList的遍历性能问题

参看这篇文章 http://blog.csdn.net/u010853261/article/details/54143917
不要使用for循环,还是用迭代器吧

2.3Vector

ArrayList的线程安全版本,方法上增加synchronized 实现。

3.fast-fail机制

在AbstractList类中有modCount这么一个字段,扩展类ArrayList、LinkedList以及Vector中 在对自身的元素进行更改时均会modCount++操作;
Thread a,b 两个线程对同一个List实例 listTest通过迭代器迭代(迭代期对象持有一个在自身被创建时listTest的modCount的值),如果a线程进行修改导致了modCount++操作,b线程在的迭代器modCount未进行改变,则b线程迭代会导致 ConcurrentModificationException();而Java并不保证一定能触发,所以还是不要在多线程环境中使用这些实现或者自己在外部提供同步机制

final void checkForComodification() {
  if (modCount != expectedModCount)
     throw new ConcurrentModificationException();
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • Java集合 作为一个Developer,Java集合类是我们在工作中运用最多的、最频繁的类。相比于数组(Arra...
    贾博岩阅读 63,722评论 14 103
  • java笔记第一天 == 和 equals ==比较的比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量...
    jmychou阅读 1,440评论 0 3
  • List是有序,元素可重复的Collection,实现List接口的常用类有ArrayList,LinkedLis...
    spiritTalk阅读 511评论 0 0
  • 一、基本数据类型 注释 单行注释:// 区域注释:/* */ 文档注释:/** */ 数值 对于byte类型而言...
    龙猫小爷阅读 4,213评论 0 16
  • 细雪微微,斜风作晓寒,落笔恍觉忽已晚,临窗灯火疏暗。 京都漫漫,征鸿度玉关,莫道此间行路难,人间自是清欢。 一年的...
    踏歌娘阅读 535评论 9 5