- 浏览: 754459 次
- 性别:
- 来自: 郑州
文章分类
- 全部博客 (396)
- JAVA (50)
- ORACLE (22)
- HIBERNATE (1)
- SPRING (26)
- STRUTS (4)
- OTHERS (0)
- MYSQL (11)
- Struts2 (16)
- JS (33)
- Tomcat (6)
- DWR (1)
- JQuery (26)
- JBoss (0)
- SQL SERVER (0)
- XML (10)
- 生活 (3)
- JSP (11)
- CSS (5)
- word (1)
- MyEclipse (7)
- JSTL (1)
- JEECMS (2)
- Freemarker (8)
- 页面特效 (1)
- EXT (2)
- Web前端 js库 (2)
- JSON http://www.json.org (3)
- 代码收集 (1)
- 电脑常识 (6)
- MD5加密 (0)
- Axis (0)
- Grails (1)
- 浏览器 (1)
- js调试工具 (1)
- WEB前端 (5)
- JDBC (2)
- PowerDesigner (1)
- OperaMasks (1)
- CMS (1)
- Java开源大全 (2)
- 分页 (28)
- Eclipse插件 (1)
- Proxool (1)
- Jad (1)
- Java反编译 (2)
- 报表 (6)
- JSON (14)
- FCKeditor (9)
- SVN (1)
- ACCESS (1)
- 正则表达式 (3)
- 数据库 (1)
- Flex (3)
- pinyin4j (2)
- IBATIS (3)
- probe (1)
- JSP & Servlet (1)
- 飞信 (0)
- AjaxSwing (0)
- AjaxSwing (0)
- Grid相关 (1)
- HTML (5)
- Guice (4)
- Warp framework (1)
- warp-persist (1)
- 服务器推送 (3)
- eclipse (1)
- JForum (5)
- 工具 (1)
- Python (1)
- Ruby (1)
- SVG (3)
- Joda-Time日期时间工具 (1)
- JDK (3)
- Pushlet (2)
- JSP & Servlet & FTP (1)
- FTP (6)
- 时间与效率 (4)
- 二维码 (1)
- 条码/二维码 (1)
最新评论
-
ctrlc:
你这是从web服务器上传到FTP服务器上的吧,能从用户电脑上上 ...
jsp 往 FTP 上传文件问题 -
annybz:
说的好抽象 为什么代码都有两遍。这个感觉没有第一篇 和第二篇 ...
Spring源代码解析(三):Spring JDBC -
annybz:
...
Spring源代码解析(一):IOC容器 -
jie_20:
你确定你有这样配置做过测试? 请不要转载一些自己没有测试的文档 ...
Spring2.0集成iReport报表技术概述 -
asd51731:
大哥,limit传-1时出错啊,怎么修改啊?
mysql limit 使用方法
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
private transient Entry<E> header = new Entry<E>(null, null, null);
private transient int size = 0;
可以看到,LinkedList继承了抽象的序列链表类,并实现了List、Queue、Cloneable、Serializable接口,使LinkedList可以像队列一样进行操作,同时可以克隆和串行化,使其能够保存到文件。
值得我们注意的是,在这里面声明变量时,用到了transient关键词。那么他是什么意思啊?
transient 关键字表示在Serializable 的时候不保存该值。这两个变量在串行化时,不需要保存。
Entry类到底是如何实现的呢?
private static class Entry<E> {
E element;
Entry<E> next;
Entry<E> previous;
Entry(E element, Entry<E> next, Entry<E> previous) {
this.element = element;
this.next = next;
this.previous = previous;
}
}
可以看到了,Entry里面声明了变量elment,next和previous,这就是我们在数据结构中知道的一个节点类声明。这是一个双向链表,不是吗?
public LinkedList() {
header.next = header.previous = header;
}
构造函数。初始化链表类。将next和previous指针指向自己。
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
用一个链表类初始化LinkedList,关于上面的红色部分,据我的理解,这个泛型类要求加入的泛型元素必须是E的子类。
这个构造函数调用了默认构造函数,addAll把c添加到LinkedList中,下面会介绍这个函数。
public E getFirst() {
if (size==0)
throw new NoSuchElementException();
return header.next.element;
}
返回第一个元素。如果size==0,抛出异常,否则就返回head.next.element;
通过这句话,我们似乎明白,这里的数据结构是有头结点的。
public E getLast() {
if (size==0)
throw new NoSuchElementException();
return header.previous.element;
}
返回最后一个元素。如果size==0,那么抛出异常。否则返回header.previous.element。
这就是双向链表,将头结点的previous指向最后一个元素。
public E removeFirst() {
return remove(header.next);
}
public E removeLast() {
return remove(header.previous);
}
public E remove(int index) {
return remove(entry(index));
}
private E remove(Entry<E> e) {
if (e == header)
throw new NoSuchElementException();
E result = e.element;
e.previous.next = e.next;
e.next.previous = e.previous;
e.next = e.previous = null;
e.element = null;
size--;
modCount++;
return result;
}
移走元素。要移走的元素已经确定,不需再找到这个元素。所以直接移走就可以了。先用result指向要移走的元素。然后按照数据结构中的算法移走就可以了。移走后返回移走的元素。
modCount是在AbstractList中声明使用的。用来记录这个链表结构被修改的次数。this list has been
public void addFirst(E e) {
addBefore(e, header.next);
}
public void addLast(E e) {
addBefore(e, header);
}
public boolean add(E e) {
addBefore(e, header);
return true;
}
public void add(int index, E element) {
addBefore(element, (index==size ? header : entry(index)));
}
private Entry<E> addBefore(E e, Entry<E> entry) {
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}
将元素e添加到entry前面。很简单,不用分析,相信你也明白。
public boolean contains(Object o) {
return indexOf(o) != -1;
}
public int indexOf(Object o) {
int index = 0;
if (o==null) {//如果o为null
for (Entry e = header.next; e != header; e = e.next) {
if (e.element==null)
return index;
index++;
}
} else {不为空,其判断是通过equals进行判断的。
for (Entry e = header.next; e != header; e = e.next) {
if (o.equals(e.element))
return index;
index++;
}
}
return -1;
}
首先获得元素的索引值。如果返回-1,无这个元素。为什么要分元素是不是空这个分支呢?因为如果o是空的话,判断是通过e.element==null判断的。不为空,则通过o.equals(e.element)判断。
public int size() {
return size;
}
返回大小。
public boolean remove(Object o) {
if (o==null) {
for (Entry<E> e = header.next; e != header; e = e.next) {
if (e.element==null) {
remove(e);
return true;
}
}
} else {
for (Entry<E> e = header.next; e != header; e = e.next) {
if (o.equals(e.element)) {
remove(e);
return true;
}
}
}
return false;
}
也比较容易理解。不做解释了。
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
if (index < 0 || index > size)//如果要插入的位置>size或小于0,异常。
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Object[] a = c.toArray();//将集合中的元素转化为数组。
int numNew = a.length;//返回数组长度
if (numNew==0)//如果是0的话,遗憾,无法添加了
return false;
modCount++;//不是0的话,ok,修改计数器加1
Entry<E> successor = (index==size ? header : entry(index));//如果index==size,那么successor=header
Entry<E> predecessor = successor.previous;//获得前一个处理元素
for (int i=0; i<numNew; i++) {//对于数组每一个元素,生成entry类,加入到链表中。
Entry<E> e = new Entry<E>((E)a[i], successor, predecessor);
predecessor.next = e;
predecessor = e;
}
successor.previous = predecessor;
size += numNew;
return true;
}
如上注解。
public void clear() {
Entry<E> e = header.next;
while (e != header) {
Entry<E> next = e.next;//记录e的next
e.next = e.previous = null;//去掉e的next和previous
e.element = null;//去掉自己元素。
e = next;//处理下一个节点
}
header.next = header.previous = header;
size = 0;
modCount++;
}
将链表清空。不用解释了。很简单。不过,我们通过这个方法明白一点,要真正的销毁对象,光靠垃圾回收机制是不行的。像这里,给没有用的引用赋空值,使内存中的实体对象没有指针,而加快内存的回收。
public E get(int index) {
return entry(index).element;
}
private Entry<E> entry(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Entry<E> e = header;//获得头结点
if (index < (size >> 1)) {//如果index小于size的一半
for (int i = 0; i <= index; i++)
e = e.next;
} else {//不小于的话,ok,从后面找。
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}
多么好的算法啊。如果要找的元素在前半部分,那就从头找,如果在最后那么就从尾开始找。获得size的一半也很节省cpu消耗,采用移位的方式,值得学习。
public E set(int index, E element) {
Entry<E> e = entry(index);
E oldVal = e.element;
e.element = element;
return oldVal;
}
不再解释。很简单。
下面的分析关系到了LinkedList的遍历、持久化、克隆等相关主题。
public ListIterator<E> listIterator(int index) {
return new ListItr(index);
}
返回一个从index开始的遍历器。
private class ListItr implements ListIterator<E> {
private Entry<E> lastReturned = header;//让这里面的参数初始化,最后一个返回的元素。
private Entry<E> next;下一个元素的指针
private int nextIndex;下一个元素的索引
private int expectedModCount = modCount;等于原来类中的修改次数
ListItr(int index) {//构造函数
if (index < 0 || index > size)//如果给的index不正确
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
if (index < (size >> 1)) {//如果index<size的一半
next = header.next;//找到index所指的元素
for (nextIndex=0; nextIndex<index; nextIndex++)
next = next.next;
} else {
next = header;//从后面遍历,找到所要的元素
for (nextIndex=size; nextIndex>index; nextIndex--)
next = next.previous;
}
}
public boolean hasNext() {//判断有没有下个元素
return nextIndex != size;
}
public E next() {获得下一个元素
checkForComodification();
if (nextIndex == size)
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.element;
}
public boolean hasPrevious() {
return nextIndex != 0;
}
public E previous() {
if (nextIndex == 0)
throw new NoSuchElementException();
lastReturned = next = next.previous;
nextIndex--;
checkForComodification();
return lastReturned.element;
}
public int nextIndex() {
return nextIndex;
}
public int previousIndex() {
return nextIndex-1;
}
public void remove() {
checkForComodification();
Entry<E> lastNext = lastReturned.next;
try {
LinkedList.this.remove(lastReturned);
} catch (NoSuchElementException e) {
throw new IllegalStateException();
}
if (next==lastReturned)
next = lastNext;
else
nextIndex--;
lastReturned = header;
expectedModCount++;
}
public void set(E e) {
if (lastReturned == header)
throw new IllegalStateException();
checkForComodification();
lastReturned.element = e;
}
public void add(E e) {
checkForComodification();
lastReturned = header;
addBefore(e, next);
nextIndex++;
expectedModCount++;
}
final void checkForComodification() {//
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
上面的这个类是定义在LinkedList中的私有类。他实现了ListIterator具体的分析参照上面的注释。
public Iterator<E> descendingIterator() {
return new DescendingIterator();
}
private class DescendingIterator implements Iterator {
final ListItr itr = new ListItr(size());
public boolean hasNext() {
return itr.hasPrevious();
}
public E next() {
return itr.previous();
}
public void remove() {
itr.remove();
}
}
上面的函数和类仍然返回不同的遍历器。不再解释。不过DescendingIterator 是递减的遍历器。可以注意到他的next()、hasNext()方法的不同。
public Object clone() {
LinkedList<E> clone = null;
try {
clone = (LinkedList<E>) super.clone();//先调用父类的克隆函数
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
// Put clone into "virgin" state
clone.header = new Entry<E>(null, null, null);//自己开始复制,先复制头节点
clone.header.next = clone.header.previous = clone.header;//给头结点赋值
clone.size = 0;
clone.modCount = 0;
// Initialize clone with our elements
for (Entry<E> e = header.next; e != header; e = e.next)//把元素也复制过去
clone.add(e.element);
return clone;
}
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Entry<E> e = header.next; e != header; e = e.next)
result[i++] = e.element;
return result;
}
转化成数组。
public <T> T[] toArray(T[] a) {
if (a.length < size)如果a太小了,那么就在重新给a分配空间吧。
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);如何分配,那么就用反射机制吧。
//有地方放了,好吧数据放入数组中,呵呵。
int i = 0;
Object[] result = a;
for (Entry<E> e = header.next; e != header; e = e.next)
result[i++] = e.element;
if (a.length > size)如果a长了,a【size】=null,使不能访问后面的元素。
a[size] = null;
return a;
}
private static final long serialVersionUID = 876323262645176354L;
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden serialization magic
s.defaultWriteObject();
// Write out size
s.writeInt(size);
// Write out all elements in the proper order.
for (Entry e = header.next; e != header; e = e.next)
s.writeObject(e.element);
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden serialization magic
s.defaultReadObject();
// Read in size
int size = s.readInt();
// Initialize header
header = new Entry<E>(null, null, null);
header.next = header.previous = header;
// Read in all elements in the proper order.
for (int i=0; i<size; i++)
addBefore((E)s.readObject(), header);
}
}
发表评论
-
网页标签过滤
2012-05-14 15:49 1003package com.xcy.babyonline.c ... -
图片压缩
2012-05-14 15:48 1663/** * WriteImage.java Crea ... -
BeanUtils.copyProperties与PropertyUtils.copyProperties用法及区别
2012-02-24 17:11 1011一、简介: BeanUtils提供 ... -
[转]给网站上传的图片盖章
2011-12-30 16:13 941/****************************** ... -
[转] 给网站上传的图片盖章
2011-12-30 16:12 999/****************************** ... -
java 给图片加文字水印
2011-12-30 16:10 2168java给图片加水印,在网上有很多资料,但我想要一个能自适 ... -
joda time 方便快捷 .
2011-12-01 11:08 887操作日期不再那么麻烦 DateTime dt ... -
jsp 往 FTP 上传文件问题
2011-11-21 18:17 2512FtpUtil: import java.io.DataI ... -
Java中读取字节流并按指定编码转换成字符串的方法
2011-11-21 18:13 1195该方法中使用一个无限循环,从字节流中读取字节,存放到byte数 ... -
InputStream转String
2011-11-21 18:09 1208org.apache.commons.io.output.B ... -
在EditPlus中配置JDK编译JAVA的详细方法
2011-08-09 18:17 759在EditPlus中配置JDK编译JAVA的详细方法 -
Linux下Jsp环境搭建 Java平台 Tomcat安装 MySQL安装配置
2011-05-11 14:08 1534安装软件 1、安装JDK(因JDK包含JRE,若原来装 ... -
Java中怎么遍历map中value值
2011-04-22 15:21 1310//两种方法,有问题,给我发百度消息 public sta ... -
Java 获取指定日期的方法总结
2011-04-13 19:14 1572格式化日期 String-->Date 或者 Data ... -
java位与运算
2011-02-11 17:20 2165位与运算的实质是将参与运算的两个数据,按对应的二进制数逐位进行 ... -
技术网站
2011-02-11 11:03 871OpenSource: http://www.open-ope ... -
Java或Web中解决所有路径问题
2011-01-27 09:58 886Java中使用的路径,分为两种:绝对路径和相对路径。归根结底, ... -
给出一个字符串或其他,返回一个指定长度的字符串,长度小于指定长度,用指定字符填充
2011-01-19 17:25 1353实现代码如下: publ ... -
JDK命令详解
2010-12-28 15:25 850转自:http://www.historycreator.co ... -
XFIRE_WEBSERVICES实例
2010-12-13 18:30 840服务器端 接口 package com.server ...
相关推荐
在深入分析JDK 7.0中LinkedList集合的底层实现原理前,我们首先需要了解LinkedList的基本概念。LinkedList,即双向链表,是一种通过双向指针相互连接的数据结构,每个节点包含数据域以及指向前驱和后继节点的指针。...
在Java编程语言中,LinkedList是一个常用的集合类,它实现了List接口,同时也提供了双向链表的实现...在阅读和分析给定的Queue.java和Stack.java文件时,可以从实现原理、方法调用、线程安全等方面进行深入学习和理解。
LinkedList类的源代码分析对于理解其工作原理非常重要,特别是对于学习数据结构和算法的开发者来说。它展示了如何使用链表数据结构来实现动态列表,以及如何通过内部类和指针操作实现高效的插入、删除和遍历操作。...
8. 性能分析: 由于LinkedList的所有插入、删除操作都需要改变节点的引用,所以其在随机访问和修改时的性能不如ArrayList。但在需要频繁插入、删除元素且对元素顺序有特定要求的情况下,LinkedList的性能更优。 9. ...
LinkedList是Java中的一个类,位于java.util包下,它是List接口的一个实现,主要用于存储动态的、有序的数据集合。与数组不同,链表的元素不需要在内存中连续存储,这使得在链表中插入和删除元素具有较高的效率。 ...
【ArrayList、LinkedList、Vector对比分析】 1. **List概述** List接口是Java集合框架中的重要组成部分,它是一个有序的集合,允许重复元素,并且保持插入顺序。List接口的实现类主要有ArrayList、LinkedList和...
* 数据处理:LinkedList可以用来处理大量数据,例如数据统计、数据分析等。 LinkedList是Java集合框架中的一个重要组件,具有链表底层实现的特点,查询速度慢,增删速度快。通过本文的讲解,读者可以快速掌握...
Java层次分析法(Analytic Hierarchy Process,AHP)是一种基于多准则决策分析的方法,它通过将复杂问题分解为多个相互关联的子问题,并通过比较和综合这些子问题的相对重要性来解决整个问题。在Java编程环境中实现...
通过分析和研究这些源代码,读者可以深入理解Java语言的特性和应用。 1. **Java基础**:书中源代码可能包括了Java的基础语法,如变量、数据类型、控制结构(if、for、while)、类与对象、封装、继承和多态等概念。...
每个文件都可能包含独立的Java编程知识点,通过阅读和分析这些代码,学习者可以深入理解Java语言的不同方面。为了充分利用这些资源,可以逐个文件打开,理解并实践其中的代码,同时查阅相关的Java教程和文档以增强...
6. 示例代码分析: 给定的代码中,通过二分查找测试了 ArrayList 和 LinkedList 的访问速度。由于二分查找依赖于随机访问,ArrayList 在这个例子中表现得更快。实际运行结果会显示 ArrayList 消耗的时间少于 ...
在Java编程语言中,ArrayList、LinkedList和Vector是三种常见的动态数组实现,它们都在java.util包中,用于存储和管理对象的集合。这三个类都实现了List接口,提供了多种操作方法,但它们在内部实现和性能特性上有所...
Java编程语言中的`Map`, `List`, `ArrayList` 和 `LinkedList` 是四个核心的数据结构,它们在实际开发中被广泛使用。了解它们的源码对于深入理解Java集合框架的内部工作原理至关重要,尤其是对初学者而言,这有助于...
简介 LinkedList 是一个常用的集合类,用于顺序存储元素。 LinkedList 经常和 ArrayList 一起被提及。...本文分析 LinkedList 的具体实现。 继承关系 public class LinkedList extends AbstractS
Java 试题解析包括对 Java 试题的分析和解释,可以帮助考生更好地准备 Java 考试。 8. Java collection 框架 Java collection 框架提供了一个通用的集合类框架,能够帮助开发者更方便地操作数据。 9. Java IO ...
在《数据结构与算法分析:Java语言描述》一书中,作者深入探讨了这一领域的关键概念和技术,并通过Java编程语言进行了具体的实现和演示。 ### 数据结构 数据结构是指在计算机中存储、组织数据的方式,它不仅影响到...
以下是对这两个类的详细分析: 1. 数据结构: - ArrayList是基于动态数组的数据结构,即在内存中分配一块连续的空间来存储元素。这种设计使得ArrayList支持随机访问,因为可以通过索引直接定位到元素。 - ...
在处理过程中,词法分析器会将每个识别到的记号存储在一个数据结构中,如ArrayList或LinkedList,以便后续的语法分析阶段使用。 图形用户界面(GUI)的设计使得用户能直观地看到分析结果。它可以显示源代码中的行号...
### Java应用:两种Java容器类List和Set分析 #### 一、概述 在Java编程语言中,集合框架(Collections Framework)是处理数据的核心组件之一,它提供了存储和操作对象的各种方式。本文将深入探讨Java中的两种重要...
4. **Java集合框架**:在处理数据时,Java的集合框架如ArrayList、LinkedList、HashMap等会广泛应用于数据的存储和操作。 5. **JDBC**:Java数据库连接,是Java访问数据库的标准API,用于建立、配置和管理数据库...