一、List接口概述

List有个很大的特点就是可以操作角标。

下面开始介绍List接口中相对于Collection接口比较特别的方法。在Collection接口中已经介绍的方法此处就不再赘述。

1.添加

 void add(int index, E element) 
          在列表的指定位置插入指定元素(可选操作)。
 boolean addAll(int index, Collection<? extends E> c) 
          将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。

这两个方法相对于Collection接口,可以直接在特定的地方插入新的元素或者集合。

2.删除。

 E remove(int index) 
          移除列表中指定位置的元素(可选操作)。

这个方法相对于Collection接口来说,可以直接删除特定位置上的元素。

3.修改

 E set(int index, E element) 
          用指定元素替换列表中指定位置的元素(可选操作)。

这个方法可以将指定位置上的元素替换为另外一个元素(对象)。

4.查找

 E get(int index) 
          返回列表中指定位置的元素。
 int indexOf(Object o) 
          返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
 int lastIndexOf(Object o) 
          返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
 List<E> subList(int fromIndex, int toIndex) 
          返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

可以看出,上述List所有特有的方法都是和角标操作有关的,这是和List“有序”特点造成的。

5.List接口的特有方法:listIterator

 ListIterator<E> listIterator() 
          返回此列表元素的列表迭代器(按适当顺序)。
 ListIterator<E> listIterator(int index) 
          返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。

案例:

package p01.BaseCollectionDemo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; public class ListIteratorDemo { public static void main(String[] args)
{
List al=new ArrayList();
al.add("abc1");
al.add("abc2");
al.add("abc3");
al.add("abc4");
Demo1(al);
} private static void Demo1(List al) {
for(Iterator it=al.iterator();it.hasNext();)
{
String str=(String)it.next();
System.out.println(str);
if(str=="abc1")
{
al.add("abc5");
}
}
} }

运行结果出现了异常:

分析:查看API,可以得到API对ConcurrentModificationException异常的描述:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。程序首先是单线程,怎么就对对象作了并发修改呢?真正的原因是,迭代器在遍历之前就已经确定了容器内对象的数量,如果容器内再增加对象,迭代器将无法确定容器内对象的个数。迭代器在迭代对象,而add方法在添加对象,这就造成了对对象的并发修改。API对此类异常的说明是:如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。例如,如果线程使用快速失败迭代器在 collection 上迭代时直接修改该 collection,则迭代器将抛出此异常。简单来说,不允许迭代的时候集合对元素进行修改。

解决方法:使用ListIterator迭代器。

ListIterator迭代器是List专门的迭代器,对其他集合的迭代并不适用。

package p01.BaseCollectionDemo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator; public class ListIteratorDemo { public static void main(String[] args)
{
List al=new ArrayList();
al.add("abc1");
al.add("abc2");
al.add("abc3");
al.add("abc4");
// Demo1(al);
Demo2(al);
} private static void Demo2(List al) {
for(ListIterator li=al.listIterator();li.hasNext();)
{
String str=(String)li.next();
if(str.equals("abc1"))
{
li.add("abc5");
}
}
System.out.println(al); } private static void Demo1(List al) {
for(Iterator it=al.iterator();it.hasNext();)
{
String str=(String)it.next();
System.out.println(str);
if(str=="abc1")
{
al.add("abc5");
}
}
} }

运行结果:

  [abc1, abc5, abc2, abc3, abc4]

解决问题的关键就是使用ListIterator中的add方法添加元素。也就是说无论是迭代还是修改元素,都交给ListIterator来完成。迭代的时候集合对元素进行修改仍然是不允许的

ListIterator listIterator(int index);方法则是指定了迭代的位置,这个位置可以自行制定,而默认(无参)的情况下是0。

此外,ListIterator还提供了比较有趣的两个方法:

 boolean hasPrevious() 
          如果以逆向遍历列表,列表迭代器有多个元素,则返回 true
 E previous() 
          返回列表中的前一个元素。

通过这两个方法可以实现逆向遍历。

6.List接口常用“子类”的特点。

List下有三个类比较常用:Vector、ArrayList、LinkedList。

6.1 Vector类

Vector类自JDK1.0就出现了,它可以说是集合框架的元老级干部。集合框架自JDK2.0出现以后,Vector类就加入了集合框架的队伍并归入了List旗下。Vector类的最大特点就是线程安全,这在整个集合框架中都是少见的。正是因为线程安全,所以执行效率低下,到了现在几乎已经废弃。即使在多线程编程中也不会使用它,而是使用ArrayList加锁代替。Vector内部是一个数组结构,并且是可增长的,步长为100%。Vector增删查询都很慢。

6.2ArrayList类。

ArrayList类是为了替代Vector类而出现的,所以它的功能几乎和Vector类完全相同,但它是非同步的。ArrayList内部也维护了一个变长的数组,增长的步长为50%,查询速度很快。

6.3LinkedList类。

LinkedList是List接口链接列表实现。也就是说我们说的链表。LinkedList最大的特点就是增删速度非常快。

7.LinkedList和ArrayList都有get方法,有什么区别?

两者虽然都是List的子类,但是ArrayList的底层是数组数据结构,在内存中是连续的,所以使用get方法并不用从头开始查找;但是LinkedList底层是链表数据结构,即使使用了get方法,但是仍然需要从头开始查找。

二、Vector类

1.概述。

VectorJDK1.0就已经出现了,在JDK1.2被收入JAVA集合框架中,作为List旗下的一员。它和新出现的collection不同,它是线程安全的。正因为同步,所以效率低,后来被ArrayList所取代。

2.Vector比较List

Vector中有很多方法都被新出现的方法所取代。

 Enumeration<E> elements() 
          返回此向量的组件的枚举。

而Enumeration又是什么呢?

Enumeration是一个接口,它的功能和Iterator是重复的,但是它在JDK1.0就已经出现了。它只有两个方法:

 boolean hasMoreElements() 
          测试此枚举是否包含更多的元素。
 E nextElement() 
          如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。

这两个方法分别对应着Iterator接口中的两个方法:

 boolean hasNext() 
          如果仍有元素可以迭代,则返回 true
 E next() 
          返回迭代的下一个元素。

新的实现应当优先考虑使用Iterator接口而不是Enumeration 接口。

3.代码示例。

package p02.VectorDemo;

import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector; public class VectorDemo
{
public static void main(String[] args) {
Vector v=new Vector();
v.add("abc1");
v.add("abc2");
v.add("abc3");
v.add("abc4"); Demo1(v);
Demo2(v);
} private static void Demo2(Vector v) { for(Iterator it=v.iterator();it.hasNext();)
{
System.out.println(it.next());
} } private static void Demo1(Vector v)
{
for (Enumeration e = v.elements(); e.hasMoreElements();)
{
System.out.println(e.nextElement());
}
} }

使用for循环遍历容器是最靠谱的,这是应当注意的地方。

三、LinkedList类

1.概述。

LinkedList底层是链表数据结构,这就导致了它的内容在内存中并不是连续的。这也使得它增删速度快而查询速度慢。注意,LinkedList中存储的都是对象的地址,即引用,而非对象本身

2.LinkedList特有的方法。

2.1.添加。

 void addFirst(E e) 
          将指定元素插入此列表的开头。
 void addLast(E e) 
          将指定元素添加到此列表的结尾。

2.2.删除

 E removeFirst() 
          移除并返回此列表的第一个元素。
 E removeLast() 
          移除并返回此列表的最后一个元素。
 E pollFirst() 
          获取并移除此列表的第一个元素;如果此列表为空,则返回 null
 E pollLast() 
          获取并移除此列表的最后一个元素;如果此列表为空,则返回 null

后者在JDK1.6之后取代了前者,原因是前者在列表为空的时候抛出了NoSuchElementException异常,而后者则返回Null,这为健壮性的判断创造了更好的条件。

2.3.获取。

 E getFirst() 
          返回此列表的第一个元素。
 E getLast() 
          返回此列表的最后一个元素。
 E peekFirst() 
          获取但不移除此列表的第一个元素;如果此列表为空,则返回 null
 E peekLast() 
          获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null

peekFirst和peekLast方法在JDK1.6之后取代了getFirst方法和getLast方法,原因同上。

四、ArrayList类

1.概述。

ArrayList和Vector类几乎相同,略。

但需要注意的是,ArrayList中存储的是对象的引用,即地址,而非对象本身。如果ArrayList容器发生了al.add(3);这种情况,但是编译器并没有报错,不能认为是集合中可以存储基本数据类型,事实上在这个过程中发生了两件事:自动装箱以及上转型。这和Object obj=3;有着异曲同工之妙。

2.方法。

略。

注意,虽然ArrayList略掉很多,但并不是说它不重要,只是因为方法中和List接口中的差不多,所以就不做介绍了。实际上在开发中最常使用的类就是ArrayList。

java集合框架——List的更多相关文章

  1. Java集合框架List,Map,Set等全面介绍

    Java集合框架的基本接口/类层次结构: java.util.Collection [I]+--java.util.List [I]   +--java.util.ArrayList [C]   +- ...

  2. Java集合框架练习-计算表达式的值

    最近在看<算法>这本书,正好看到一个计算表达式的问题,于是就打算写一下,也正好熟悉一下Java集合框架的使用,大致测试了一下,没啥问题. import java.util.*; /* * ...

  3. 【集合框架】Java集合框架综述

    一.前言 现笔者打算做关于Java集合框架的教程,具体是打算分析Java源码,因为平时在写程序的过程中用Java集合特别频繁,但是对于里面一些具体的原理还没有进行很好的梳理,所以拟从源码的角度去熟悉梳 ...

  4. Java 集合框架

    Java集合框架大致可以分为五个部分:List列表,Set集合.Map映射.迭代器.工具类 List 接口通常表示一个列表(数组.队列.链表 栈),其中的元素 可以重复 的是:ArrayList 和L ...

  5. Java集合框架之map

    Java集合框架之map. Map的主要实现类有HashMap,LinkedHashMap,TreeMap,等等.具体可参阅API文档. 其中HashMap是无序排序. LinkedHashMap是自 ...

  6. 22章、Java集合框架习题

    1.描述Java集合框架.列出接口.便利抽象类和具体类. Java集合框架支持2种容器:(1) 集合(Collection),存储元素集合 (2)图(Map),存储键值对.

  7. Java集合框架实现自定义排序

    Java集合框架针对不同的数据结构提供了多种排序的方法,虽然很多时候我们可以自己实现排序,比如数组等,但是灵活的使用JDK提供的排序方法,可以提高开发效率,而且通常JDK的实现要比自己造的轮子性能更优 ...

  8. (转)Java集合框架:HashMap

    来源:朱小厮 链接:http://blog.csdn.net/u013256816/article/details/50912762 Java集合框架概述 Java集合框架无论是在工作.学习.面试中都 ...

  9. Java集合框架

    集合框架体系如图所示 Java 集合框架提供了一套性能优良,使用方便的接口和类,java集合框架位于java.util包中, 所以当使用集合框架的时候需要进行导包. Map接口的常用方法 Map接口提 ...

  10. Java集合框架(常用类) JCF

    Java集合框架(常用类) JCF 为了实现某一目的或功能而预先设计好一系列封装好的具有继承关系或实现关系类的接口: 集合的由来: 特点:元素类型可以不同,集合长度可变,空间不固定: 管理集合类和接口 ...

随机推荐

  1. P5021 赛道修建 (NOIP2018)

    传送门 考场上把暴力都打满了,结果文件输入输出写错了.... 当时时间很充裕,如果认真想想正解是可以想出来的.. 问你 长度最小的赛道长度的最大值 显然二分答案 考虑如何判断是否可行 显然对于一个节点 ...

  2. Nand Flash 基础

    1. 根据物理结构上的区别,Nand Flash主要分为: SLC(Single Level Cell): 单层式存储 MLC(Multi Level Cell): 多层式存储 TLC(Triple ...

  3. 创建Banner

    org.springframework.boot.SpringApplicationBannerPrinter#print(org.springframework.core.env.Environme ...

  4. 事务背书 ACID, CAP, BASE

    A atomicity 原子性 一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成, C consistency 一致性 在事务开始之前和事务结束以后,数据库的完整性没有被破 ...

  5. netty在rpc MQ中的应用

    https://files.cnblogs.com/files/yszzu/netty-rpc-parent.zip https://github.com/apache/rocketmq/blob/m ...

  6. Yii2 前台控制器访问权限控制

    class BaseController extends Controller { public function behaviors() { return [ 'access' => [ 'c ...

  7. Storm与Spark区别

    Storm擅长于动态处理大量实时生产的小数据块,概念上是将小数据量的数据源源不断传给过程: Spark擅长对现有的数据全集做处理,概念是将过程传给大数据量的数据. 二者设计思路相反.Storm侧重于处 ...

  8. idea+springboot+Mybatis搭建web项目

    使用idea+springboot+Mybatis搭建一个简单的web项目. 首先新建一个项目: 在这里选择Maven项目也可以,但是IDEA为我们提供了一种更方便快捷的创建方法,即Spring In ...

  9. HAL库延时、SYCCNT与SYSTICK

    HAL库驱动中,由于某些外设的驱动需要使用超时判断(比如I2C.SPI.SDIO等),需要精确延时(精度为1ms),使用的是SysTick,但是在操作系统里面,我们需要使用SysTick来提供系统时基 ...

  10. [转]js 判断js函数、变量是否存在

    本文转自:http://blog.csdn.net/liang4571231/article/details/4042519 在进行js编程时,总会出现可能一些函数或者变量未定义而被引用,导致报错的情 ...