JavaSE集合 - List入门与详解

    xiaoxiao2021-11-11  76

    List集合代表一个元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List集合允许加入重复元素,因为它可以通过索引来访问指定位置的集合元素。List集合默认按元素的添加顺序设置元素的索引 。

    【1】List接口

    底层使用数组实现。List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。

    public interface List<E> extends Collection<E> { //... }

    List 集合里添加了一些根据索引来操作集合元素的方法:

    void add(int index, Object ele) boolean addAll(int index, Collection eles) Object get(int index) int indexOf(Object obj) int lastIndexOf(Object obj) Object remove(int index) Object set(int index, Object ele) List subList(int fromIndex, int toIndex)

    JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector(stack是Vector子类)。

    【2】ArrayList

    ArrayList是基于数组实现的List类,它封装了一个动态的增长的、允许再分配的Object[]数组。

    采用数组的形式保存对象,将对象存放在连续的位置中,进行遍历或查看非常方便,支持随机访问(实现了RandomAccess接口),插入或删除时比较麻烦。

    ArrayList 是 List 接口的典型实现类,本质上,ArrayList是对象引用的一个变长数组。ArrayList 是线程不安全的,而 Vector 是线程安全的,但即使为保证 List 集合线程安全,也不推荐使用Vector。

    Arrays.asList(…) 方法返回的 List 集合既不是 ArrayList 实例,也不是 Vector 实例。 Arrays.asList(…) 返回值是一个固定长度的 List 集合。

    如果一开始就知道ArrayList集合需要保存多少元素,则可以在创建它们时就指定initialCapacity大小,这样可以减少重新分配的次数,提供性能,ArrayList还提供了如下方法来重新分配Object[]数组:

    ensureCapacity(int minCapacity): 将ArrayList集合的Object[]数组长度增加minCapacitytrimToSize(): 调整ArrayList集合的Object[]数组长度为当前元素的个数。程序可以通过此方法来减少ArrayList集合对象占用的内存空间

    【3】LinkedList

    implements List<E>, Deque<E>。实现List接口,能对它进行队列操作,即可以根据索引来随机访问集合中的元素。同时它还实现Deque接口,即能将LinkedList当作双端队列使用,自然也可以被当作"栈来使用") 。

    方便插入和删除,但是不支持快速随机访问(没有实现RandomAccess接口),如果需要访问LinkedList中的第n个元素,必须从头开始查找,依次检查n-1个元素。

    对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高。

    新增方法:

    void addFirst(Object obj) void addLast(Object obj) Object getFirst() Object getLast() Object removeFirst() Object removeLast()

    实例代码如下:

    import java.util.*; public class LinkedListTest { public static void main(String[] args) { LinkedList books = new LinkedList(); //将字符串元素加入队列的尾部(双端队列) books.offer("疯狂Java讲义"); //将一个字符串元素加入栈的顶部(双端队列) books.push("轻量级Java EE企业应用实战"); //将字符串元素添加到队列的头(相当于栈的顶部) books.offerFirst("疯狂Android讲义"); for (int i = 0; i < books.size() ; i++ ) { System.out.println(books.get(i)); } //访问、并不删除队列的头部元素 System.out.println(books.peekFirst()); //访问、并不删除队列的最后一个元素 System.out.println(books.peekLast()); //将栈顶的元素弹出"栈" System.out.println(books.pop()); //下面输出将看到队列中第一个元素被删除 System.out.println(books); //访问、并删除队列的最后一个元素 System.out.println(books.pollLast()); //下面输出将看到队列中只剩下中间一个元素: //轻量级Java EE企业应用实战 System.out.println(books); } }

    从代码中我们可以看到,LinkedList同时表现出了双端队列、栈的用法。功能非常强大。


    【4】Vector

    Vector和ArrayList在用法上几乎完全相同,但由于Vector是一个古老的集合,所以Vector提供了一些方法名很长的方法。但随着JDK1.2以后,java提供了系统的集合框架,就将Vector改为实现List接口,统一归入集合框架体系中

    Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全的。

    在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList。Vector总是比ArrayList慢,所以尽量避免使用。

    新增方法:

    void addElement(Object obj) void insertElementAt(Object obj,int index) void setElementAt(Object obj,int index) void removeElement(Object obj) void removeAllElements()

    遍历Vector:

    Vector<String> vector = new Vector<String>(); vector.add("one"); vector.add("tow"); vector.add("three"); vector.add("four"); vector.add("five"); //使用枚举 Enumeration<String> en = vector.elements(); while(en.hasMoreElements()){ String str = en.nextElement(); System.out.println(str); } //使用for for(int i = 0;i<vector.size();i++){ System.out.println(vector.get(i)); } //使用iterator Vector<String> vector = new Vector<String>(); vector.add("one"); vector.add("tow"); vector.add("three"); vector.add("four"); vector.add("five"); Iterator iterator = vector.iterator(); while (iterator.hasNext()) { String str = (String) iterator.next(); System.out.println(str); } //使用 ListIterator ListIterator iListIterator = vector.listIterator(); while (iListIterator.hasNext()) { String str = (String) iListIterator.next(); System.out.println(str); }

    【5】Stack

    Stack是Vector提供的一个子类,用于模拟"栈"这种数据结构(LIFO后进先出) 。 其主要方法如下:

    import java.util.*; public class VectorTest { public static void main(String[] args) { Stack v = new Stack(); //依次将三个元素push入"栈" v.push("Hello"); v.push("World"); v.push("Janus"); //输出:[Hello,World,Janus] System.out.println(v); //访问第一个元素,但并不将其pop出"栈", System.out.println(v.peek()); //依然输出[Hello,World,Janus] System.out.println(v); //pop出第一个元素, System.out.println(v.pop()); //[Hello,World] System.out.println(v); } }

    【6】ListIterator接口

    List 额外提供了一个 listIterator() 方法,该方法返回一个 ListIterator 对象。

    ListIterator 接口继承了 Iterator 接口,提供了专门操作 List 的方法:

    public interface ListIterator<E> extends Iterator<E> { void add() boolean hasPrevious() Object previous() Boolean hasNext() Object next() //... }

    【7】Iterator和ListIterator主要区别

    ① ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历。

    但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历,Iterator就不可以。

    ② ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator 没有此功能。

    ③ ListIterator有add()方法,可以向List中插入对象,而Iterator不能。

    ④ 都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。

    ListIterator<E>接口方法如下:


    【8】ArrayList,Vector, LinkedList的存储性能和特性

    ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢即遍历查找快而插入删除慢。

    Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差。

    而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。

    java提供的List就是一个"线性表接口",ArrayList(基于数组的线性表)、LinkedList(基于链的线性表)是线性表的两种典型实现。 因为数组以一块连续内存来保存所有的数组元素,所以数组在随机访问时性能最好。所以的内部以数组作为底层实现的集合在随机访问时性能最好。

    内部以链表作为底层实现的集合在执行插入、删除操作时有很好的性能。 进行迭代操作时,以链表作为底层实现的集合比以数组作为底层实现的集合性能好 我们之前说过,Collection接口继承了Iterable接口,也就是说,我们以上学习到的所有的Collection集合类都具有"可遍历性"。

    转载请注明原文地址: https://ju.6miu.com/read-678203.html

    最新回复(0)