List接口
List接口是Collection接口的子接口,该List接口中的元素,是有序的,可重复的,可允许多个为null。且可以通过索引对List接口中的元素进行访问。
– List除了继承Collection中的方法,自己新增了与索引相关的方法。
– List特有的方法listIterator()方法。
• 在迭代过程中,不能使用迭代对象和集合对象同时操作集合中的元素。否则会报ConcurrentModificationException。
• ListIterator对象中除了可以在迭代过程中,移除集合中的元素,还可以对集合进行添加,设置。还可以从下往上遍历循环集合中的元素。
• Iterator接口只能从上向下遍历集合中的元素,且在迭代过程中,仅可以移除集合中的元素。
List集合在继承了Collection接口和Iterator接口的基础上新增了与索引操作相关的方法和更具体的迭代方法。
package com.jcxy.demo12;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListDemo
{
public static void main(String[] args)
{
List ls1 = new ArrayList();
ls1.add("aaa");
ls1.add("bbb");
ls1.add("ccc");
ls1.add("ddd");
ls1.add("aaa");
//1-返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
int i1 = ls1.indexOf("aaa");
System.out.println(i1);//0
System.out.println(ls1.indexOf("ddd"));//3
System.out.println(ls1.indexOf("aaaaa"));//-1
//2-返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
System.out.println(ls1.lastIndexOf("aaa"));//4
//3-返回此列表元素的列表迭代器(按适当顺序)。
ListIterator li1 = ls1.listIterator();
//3.1-这种和Collection中的迭代一样.只有先正向打印输出,下面才能逆向打印输出。必须交替进行才可以。可以debug跟踪一下lastSet的变化
while(li1.hasNext())
{
String str = (String)li1.next();
System.out.println(str);
}
//3.2-但是ListIterator比iterator提供更多的方法
//这个可以从后向前打印
while(li1.hasPrevious())
{
String str = (String)li1.previous();
System.out.println(str+"******");
}
// ls1.add("hhhh"); //在迭代期间,如果li1和ls1同时操作集合中的元素会发生ConcurrentModificationException
while(li1.hasNext())
{
String str = (String)li1.next();
if(str.equals("ddd"));
{
//该元素直接插入到 next 返回的下一个元素的前面(如果有)
//cccc直接插入到ddd的前面,所以不会打印出来。
li1.add("cccc");
}
System.out.println(str+"======");
}
// ls1.add("hhhh"); //ConcurrentModificationException
}
}
List接口实现类
ArrayList-可变数组
• 底层由数组实现,查询速度快,增删速度慢。
• ArrayList类是不同步的,如果需要同步,可以使用Collections.synchronizedList(ArrayList对象)方法,使其同步。
Vector-矢量
• 底层也是由数组实现
• Vector类使用与ArrayList基本相同,但是以后用的更多的是ArrayList
• Vector类是同步的类。
• Vector类扩展了含有element的各种方法。
LinkedList-链表
• 底层有双向循环链表实现。查询速度慢,增删速度快。
• LinkedList除了实现父接口中的方法,还扩展了自己的方法。比如在列表的开头及结尾get、remove 和 insert 元素提供了统一的命名方法。
• 此实现不是同步的,想要实现同步,可以使用List list = Collections.synchronizedList(new LinkedList(...));
– Stack类
• JDK中提供了Stack类,但因为其是Vector类的子类,所以,不符合堆栈的特点。
• 自定义Stack类,实现堆栈的功能。
LinkedList中的常用方法
package com.jcxy.demo12;
import java.util.Iterator;
import java.util.LinkedList;
/**
*
* 演示LinkedList实现类中的方法
*
* @author Mr Wang
* @version [V1.00, 2015-12-12]
* @see [相关类/方法]
* @since V1.00
*/
public class Test
{
public static void main(String[] args)
{
LinkedList ls1 = new LinkedList();
// 1-将指定元素添加到此列表的末尾(LinkedList特有),与add方法功能相同
ls1.offer("aaa");
ls1.offer("bbb");
ls1.offer("aaa");
ls1.offer("ccc");
ls1.offer("ddd");
// 2- 将指定元素插入此列表的开头,下面两个方法功能相同
ls1.addFirst("first");
ls1.offerFirst("firstOne");
// 3-将指定元素添加到此列表的结尾,功能相同
ls1.addLast("last");
ls1.offerLast("lastOne");
// 4-返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。
// 反向打印输出
Iterator di = ls1.descendingIterator();
while (di.hasNext())
{
String str = (String)di.next();
System.out.println(str + "*****");
}
// 5-获取但不移除第一个元素
Object obj1 = ls1.element();
System.out.println(obj1);// first
// 6-返回此列表的第一个元素
Object obj2 = ls1.getFirst();
System.out.println(obj2);// first
// 7-返回此列表的最后一个元素
Object obj3 = ls1.getLast();
System.out.println(obj3);// last
// 8-获取但不移除第一个元素,peek 中文 瞥一眼 的意思
Object obj4 = ls1.peek();
System.out.println(obj4);
// 9-获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
Object obj5 = ls1.peekFirst();
System.out.println(obj5);
// 10-获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
Object obj6 = ls1.peekLast();
System.out.println(obj6);
// 11-获取并移除此列表的头(第一个元素)功能与remove一样,但是remove当列表为空是会抛出异常NoSuchElementException
Object obj7 = ls1.poll();
System.out.println(obj7);// firstOne
// 12- 获取并移除此列表的第一个元素;如果此列表为空,则返回 null,与removeFirst功能一样,为空时抛出异常
Object obj8 = ls1.pollFirst();
System.out.println(obj8);// first
// 13-获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。与removeLast功能一样,为空时抛出异常
Object obj9 = ls1.pollLast();
System.out.println(obj9);// lastOne
// 14-将此列表中指定位置的元素替换为指定的元素。
ls1.set(2, "new");// 第二处出现的aaa,索引为2被替换为new
for (Object o : ls1)
{
System.out.println(o + "======");
}
}
}
Vector中的方法介绍
package com.jcxy.demo12;
import java.util.Enumeration;
import java.util.Vector;
/**
*
* Vector向量是同步的,面对并发的修改,
* 迭代器很快就完全失败。
* Vector 的 elements 方法返回的 Enumeration 不是快速失败的。
*
* @author Mr Wang
* @version [V1.00, 2015-12-12]
* @see [相关类/方法]
* @since V1.00
*/
public class Test1
{
/**
*
* Vector类中的方法介绍
* <功能详细描述>
* @param args
* @see [类、类#方法、类#成员]
*/
public static void main(String[] args)
{
Vector v1 = new Vector();
//1-将指定元素添加到此向量的末尾
v1.add("aaa");
v1.add("bbb");
v1.add("ccc");
v1.add("aaa");
v1.add("ddd");
//2-将指定的组件添加到此向量的末尾,将其大小增加 1,方法功能与上面相同
v1.addElement("eee");
//3-返回此向量的当前容量。
System.out.println(v1.capacity());//向量的初始容量为10,当组件的大小超过10以后,向量的容量自动增加10,以此类推。
//4-返回指定索引处的组件。
Object obj1 = v1.elementAt(2);
System.out.println(obj1);//ccc
//5-返回此向量的第一个组件(位于索引 0) 处的项)。
Object obj2 = v1.firstElement();
System.out.println(obj2);//aaa
//6-从此向量中移除全部组件,并将其大小设置为零。下面两个方法功能相同
// v1.removeAllElements();
// v1.clear();
//7-返回此向量的组件的枚举
//功能与iterator相同
Enumeration en = v1.elements();
while(en.hasMoreElements())
{
String str = (String)en.nextElement();
System.out.println(str+"*********");
}
}
}
在Vector向量中我们用到了Enumeration枚举,那它和Iterator、ListIterator有什么不同呢?
Iterator和ListIterator接口
*iterator()方法在Collection接口;
*listIterator()方法在List接口中;
*ListIterator接口中提供了比Iterator接口更多,更丰富的方法。
Iterator与Enumeration两个接口
Iterator迭代器取代了 Java Collections Framework 中的 Enumeration,他们两个实现的功能是相同。
迭代器与枚举有两点不同:
*迭代器允许调用者利用定义良好的语义在迭代期间从迭代器所指向的collection 移除元素。
*方法名称得到了改进。
************************************************************************************************************Stack类
• JDK中提供了Stack类,但因为其是Vector类的子类,由于多态的特性,会改变Stack原有的特征。所以,不符合堆栈的特点。
• 我们可以自定义Stack类,实现堆栈的功能。
<pre name="code" class="java">package com.jcxy.demo12;
import java.util.LinkedList;
import java.util.List;
/**
*
*自定义Stack的原理就是覆盖Stack中基本的方法
* @author Mr Wang
* @version [V1.00, 2015-12-12]
* @see [相关类/方法]
* @since V1.00
*/
public class MyStack
{
LinkedList ll = new LinkedList();
//查看堆栈顶部的对象,但不从堆栈中移除它
public Object peek()
{
//堆栈顶部对象便是linkedlist对象中最后一项
return ll.peekLast();
}
public Object pop()
{
return ll.pop();
}
//把项压入堆栈顶部
public Object push(Object item)
{
//list将项添加到集合开头
ll.offerFirst(item);
return item;
}
public boolean empty()
{
return ll.isEmpty();
}
//返回对象在堆栈中的位置,以 1 为基数
public int search(Object o)
{
//list中以0为基数,所以要加一
return ll.indexOf(o) + 1;
}
}
同理,我们也可以实现自定义的queue
注意: ArrayList类与Vector类异同(了解)
– 相同
• 他们都是Collection或List接口的具体实现类。
• 他们都能存储任意类型的对象。但通常情况下,这些不同的对象都具有相同的父类或父接口。
• 他们都不能存储基本数据类型(primitive);集合对象.add(1),可以添加成功,但内部相当于int->Integer->Object.
• 他们底层都是由可变数组实现的,容量都可以自动扩充。
– 不同
• Vector是同步的,线程安全的,效率较低;ArrayList是不同步的,线程不安全,但效率高。
• Vector缺省情况下,自动增长为原来的一倍空间;ArrayList缺省情况下,自动增长为原来的一半。
– ArrayList, Vector, LinkedList真实开发中,如何选择使用?
– 根据各自类的特点,按照实际需求,选择。