list

ArrayList, LinkedList, Vector, Stack是List的4个实现类:

  1. ArrayList 是一个数组队列,相当于动态数组。它由数组实现,随机访问效率高,适合查找更新元素,尾部插入删除有效,元素可以为NULL。但是随机插入、随机删除效率低。容量不足时,“新的容量”=“(原始容量x3)/2 + 1”

 

  1. LinkedList 是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList随机访问效率低,但随机插入、随机删除效率低。

 

  1. Vector 是矢量队列,和ArrayList一样,它也是一个动态数组,由数组实现。但是ArrayList是非线程安全的,而Vector是线程安全的。而Vector的容量增长与“增长系数有关”,若指定了“增长系数”,且“增长系数有效(即,大于0)”;那么,每次容量不足时,“新的容量”=“原始容量+增长系数”。若增长系数无效(即,小于/等于0),则“新的容量”=“原始容量 x 2”

 

  1. Stack 是栈,它继承于Vector。它的特性是:先进后出(FILO, First In Last Out)。

 

使用的场景:

  • 对于需要快速插入,删除元素,应该使用LinkedList。
  • 对于需要快速随机访问元素,应该使用ArrayList。
  •  对于“单线程环境” 或者 “多线程环境,但List仅仅只会被单个线程操作”,此时应该使用非同步的类(如ArrayList)。
  • 对于“多线程环境,且List可能同时被多个线程操作”,此时,应该使用同步的类(如Vector)。

 

/ArrayList///

当我们不知道到底有多少个数据元素的时候,就可使用ArrayList,ArrayList比较适合顺序添加、随机访问的场景。如果知道数据集合有多少个元素,就用数组。

优点:

1、根据下标遍历元素效率较高。

2、根据下标访问元素效率较高。

3、在数组的基础上封装了对元素操作的方法。

4、可以自动扩容。每次扩容现有容量的50%。

 

缺点:

1、插入和删除的效率比较低。其原因是数组中处于被删除元素之后的所有元素都要向数组的前端移动,在数组中间的位置上插入一个元素也是如此。

2、根据内容查找元素的效率较低。

 

 

使用:

 

  • 增加元素到链表中
    • boolean add(Element e)

增加指定元素到链表尾部.

    • void add(int index, Element e)

增加指定元素到链表指定位置.

  • 从链表中删除元素
    • void clear()

从链表中删除所有元素.

    • E remove(int index)

删除链表中指定位置的元素.

    • protected void removeRange(int start, int end)

删除链表中从某一个位置开始到某一个位置结束的元素。

  • 获取链表中的元素
    • E get(int index)

获取链表中指定位置处的元素.如果遇到不行则可以强制转换

    • Object[] toArray()

获取一个数组,数组中所有元素是链表中的元素.(即将链表转换为一个数组)

  • 修改某个元素
    • E set(int index, E element)

将链表中指定位置上的元素替换成新元素。

  • 搜索元素
    • boolean contains(Object o)

如果链表包含指定元素,返回true.

    • int indexOf(Object o)

返回元素在链表中第一次出现的位置,如果返回-1,表示链表中没有这个元素。

    • int lastIndexOf(Object o)

返回元素在链表中最后一次出现的位置,如果返回-1,表示链表中没有这个元素。

  • 检查链表是否为空
    • boolean isEmpty()

返回true表示链表中没有任何元素.

  • 获取链表大小
    • int size()

返回链表长度(链表包含元素的个数)

 

在 Java 中初始化 List 的五种方法 1.构造 List 后使用 List.add 初始化 2.使用 {{}} 双括号语法 3.使用 Arrays.asList 4. 使用 Stream (JDK8) 5. 使用 Lists (JDK9)

//主要方法详解 //ArrayList底层使用的是Java数组来存储集合中的内容,这个数组是Object类型的: transient Object[] elementData; //同时,elementData的访问级别为包内私有,是为了使内部类能够访问到其中的元素。 //使用int类型的size表示数组中元素的个数: private int size; //为了对应不同的构造函数,ArrayList使用了不同的数组: /** * Shared empty array instance used for empty instances. */ private static final Object[] EMPTY_ELEMENTDATA = {}; /** * Shared empty array instance used for default sized empty instances. We * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when * first element is added. */ private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //代码中有个常量,表示数组的默认容量,大小为10: /** * Default initial capacity. */ private static final int DEFAULT_CAPACITY = 10; //(1)构造函数 //常量EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA是为了初始化elementData的。如果为无参构造函数,使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA;如果为含参构造函数,使用EMPTY_ELEMENTDATA: public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } /** * Constructs an empty list with an initial capacity of ten. */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //使用上述构造函数,elementData中没有元素,size为0,不过elementData的长度有可能不同。 //ArrayList还提供了使用集合构造的构造函数: public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } } //函数首先将集合c转化为数组,然后检查转化的类型,如果不是Object[]类型,使用Arrays类中的copyOf方法进行复制;同时,如果c中没有元素,使用EMPTY_ELEMENTDATA初始化。 //(2)trimToSize() //由于表示集合中元素个数的size和表示集合容量的elementData.length可能不同,在不太需要增加集合元素的情况下容量有浪费,可以使用trimToSize方法减小elementData的大小。代码如下: public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } } //代码中有个modCount,这个是继承自AbstractList中的字段,表示数组修改的次数,数组每修改一次,就要增加modCount。可以看到,ArrayList的底层使用Object[]类型的数组存储内容,使用Arrays类来处理数组中的内容。 //(3)ensureCapacity(int minCapacity) //这个方法可以用来保证数组能够包含给定参数个元素,也就是说如果需要的话可以扩大数组的容量。主要代码: public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // any size if not default element table ? 0 // larger than default for default empty table. It's already // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } //首先检查是不是DEFAULTCAPACITY_EMPTY_ELEMENTDATA,如果是的话,说明长度为10,如果不是,将minExpand设为0,比较与minCapacity的大小,然后调用私有函数进行操作: private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } //首先minCapacity和默认大小(10)比较,如果需要扩大容量,继续调用: private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } //然后比较minCapacity和当前长度的大小,如果需要扩容,调用grow方法: private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } //这里,首先增加容量为原来的1.5倍,如果还不够,就用给定的容量minCapacity。同时,ArrayList设置了数组的最大长度MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8,如果没超出,使用Arrays类进行复制,不够的元素使用null。如果超出最大长度,调用函数检查是否溢出: private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } //如果没有溢出就得到合适的minCapacity值,然后复制。 (4)size() //函数返回集合中元素的数量: public int size() { return size; } (5)isEmpty() //函数返回集合是否为空,检查size是否为0,即使容量不为0(没有元素): public boolean isEmpty() { return size == 0; } (6)contains(Object o) //检查集合中是否包含给定的元素: public boolean contains(Object o) { return indexOf(o) >= 0; } //使用indexOf方法,如果返回值非负,表示集合中函数这个元素。 (7)indexOf(Object o) //函数返回集合中给定元素的第一次出现的位置,如果没有就返回-1: public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; } //首先检查o是否为null,如果为null,就返回集合中第一个null元素的位置;如果不为null,就是用equals函数进行相等性检查。之所以这样,是因为如果直接对null调用equals方法,会抛出空指针异常。同时也不能循环遍历数组中的元素调用equals方法检查是否相等,因为ArrayList集合中允许有null元素的存在。 //(8)lastIndexOf(Object o) //函数返回给定元素最后一次出现的位置,如果没有就返回-1: public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; } //原理和indexOf一样,不过对集合元素遍历的时候是倒序遍历的。 //(9)clone() //复制集合: public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(e); } } //本质上就是使用Arrays类进行元素的复制。 (10)toArray() //将集合转化为数组: public Object[] toArray() { return Arrays.copyOf(elementData, size); } //也是使用Arrays的复制操作。 //(11)toArray(T[] a) //转化为数组,和上一个不同的是,上一个返回的数组是Object[]类型的,这个函数返回的数组类型根据参数确定: @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } //(12)get(int index) //返回指定位置的元素,这里用到了一个私有函数: @SuppressWarnings("unchecked") E elementData(int index) { return (E) elementData[index]; } //函数返回数组中指定位置的元素,不过这个函数没有进行下标范围检查,这个工作由另一个私有函数完成: private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } //对于get方法来说,首先调用rangeCheck检查下标,然后调用elementData返回元素: public E get(int index) { rangeCheck(index); return elementData(index); } //(13)set(int index,E element) //设置给定位置的元素为给定的元素,然后返回原来的元素: public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; } //同样,函数也先进行下标检查。 //(14)add(E e) //添加元素: public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } //首先确保有足够的容量,然后再末尾添加元素。 //(15)add(int index,E element) //在指定位置添加元素: public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } //(16)remove(int index) //删除指定位置的元素,然后返回这个元素: public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work return oldValue; } //(17)remove(Object o) //删除指定的元素,如果集合中有,则删除第一次出现的并返回true;如果没有,集合不变并返回false: public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } //在找到集合中的元素后,函数调用私有方法fastRemove来删除这个元素: private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work } //(18)clear() //清空集合,将所有元素设为null,并把size设为0: public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; } //(19)addAll(Collection<? extends E> c) //添加给定集合中的所有元素到集合中,从末尾开始添加: public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } //首先把c集合转为数组,然后确保容量,最后复制。 //(20)add(int index,Collection<? extends E> c) //在指定位置开始添加指定集合中的所有元素: public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount int numMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; } //原理和上一个一样,不同的是复制的位置。 //(21)removeRange(int fromIndex,int toIndex) //删除给定范围内的所有元素: protected void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // clear to let GC do its work int newSize = size - (toIndex-fromIndex); for (int i = newSize; i < size; i++) { elementData[i] = null; } size = newSize; } //(22)removeAll和retainAll //这两个函数都给一个集合参数c,removeAll删除集合中所有在集合c中出现过的元素;retainAll保留所有在集合c中出现的元素。两个函数都调用私有函数batchRemove(): public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, false); } public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, true); } //batchRemove函数如下: private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // clear to let GC do its work for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; } //函数对集合中的元素进行遍历,首先复制集合中的元素,然后检查是否符合complement的要求进行保留。在finally中,复制元素到集合中。并修改相应的size。 //(23)ListIterator<E> listIterator()和ListIterator<E> listIterator(int index) //这两个函数返回在集合上的一个迭代器,不同是第一个是关于所有元素的,第二个是从指定位置开始的。这里ArrayList使用了内部类ListItr, public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); } public ListIterator<E> listIterator() { return new ListItr(0); } //(24)Iterator<E> iterator() //也返回一个迭代器,使用了内部类Itr,继承于ListItr: public Iterator<E> iterator() { return new Itr(); } //(25)List<E> subList(int fromIndex, int toIndex) //返回一个从fromIndex到toIndex的子集合: public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); } //使用了内部类SubList。 // 除了for,foreach外第三种方法循环:使用迭代器 // hasNext(): 返回true表示链表链表中还有元素 // next(): 返回下一个元素 ArrayList<String> a = new ArrayList<>(); System.out.println("Retrieving items using iterator"); for (Iterator<String> it = list.iterator(); it.hasNext();) { System.out.println("Item is: " + it.next()); }

 

 

List<String> list = new ArrayList<>(Arrays.asList("a1", "ab2", "a3", "ab4", "a5", "ab6", "a7", "ab8", "a9")); for (Iterator<String> ite = list.iterator(); ite.hasNext();) {//循环删除List元素的正确方法             String str = ite.next();             if (str.contains("b")) {                 ite.remove();             }         } //错误的循环: 1、for循环遍历list for(int i=0;i<list.size();i++){ if(list.get(i).equals("del")) list.remove(i); //这种方式的问题在于,删除某个元素后,list的大小发生了变化,而你的索引也在变化,所以会导致你在遍历的时候漏掉某些元素。比如当你删除第1个元素后,继续根据索引访问第2个元素时,因为删除的关系后面的元素都往前移动了一位,所以实际访问的是第3个元素。因此,这种方式可以用在删除特定的一个元素时使用,但不适合循环删除多个元素时使用。   //2、增强for循环 for(String x:list){ if(x.equals("del")) list.remove(x); } //这种方式的问题在于,删除元素后继续循环会报错误信息ConcurrentModificationException,因为元素在使用的时候发生了并发的修改,导致异常抛出。但是删除完毕马上使用break跳出,则不会触发报错。  

///LinkedList

 

 

LinkedList是基于链表实现的,LinkedList是一种双向链表。如果只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是对其它指定位置的插入、删除操作,最好选择LinkedList。

允许为空,有序,非线程安全,允许重复。

优点:

在插入、删除集合中任何位置的元素所花费的时间都是一样的—O(1)。

缺点:

它在索引一个元素的时候比较慢,为O(i),其中i是索引的位置。

 

private static void testLinkedListAPIs() { String val = null; //LinkedList llist; //llist.offer("10"); // 新建一个LinkedList LinkedList llist = new LinkedList(); //---- 添加操作 ---- // 依次添加1,2,3 llist.add("1"); llist.add("2"); llist.add("3"); // 将“4”添加到第一个位置 llist.add(1, "4"); System.out.println("\nTest \"addFirst(), removeFirst(), getFirst()\""); // (01) 将“10”添加到第一个位置。 失败的话,抛出异常! llist.addFirst("10"); System.out.println("llist:"+llist); // (02) 将第一个元素删除。 失败的话,抛出异常! System.out.println("llist.removeFirst():"+llist.removeFirst()); System.out.println("llist:"+llist); // (03) 获取第一个元素。 失败的话,抛出异常! System.out.println("llist.getFirst():"+llist.getFirst()); System.out.println("\nTest \"offerFirst(), pollFirst(), peekFirst()\""); // (01) 将“10”添加到第一个位置。 返回true。 llist.offerFirst("10"); System.out.println("llist:"+llist); // (02) 将第一个元素删除。 失败的话,返回null。 System.out.println("llist.pollFirst():"+llist.pollFirst()); System.out.println("llist:"+llist); // (03) 获取第一个元素。 失败的话,返回null。 System.out.println("llist.peekFirst():"+llist.peekFirst()); System.out.println("\nTest \"addLast(), removeLast(), getLast()\""); // (01) 将“20”添加到最后一个位置。 失败的话,抛出异常! llist.addLast("20"); System.out.println("llist:"+llist); // (02) 将最后一个元素删除。 失败的话,抛出异常! System.out.println("llist.removeLast():"+llist.removeLast()); System.out.println("llist:"+llist); // (03) 获取最后一个元素。 失败的话,抛出异常! System.out.println("llist.getLast():"+llist.getLast()); System.out.println("\nTest \"offerLast(), pollLast(), peekLast()\""); // (01) 将“20”添加到第一个位置。 返回true。 llist.offerLast("20"); System.out.println("llist:"+llist); // (02) 将第一个元素删除。 失败的话,返回null。 System.out.println("llist.pollLast():"+llist.pollLast()); System.out.println("llist:"+llist); // (03) 获取第一个元素。 失败的话,返回null。 System.out.println("llist.peekLast():"+llist.peekLast()); // 将第3个元素设置300。不建议在LinkedList中使用此操作,因为效率低! llist.set(2, "300"); // 获取第3个元素。不建议在LinkedList中使用此操作,因为效率低! System.out.println("\nget(3):"+llist.get(2)); // ---- toArray(T[] a) ---- // 将LinkedList转行为数组 String[] arr = (String[])llist.toArray(new String[0]); for (String str:arr) System.out.println("str:"+str); // 输出大小 System.out.println("size:"+llist.size()); // 清空LinkedList llist.clear(); // 判断LinkedList是否为空 System.out.println("isEmpty():"+llist.isEmpty()+"\n"); } /** * 将LinkedList当作 LIFO(后进先出)的堆栈 */ private static void useLinkedListAsLIFO() { System.out.println("\nuseLinkedListAsLIFO"); // 新建一个LinkedList LinkedList stack = new LinkedList(); // 将1,2,3,4添加到堆栈中 stack.push("1"); stack.push("2"); stack.push("3"); stack.push("4"); // 打印“栈” System.out.println("stack:"+stack); // 删除“栈顶元素” System.out.println("stack.pop():"+stack.pop()); // 取出“栈顶元素” System.out.println("stack.peek():"+stack.peek()); // 打印“栈” System.out.println("stack:"+stack); } /** * 将LinkedList当作 FIFO(先进先出)的队列 */ private static void useLinkedListAsFIFO() { System.out.println("\nuseLinkedListAsFIFO"); // 新建一个LinkedList LinkedList queue = new LinkedList(); // 将10,20,30,40添加到队列。每次都是插入到末尾 queue.add("10"); queue.add("20"); queue.add("30"); queue.add("40"); // 打印“队列” System.out.println("queue:"+queue); // 删除(队列的第一个元素) System.out.println("queue.remove():"+queue.remove()); // 读取(队列的第一个元素) System.out.println("queue.element():"+queue.element()); // 打印“队列” System.out.println("queue:"+queue); } }

 

 //遍历方法 private static void byCommonFor(LinkedList<Integer> list) {// 通过一般for循环来遍历LinkedList           if (list == null)               return ;           long start = System.currentTimeMillis();                int size = list.size();   ///         for (int i=0; i<size; i++) {               list.get(i);                   }  /          long end = System.currentTimeMillis();           long total = end - start;           System.out.println("byCommonFor------->" + total+" ms");       }              private static void byForEach(LinkedList<Integer> list) {// 通过for-each来遍历LinkedList           if (list == null)               return ;            long start = System.currentTimeMillis();         /           for (Integer integ:list)                ;    /          long end = System.currentTimeMillis();           long total = end - start;           System.out.println("byForEach------->" + total+" ms");       }           private static void byIterator(LinkedList<Integer> list) {// 通过Iterator来遍历LinkedList           if (list == null)               return ;            long start = System.currentTimeMillis();   /               for(Iterator iter = list.iterator(); iter.hasNext();)               iter.next();    /          long end = System.currentTimeMillis();           long total = end - start;           System.out.println("byIterator------->" + total+" ms");       }           private static void byPollFirst(LinkedList<Integer> list) {//通过PollFirst()遍历LinkedList              if (list == null)               return ;            long start = System.currentTimeMillis();   /          while(list.pollFirst() != null)               ;    /          long end = System.currentTimeMillis();           long total = end - start;           System.out.println("byPollFirst------->" + total+" ms");       }           private static void byPollLast(LinkedList<Integer> list) {// 通过PollLast()遍历LinkedList            if (list == null)               return ;            long start = System.currentTimeMillis();   /          while(list.pollLast() != null)               ;    /          long end = System.currentTimeMillis();           long total = end - start;           System.out.println("byPollLast------->" + total+" ms");       }           private static void byRemoveFirst(LinkedList<Integer> list) {// 通过removeFirst()遍历LinkedList           if (list == null)               return ;            long start = System.currentTimeMillis();   /          try {               while(list.removeFirst() != null)                   ;           } catch (NoSuchElementException e) {           }    /          long end = System.currentTimeMillis();           long total = end - start;           System.out.println("byRemoveFirst------->" + total+" ms");       }           private static void byRemoveLast(LinkedList<Integer> list) {// 通过removeLast()遍历LinkedList           if (list == null)               return ;           long start = System.currentTimeMillis();   /          try {               while(list.removeLast() != null)                   ;           } catch (NoSuchElementException e) {           }   /          long end = System.currentTimeMillis();           long total = end - start;           System.out.println("byRemoveLast------->" + total+" ms");       }     

 

 

链表不支持快速随机访问。如果要查看链表中的第n个元素,就必须从头开始,越过n-1个元素,没有捷径可走。鉴于这个原因,在程序需要采用整数索引访问元素时,一般不选用链表,比如:

LinkedList<String> list=...; String s=list.get(n);

 

LinkedList对象根本不做任何缓存位置信息的处理。其实,在LinkedList类中,get方法会判断当前的位置距离头和尾哪一端更近,然后判断从左向右遍历还是从右向左遍历。

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

 

LinkedList类有三个域,分别是大小、头结点和尾节点:

transient int size; transient Node<E> first; transient Node<E> last;

 

还有两个构造器,一个无参构造器和一个含参构造器:

public java.util.LinkedList(); public java.util.LinkedList(java.util.Collection<? extends E>);

 

其中无参构造器构造一个空的链表,含参构造器根据传进来的一个集合构造一个链表。

LinkedList类中,定义了一个Node<E>内部类来表示一个节点。这个类的定义如下:

private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }

这是一个静态内部类,也没有对外部的引用,这个类有三个域:值,前序节点的引用,后序节点的引用,也有一个构造方法,定义很简单。

如果要创建一个Node节点,可以这样:

Node<E> node=new Node<>(pre,item,next);

 

其中,pre和next分别是前序节点和后序节点的引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值