【JAVA】 容纳对象 列表 Lists

概述

a) 列表和数组一样将对象和索引关联——因此,数组和列表是有序的容器。
b) 要进行大量的随机访问,使用ArrayList;要在列表中进行大量插入和删除操作,用LinkedList
c) 队列和堆栈的行为都有LinkedList提供
d) 元素怎么插入就怎么保存

List

Interface List
public interface List extends Collection
介绍
有序集合(也叫做序列Sequence)。使用该接口可以精确地控制元素插入到List中的位置。可以通过下标访问和搜索List中的元素

不像Set,List允许重复元素。更正式来说,List允许多对元素e1和e2,其中e1.equals(e2)。如果List允许null元素,则通常允许多个null元素

List接口为iterator, add, remove, equals和hashCode方法添加了额外的规定。其他继承方法的声明也记录如下。

List接口提供四种访问元素位置(索引)的方法。List与Java数组类似,索引都是从0开始。注意这些操作在有些实现中(例如LinkedList)按与索引值成比例的时间执行(索引越多执行时间越长)。如果调用者不清楚具体实现,则迭代List的元素通常要好于对List进行索引。

List接口提供特殊的迭代器,叫做ListIterator,除Iterator接口提供的常规操作外,还允许元素插入,替换和双向访问(bidirectional access)。提供了一种方法来获得从List的指定位置开始的list迭代器。

List接口提供两种方法搜索指定对象。从性能(performance)的角度来看,在使用这些方法时要小心。在许多实现中,这些方法会执行消耗巨大的线性查询(linear search)

注意:允许列表将自己包含为元素,但要十分谨慎:equals和hashCode方法不能在这样的列表中很好的定义

一些lsit实现对所包含的元素有限制。例如,一些实现禁止null元素,一些对元素的类型有限制。尝试添加不符合要求的元素会抛出未确认的异常,通常是NullPointerException或ClassCastException。尝试查询不合要求的元素会抛出异常,或简单地返回false。

常用方法

  1. int size()
    返回列表元素的个数。如果列表中的元素数超过Integet.MAX_VALUE,则返回Integer.MAX_VALUE

  2. boolean isEmpty()
    如果列表中没有元素,则返回true

  3. boolean contains(Object o)
    如果列表包含特定的那个元素,则返回true。更确切地来说,有且只有至少一个按照(o==null? e==null:o.equals(e))返回的元素e时,则返回true。

  4. Iterator iterator()
    按顺序返回列表的元素的迭代器。

  5. Object[] toArray()
    按顺序(从第一个元素到最后一个元素)返回一个包含该集合所有元素的集合。
    返回的数组是“安全的”,因为此集合不会保留对其的引用。也就是说,即使该集合是有数组支持的,那也要分配新的数组。所以调用者可以自由修改返回的数组。不用担心会影响到原来的数组

  6. boolean add(E e)
    将指定元素添加到列表末尾(the end of this list)(可选操作)
    支持该操作的List对可能添加到此列表的元素有限制。一些列表拒绝添加null元素,其他列表限制元素类型。List类应在文档中说明对添加的元素施加什么样的限制。

  7. boolean remove(Object o)
    移除该列表中第一次出现的指定元素,如果该指定元素存在的话(可选操作)。如果该列表不包含元素,则不被改变。更确切的说,移除符合(o==null?get(i)==null:o.equals(get(i)))的下标i最小的元素(如果存在这样的元素)。如果此列表含有指定元素,或者说,如果此列表因该方法的调用而发生改变,则返回true。

  8. boolean cotainsAll(Collection<?> c)
    如果该列表含有指定集合的所有元素则返回true

  9. boolean addAll(Collection<? extends E> c )
    将指定集合的所有元素按期迭代器返回的顺序添加到列表的末尾。如果在该操作进行时修改了指定的集合,则此操作的行为是不确定的。(注意,只在指定的集合是该列表且非空的前提下,会发生这种情况)

  10. boolean addAll(int index, Collection<? extends E> c)
    将指定集合中的所有元素插入到该列表的指定位置。如果当前位置有元素,就将当前位置的元素和所有后继元素向右一定(增加索引)。新元素将按照指定集合迭代器返回的顺序出现在此列表中。如果在该操作进行时修改了指定的集合,则此操作的行为是不确定的。(注意,只在指定的集合是该列表且非空的前提下,会发生这种情况)

  11. boolean removeAll(Collection<?> c)
    删除此列表的所有同样包含在指定集合中的元素(可选操作)。

  12. boolean retainAll(Collection<?> c)
    只保留此列表中包含在指定集合中的元素(可选操作)。换句话说,就是删除该集合中未包含在指定集合中的所有元素。

  13. default void sort(Comparator<? super E> c)
    使用提供的Comparator比较元素从而给该列表排序

  14. void clear()
    移除该列表中的所有元素(可选操作)。调用该方法后,列表为空

  15. boolean equals(Object o)
    将指定对象与该列表比较。有且只有当指定的对象也是列表,且顺序,大小和所含有的元素一样时,才返回true

  16. int hashCode()
    返回该列表的哈希码值。列表的哈希码由如下计算结果定义:
    int hashCode = 1;
    for(E e : list)
    hashCode = 31*hashCode+(e==null ? 0 : e.hashCode());
    这是为了确保list1.equals(list2)的同时list1.hashCode()==list2.hashCode()

  17. E get(int index)
    返回该列表指定位置(index)的元素

  18. E set(int index, E element)
    将该列表指定位置(index)的元素用给定元素(element)替换(可选操作)

  19. void add(int index, E element)
    在该列表指定位置插入给定元素,并将该位置的元素和在其之后的元素向右移动(下标加一)

  20. E remove(int index)
    移除该列表指定位置上的元素,将在其之后的元素向左移动(下标减一)。返回从该列表移除的元素。

  21. int indexOf(Object o)
    返回给定元素在该列表第一次出现时的下标,不存在则返回-1

  22. int lastIndexOf(Object o)
    返回给定元素在该列表最后一次出现时的下标,不存在则返回-1

  23. ListIterator ListIterator()
    (按顺序)返回此列表中元素的列表迭代器

  24. ListIterator listIterator(int index)
    从列表指定位置开始,(按顺序)返回此列表中元素的列表迭代器。The specifed index indicates the first element that would be returned by an initial call to next. An initial call to previous would return the element with the specified index minus one.

  25. List subList(int fromIndex, int toIndex)
    返回指定范围的一部分列表,(从fromIndex开始到toIndex结束,其中包含fromIndex的元素,不包含toIndex的元素)
    可以用该方法取出一定范围的元素,如:
    list.subList(from, to).clear();

  26. default Spliterator spliterator()
    为此列表的元素创建Spliterator

ArrayList

public class ArrayList
extends AbstractList
implements List, RandomAccess, Cloneable, Serializable

介绍
ArrayList实现List接口相当于可以调整大小的数组。其实现了List的所有可选操作,并允许添加所有元素包括null。除了实现List接口,该类还提供了一些方法来操作内部用于存储列表的数组的大小。(此类大致相当于Vector,但它是不同步的)

size, isEmpty, get, set, iterator和listIterator操作在恒定时间(in constant time)内运行。添加操作在分摊的恒定时间(amortized constant time)内执行,即添加n个元素需要0(n)的时间。所有其他操作在线性时间内运行。与LinkedList相比,恒定因素(constant factor)要低。

每个ArrayList实例都有一个容量(capacity)。容量是用来存储列表元素的数组的大小。容量至少与列表大小一样大(可以比列表的大小大)。随着元素添加到ArrayList,其容量会自动增加。除了增加元素需要恒定平摊时间外,未详细指定增长策略的细节。

在使用ensureCapacity操作添加大量元素之前,应用可以增加ArrayList实例的容量。
这可能会减少增量重分配(incremental reallocation)的数量。

注意:此实现线程不同步。如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步(synchronized externally)。结构修改指的是添加或删除一个或多个元素,或者显式地改变后部数组的大小。仅仅设置元素的值不是结构性的修改。通常通过自然封装了列表的对象来实现线程同步。如果不存在这样的对象,则要使用Collections.synchronizedList方法“包装”列表。该操作最好在创建时完成,以防止不同步的访问意外地发生:
List list = Collections.synchronizedList(new ArrayList(…))

ArrayList类的iterator和listIterator方法返回的迭代器是fail-fast。如果在迭代器创建后的任何时候对列表进行结构性的修改,则除了迭代器自身的remove或add方法,其他所有方法都会导致迭代器抛出ConcurrentModificationException异常。因此,在出现并发修改的情况下,迭代器会快速地失败报错,从而避免了在将来未知的时候出现不确定的行为。

fail-fast机制是java集合中的一种错误机制。当多个线程对同一个集合的内容进行操作是会产生fail-fast时间。例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。
要注意的是fail-fast应该仅用于检测bug

该类是Java集合框架中的一员。

构造方法

  1. public ArrayList()
    初始容量为10的空列表
  2. public ArrayList(Collection<? extends E> c)
    包含指定集合元素的列表,按照其迭代器返回的顺序排列
  3. public ArrayList(int initialCapacity)
    指定初始容量的空列表

主要方法

  1. public void trimToSize()
    将ArrayList实例的容量调整为列表当前大小。使用此操作可以最小化ArrayList的存储
  2. public void ensureCapacity(int minCapacity)
    在需要的情况下,增加ArrayList的容量,以确保其至少可以容纳参数minCapacity指定的元素数量
  3. public int size()
  4. public boolean isEmpty()
  5. public boolean contains(Object o)
  6. public int indexOf(Object o)
  7. public int lastIndexOf(Object o)
  8. public Object clone()
    返回该ArrayList的浅副本(shallow copy)(元素不会被复制)
  9. public Object[] toArray()
  10. public E get(int index)
    获取指定位置的元素
  11. public E set(int index, E element)
    用特定的值替换特定位置的值
  12. public boolean add(E e)
    将特定的元素添加到列表的末尾
  13. public void add(int index, E element)
    在指定位置插入指定的值
  14. public E remove(int index)
    移除指定位置的元素
  15. public boolean remove(Object o)
  16. public void clear()
  17. public boolean addAll(Collection<? extends E> c)
  18. public boolean addAll(int index, Collection<? extends E> c)
  19. protected void removeRange(int fromIndex, int toIndex)
  20. public boolean removeAll(Collection<?> c)
  21. public boolean retainAll(Collection<?> c)
  22. public ListIterator listIterator(int index)
    返回的list迭代器是fail-fast
  23. public ListIterator listIterator()
    返回的迭代器是fail-fast
  24. public Iterator iterator()
    返回的迭代器是fail-fast
  25. public List subList(int fromIndex, int toIndex)
  26. public Spliterator spliterator()
  27. public void replaceAll(UnaryOperator operator)
  28. public void sort(Comparator<? super E> c)

LinkedList

public class LinkedList extends AbstractList implements List, List,Deque, Cloneable, Serializable

简介
双链表实现List和Deque接口。实现所有可选列表操作,并允许所有元素(包括null)
对双链表的所有操作都按预定的执行。索引到链表的操作将从头到尾遍历列表,不论就不就近指定索引。

注意:此实现线程不同步。如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步(synchronized externally)。结构修改指的是添加或删除一个或多个元素,或者显式地改变后部数组的大小。仅仅设置元素的值不是结构性的修改。通常通过自然封装了列表的对象来实现线程同步。如果不存在这样的对象,则要使用Collections.synchronizedList方法“包装”列表。该操作最好在创建时完成,以防止不同步的访问意外地发生:
List list = Collections.synchronizedList(new ArrayList(…))

ArrayList类的iterator和listIterator方法返回的迭代器是fail-fast。如果在迭代器创建后的任何时候对列表进行结构性的修改,则除了迭代器自身的remove或add方法,其他所有方法都会导致迭代器抛出ConcurrentModificationException异常。因此,在出现并发修改的情况下,迭代器会快速地失败报错,从而避免了在将来未知的时候出现不确定的行为。
构造方法:

  1. LinkedList()
    创建一个空列表
  2. LinkedList(Collection<? extends E> c)
    创建一个包含指定集合元素的列表

常用方法

  1. public E getFirst()
    返回该列表的第一个元素
  2. public E getLast()
    返回该列表的最后一个元素
  3. public E removeFirst()
    移除和返回该列表的第一个元素
  4. public E removeLast()
    移除并返回该列表的最后一个元素
  5. public void addFirst(E e)
    在该列表的首部插入指定元素
  6. public void addLast(E e)
    在该列表的尾部插入指定元素
  7. public boolean contains(Object o)
  8. public int size()
  9. public boolean add(E e)
  10. pubilc boolean remove(Object o)
  11. public boolean addAll(Collection<? extends E> c)
  12. public boolean addAll(int index, Collection<? extends E> c)
  13. public void clear()
  14. public E get(int index)
    获取指定位置的元素
  15. public void set(int index, E element)
    将指定位置上的元素替换成指定的元素
  16. public void add(int index, E element)
    在指定位置处插入指定元素
  17. public E remove(int index)
    移除指定位置的元素
  18. public int lastIndexOf(Object o)
  19. public int indexOf(Object o)
  20. public E peek()
    检索(retrieve)但不移除该列表的头元素
  21. public E element()
    检索但不移除该列表的头元素
  22. public E remove()
    检索并移除该列表的头元素
  23. public E poll()
    检索并移除该列表的头元素
  24. public boolean offer(E e)
    将指定的元素添加到该列表的末尾
  25. public boolean offerFirst(E e)
    将指定元素插入到该列表的前面
  26. public boolean offerLast(E e)
    将指定元素插入到该列表的后面
  27. public E peekFirst()
    检索但不移除该列表的第一个元素,如果该列表为空则返回null
  28. public E peekLast()
    检索但不移除该列表的最后一个元素,如果该列表为空则返回null
  29. public E pollFirst()
    检索并移除该列表的第一个元素,如果该列表为空则返回null
  30. public E pollLast()
    检索并移除该列表的最后一个元素,如果该列表为空则返回null
  31. public E pop()
    移除并返回该列表的第一个元素
  32. public boolean removeFirstOccurrence(Object o)
    移除在该列表第一次出现的指定元素。如果该列表没有包含指定元素,则没有改变
  33. public boolean removeLastOccurrence(Object o)
    移除在该列表最后一次出现的指定元素。如果该列表没有包含指定元素,则没有改变
  34. public ListIterator listIterator(int index)
  35. public Iterator descendingIterator()
    返回倒序的迭代器
  36. public Object clone()
  37. public Object[] toArray()
  38. public Spliterator spliterator()

实例

//: List1.java
// Things you can do with Lists
package c08.newcollections;
import java.util.*;

public class List1 {
  // Wrap Collection1.fill() for convenience:
  public static List fill(List a) {
    return (List)Collection1.fill(a);
  }
  // You can use an Iterator, just as with a
  // Collection, but you can also use random
  // access with get():
  public static void print(List a) {
    for(int i = 0; i < a.size(); i++)
      System.out.print(a.get(i) + " ");
    System.out.println();
  }
  static boolean b;
  static Object o;
  static int i;
  static Iterator it;
  static ListIterator lit;
  public static void basicTest(List a) {
    a.add(1, "x"); // Add at location 1
    a.add("x"); // Add at end
    // Add a collection:
    a.addAll(fill(new ArrayList()));
    // Add a collection starting at location 3:
    a.addAll(3, fill(new ArrayList())); 
    b = a.contains("1"); // Is it in there?
    // Is the entire collection in there?
    b = a.containsAll(fill(new ArrayList()));
    // Lists allow random access, which is cheap
    // for ArrayList, expensive for LinkedList:
    o = a.get(1); // Get object at location 1
    i = a.indexOf("1"); // Tell index of object
    // indexOf, starting search at location 2:
    i = a.indexOf("1", 2);
    b = a.isEmpty(); // Any elements inside?
    it = a.iterator(); // Ordinary Iterator
    lit = a.listIterator(); // ListIterator
    lit = a.listIterator(3); // Start at loc 3
    i = a.lastIndexOf("1"); // Last match 
    i = a.lastIndexOf("1", 2); // ...after loc 2
    a.remove(1); // Remove location 1
    a.remove("3"); // Remove this object
    a.set(1, "y"); // Set location 1 to "y"
    // Keep everything that's in the argument
    // (the intersection of the two sets):
    a.retainAll(fill(new ArrayList()));
    // Remove elements in this range:
    a.removeRange(0, 2);
    // Remove everything that's in the argument:
    a.removeAll(fill(new ArrayList()));
    i = a.size(); // How big is it?
    a.clear(); // Remove all elements
  }
  public static void iterMotion(List a) {
    ListIterator it = a.listIterator();
    b = it.hasNext();
    b = it.hasPrevious();
    o = it.next();
    i = it.nextIndex();
    o = it.previous();
    i = it.previousIndex();
  }
  public static void iterManipulation(List a) {
    ListIterator it = a.listIterator();
    it.add("47");
    // Must move to an element after add():
    it.next();
    // Remove the element that was just produced:
    it.remove(); 
    // Must move to an element after remove():
    it.next();
    // Change the element that was just produced:
    it.set("47");
  }
  public static void testVisual(List a) {
    print(a);
    List b = new ArrayList();
    fill(b);
    System.out.print("b = ");
    print(b);
    a.addAll(b);
    a.addAll(fill(new ArrayList()));
    print(a);
    // Shrink the list by removing all the 
    // elements beyond the first 1/2 of the list
    System.out.println(a.size());
    System.out.println(a.size()/2);
    a.removeRange(a.size()/2, a.size()/2 + 2);
    print(a);
    // Insert, remove, and replace elements
    // using a ListIterator:
    ListIterator x = a.listIterator(a.size()/2);
    x.add("one"); 
    print(a);
    System.out.println(x.next());
    x.remove();
    System.out.println(x.next());
    x.set("47");
    print(a);
    // Traverse the list backwards:
    x = a.listIterator(a.size());
    while(x.hasPrevious())
      System.out.print(x.previous() + " ");
    System.out.println();
    System.out.println("testVisual finished");
  }
  // There are some things that only
  // LinkedLists can do:
  public static void testLinkedList() {
    LinkedList ll = new LinkedList();
    Collection1.fill(ll, 5);
    print(ll);
    // Treat it like a stack, pushing:
    ll.addFirst("one");
    ll.addFirst("two");
    print(ll);
    // Like "peeking" at the top of a stack:
    System.out.println(ll.getFirst());
    // Like popping a stack:
    System.out.println(ll.removeFirst());
    System.out.println(ll.removeFirst());
    // Treat it like a queue, pulling elements
    // off the tail end:
    System.out.println(ll.removeLast());
    // With the above operations, it's a dequeue!
    print(ll);
  }
  public static void main(String args[]) {
    // Make and fill a new list each time:
    basicTest(fill(new LinkedList()));
    basicTest(fill(new ArrayList()));
    iterMotion(fill(new LinkedList()));
    iterMotion(fill(new ArrayList()));
    iterManipulation(fill(new LinkedList()));
    iterManipulation(fill(new ArrayList()));
    testVisual(fill(new LinkedList()));
    testLinkedList();
  }
} ///:~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值