J2SE

我们都知道,当想要保存一组基本类型数据时,数组是最有效的保存方式,也是推荐使用这种方式的。但是数组是固有大小的,当运行时才知道大小的程序,这种方式使用就受限制了,这就是Java容器类产生的原因。Java集合类有几个特点:首先,这种容器是高性能的,对基本数据集合(动态数组、链接表、树和散列表)的实现是高效率的。第二,容器类允许不同类型的类集合以相同的方式和高度互操作方式工作。第三,容器类是容易扩展或修改的。容器类的常用的基本类型有List、Set和Map,这些对象类型也称为集合类,但是在Java中使用了Collection这个名字来指代该类库的一个特殊子集,所以业界使用了范围更广泛的“容器”来称呼。

Collection:是一个接口,它位于集合框架层次结构的顶层,继承自Iterable接口,说明是可以用Iterator迭代器来访问该集合中的元素的。又有List、Set和Queue接口继承Collection接口,直接实现该接口的是一个叫AbstractCollection的抽象类,该抽象类以最大限度地减少了实现此接口所需的工作。

List:继承自Collection接口,表示有序的、可包括重复元素的列表。同时拥有Collection内的方法外,还添加了大量的方法,使得可以在List的中间插入和删除元素。实现该接口的基本类有ArrayList和LinkedList. ArrayList:擅长于对元素的随机访问,但是在插入和删除元素时效率较慢。其实,看看ArrayList类实现的源代码就知道,ArrayList是以线性表的数据结构形式存取数据的,初始化的表大小为10,下面就有几个经常用到的核心方法:add(E e):在当前表的末尾插入元素,如果在前面表不满的情况下,也是很高效的,直接插入到末尾,但是如果在当前表已经满的情况下,就要重新生成一个比当前表大小更大的新表,新表的大小是当前表大小的1.5倍加1,比如当前表长度为20的,新表的大小就为31,还需要把当前表元素复制到新表中去,然后把当前表引用指向新表,最后把数值插入到表末尾,所以这种操作是非常低效的。

add(int index,E element):在指定索引位置插入元素,检查表大小和重新追加表大小和上面的add(E e)方式是一样的。最后是要把index以后的元素都是要依次往后移一个大小,然后把元素插入到index位置上去。涉及到表的复制和表内元素的移动,所以效率也是比add(E e)方法还要低。

remove(int index):在指定索引位置删除元素,就是把index位置后的所有元素都往前移一个大小,也是涉及到表内元素的移动,效率也是很低的。

remove(Object o):删除指定的元素,也就需要查找出该元素在表中出现第一次的位置,查找是用到顺序一个一个进行匹配的方法,找出后就把该元素后面的所有元素往前移一个大小。该方法涉及到顺序查找和表内元素移动,比remove(int index)方法更低效。

set(int index,E element):替换表中索引为index的元素值,返回被替换的值,直接用下标索引访问元素,所以效率非常高。

get(int index):获取索引为index的元素,直接用下标索引访问,所以效率也是非常高。

indexOf(Object o):获取元素的索引号,也就是需要查找,虽然用到了顺序查找法,但效率还是比较高的。

LinkedList:擅长于对元素的插入和删除操作,但对于随机访问元素比较慢。该类的实现是以双向链表的数据结构为基础的,所以是比较消耗内存的,但它的特定集比ArrayList更大。双向链表,每个节点都有三个域,两个域是存放前后节点的内存地址引用的,一个域是存放数据元素的。在LinkedList类中,有一个叫Entry的内部类,是private的,里面三个属性,分别是element、next和previous,分别对应了双向链表中的三个域,在ArrayList类中每实例化一个Entry就生成一个节点。下面看看它的核心方法:add(E e):把元素插入到链表末尾,首先要实例化一个节点,新节点previous域存放链表中最后一个节点地址,next域存放链表中第一个节点地址,element域存放元素值,链表中最后一个节点的next域存放新节点的地址,第一个元素的previous域存放新节点的地址,这样这个元素就插入到该链表中去了,没有涉及到复杂的操作,所以是非常高效的。

add(int index,E element):在index位置插入元素,这就需要先查找到该位置。查到后,这里就把查到的节点的前一个节点叫为A,实例化新的节点为B,查到index的节点为C.B的next域等于A的next值(也就是C的内存地址),B的previous域等于C的previous值(也就是A的内存地址),B的element域存放元素值,然后把A的next域和C的previous域都等于B的内存地址。这样也就把元素插入到链表的index位置中去了,但涉及到了查询,所以效率虽然高,但也没有add(E e)那么高。

remove(int index):删除在index位置的元素,首先也是要找到该位置的节点。然后把该节点的下一个节点(也就是该节点next域的内存地址那个节点)的previous值等于该节点的previous值,该节点的上一个节点(也就是该节点previous域的内存地址那个节点)的next值等于该节点的next值。这样就把该节点从这条链表删除了,过程中虽然涉及到了查找,但没有涉及到像ArrayList类中的remove方法要移动表中元素,所以该方法的效率还是很高的。

remove(Object o):删除在链表中第一个元素为o的节点,也是需要查找到该节点,然后就跟remove(int index)思路一样把元素删除,所以效率也是很高的。

set(int index,E element):把在链表中第index个元素值改为element,这也需要找到该节点来修改元素值,但涉及到了查找节点,ArrayList中的set方法就不用查找就可以修改,所以相对于ArrayList中的set方法,LinkedList方法set方法效率就没那么高了。

get(int index):获取第index位置的元素值,也是要找到该节点,所以就也没ArrayList中的get方法那么高效率了,因为该方法需要查找链表。

indexOf(Object o):获取该链表中第一o元素的位置,也是要查找链表,但ArrayList中的indexOf方法也是需要查找的,所以这两个类的indexOf的效率都差不多。

所以,在编程中,如果要进行大量的随机访问,就使用ArrayList;如果要经常从表中插入或删除元素的就应该使用LinkedList.

时间: 2024-10-27 08:16:22

J2SE的相关文章

J2SE 5.0专题 之 语言特性

j2se J2SE 5.0专题 之 语言特性                         本文作者: 高宇翔(大胃) 1.1.        背景J2SE(TM) 5.0正式发布至今已超过3个月的时间了,就在前不久,大概是在两周之前,Sun又发布了更新过的JDK 5.0 Update 1,改掉了一些第一个版本中出现的bug. 由于Java社群等待这一从1.4向5.0版本升级已经有相当长的一段时间,大家都很关心5.0中有哪些值得关注的变化,于是blog的相关信息满天飞,我也兴冲冲地在自己的bl

新手入门之如何掌握Java(J2SE篇)

j2se 本文是另外一篇文章<如何才算掌握Java(J2SE篇)>(后面简称标准篇)的姊妹篇,提出了标准,但是不告诉新手如何才能达到那个标准似乎说不过去. 首先需要说的是达到这个标准是比较困难的,没有三年的时间一般是不可能的,没有实际的项目的经验的熏陶也是不可能的,下文会说明为什么.然后给出两个宝典:一个就是TIJ(Thinking in Java),另外一个就是chm格式的JDK的API. TIJ可以看看(javaresearch.org/download/thread.jsp?thread

J2SE 5.0 语言新特性

j2se  JavaTM Language Features For more information see New Language Features. Generics This long-awaited enhancement to the type system allows a type or method to operate on objects of various types while providing compile-time type safety. It adds

升级到J2SE 5平台的5大理由

j2se 作者:Calvin Austin,2005年1月4日本文给出了升级到Java 2 Platform, Standard Edition (J2SE platform) 5.0的5大理由.每个理由都通过大量数据和参考资料来证实升级到5.0版本将大大降低开发与运行成本.J2SE 5.0(代号Project Tiger)于2004年9月底发布.它是Java平台多年来的重大更新之一.Java社区为其新增功能欢呼不已,然而这些新增功能还无法全面地描述此版本的特色.与以往任何版本相比,这一平台更能

J2SE 5.0的新特性---Autoboxing

j2se AutoboxingAs any Java programmer knows, you can't put an int (or other primitive value) into a collection. Collections can only hold object references, so you have to box primitive values into the appropriate wrapper class (which is Integer in t

J2SE新特性 Windows下读取网卡物理地址

j2se|window 个例子使用了J2SE5.0的ProcessBuilder类执行外部的程序,相对于 Runtime.exec ,它更方便,可以设置环境变量等. package com.kuaff.jdk5package;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.List;public class ProcessBuilderShow{ p

J2SE新特性---循环语句的增强

j2se|循环|语句 之前类似这样的语句: void cancelAll(Collection c) {     for (Iterator i = c.iterator(); i.hasNext(); ) {         TimerTask tt = (TimerTask) i.next();         tt.cancel();     } } 以后可以这样写: void cancelAll(Collection c) {     for (Object o : c)        

J2SE 5.0实例---原生类型的autoboxing和auto-unboxing

j2se 原生类型的autoboxing和auto-unboxing我们知道,在Java中,int,long等原生类型不是一个继承自Object的类,所以相应的,有很多操作我们都不能利用原生类型操作,比如想要把一个整数放入到一个集合中,我们必须首先创建一个Integer对象,然后再将这个对象放入到集合中.当我们从集合中取数的时候,取出来的是一个Integer对象,因此不能直接对它使用加减乘除等运算符,而是必须用Integer.intValue()取到相应的值才可以,这样的过程称之为boxing和

J2SE 5.0实例---静态引入

j2se|静态 静态引入(static import) 在过去我们要使用其他包中某类的静态变量,一般都要在前面加上对应的类名: double r = Math.cos(Math.PI * theta); 使用静态引入,我们可以把前面的类名去掉,静态引入的语句是这样的: import static java.lang.Math.PI; 必须注意到这里最后不是到类Math,而是直接到了定义的变量PI. 静态引入不只对静态变量,也可以针对静态方法.此外还可以使用*,如下面所示: import stat

J2SE 5.0实例---枚举

j2se 枚举在过去,我们必须用整型常数代替枚举,随着J2SE 5.0的发布,这样的方法终于一去不复返了. 一个简单的枚举类型定义如下: public enum Weather {      SUNNY,RAINY,CLOUDY } 枚举可以用在switch语句中: Weather weather=Weather.CLOUDY;      switch(weather)      {      case SUNNY:             System.out.println("It's su