Arrays.asList() 的输出作为一个 List,它的大小是固定的,没法add,也没法addAll, 因为其底层是一个数组

set

HashSet是检索元素最快的,treeSet(升序)跟linkedSet更强调元素的存储顺序

迭代器Iterators

迭代器并不关系它正在使用的集合的类型, 迭代器是一个对象, 它在序列中移动并选择这个序列中的每个对象, 而客户端程序员不知道也不需要关系这个序列的底层结构, 另外迭代器是一个轻量级对象, 创建它的代价很小
1.使用Iterators()方法, 要求返回一个Iterators, Iterators将返回序列中第一个元素
2.使用next()将获得序列中的下一个元素
3.使用hasNext()将检查序列中是否还有元素
4.使用remove()将会使迭代器最近一个返回的元素被删掉,它删除的是next()的返回值,所以使用它必须是前面有next()
有了Iterators 就不需要考虑集合的数量, 因为有next()跟hasNext(), 当然如果并不对list进行修改,只是单纯的遍历的话,用fori更方便

  1. // collections/CrossCollectionIteration.java
  2. import typeinfo.pets.*;
  3. import java.util.*;
  4. public class CrossCollectionIteration {
  5. public static void display(Iterator<Pet> it) {
  6. while(it.hasNext()) {
  7. Pet p = it.next();
  8. System.out.print(p.id() + ":" + p + " ");
  9. }
  10. System.out.println();
  11. }
  12. public static void main(String[] args) {
  13. List<Pet> pets = Pets.list(8);
  14. LinkedList<Pet> petsLL = new LinkedList<>(pets);
  15. HashSet<Pet> petsHS = new HashSet<>(pets);
  16. TreeSet<Pet> petsTS = new TreeSet<>(pets);
  17. display(pets.iterator());
  18. display(petsLL.iterator());
  19. display(petsHS.iterator());
  20. display(petsTS.iterator());
  21. }
  22. }
  23. /* Output:
  24. 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
  25. 7:Manx
  26. 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
  27. 7:Manx
  28. 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
  29. 7:Manx
  30. 5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug
  31. 0:Rat
  32. */

Iterable

  1. // collections/CrossCollectionIteration2.java
  2. import typeinfo.pets.*;
  3. import java.util.*;
  4. public class CrossCollectionIteration2 {
  5. public static void display(Iterable<Pet> ip) {
  6. Iterator<Pet> it = ip.iterator();
  7. while(it.hasNext()) {
  8. Pet p = it.next();
  9. System.out.print(p.id() + ":" + p + " ");
  10. }
  11. System.out.println();
  12. }
  13. public static void main(String[] args) {
  14. List<Pet> pets = Pets.list(8);
  15. LinkedList<Pet> petsLL = new LinkedList<>(pets);
  16. HashSet<Pet> petsHS = new HashSet<>(pets);
  17. TreeSet<Pet> petsTS = new TreeSet<>(pets);
  18. display(pets);
  19. display(petsLL);
  20. display(petsHS);
  21. display(petsTS);
  22. }
  23. }
  24. /* Output:
  25. 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
  26. 7:Manx
  27. 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
  28. 7:Manx
  29. 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug
  30. 7:Manx
  31. 5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug
  32. 0:Rat
  33. */

ListIterator

ListItertor是一个更强大的Iterator,它只能由各种List生成, Iterator只能向前移动, 单ListIterator可以双向移动, 也就是它在list中指向的位置当前元素previousIndex()跟后一个元素nextIndex(),还可以通过ListIterator()方法来获取集合的第一个元素, 同时它还是可set()对最近访问过的一个元素进行赋值,同时可以用ListIterator(n)来定位到索引为n的的元素

  1. // collections/ListIteration.java
  2. import typeinfo.pets.*;
  3. import java.util.*;
  4. public class ListIteration {
  5. public static void main(String[] args) {
  6. List<Pet> pets = Pets.list(8);
  7. ListIterator<Pet> it = pets.listIterator();
  8. while(it.hasNext())
  9. System.out.print(it.next() +
  10. ", " + it.nextIndex() +
  11. ", " + it.previousIndex() + "; ");
  12. System.out.println();
  13. // Backwards:
  14. while(it.hasPrevious())
  15. System.out.print(it.previous().id() + " ");
  16. System.out.println();
  17. System.out.println(pets);
  18. it = pets.listIterator(3);
  19. while(it.hasNext()) {
  20. it.next();
  21. it.set(Pets.get());
  22. }
  23. System.out.println(pets);
  24. }
  25. }
  26. /* Output:
  27. Rat, 1, 0; Manx, 2, 1; Cymric, 3, 2; Mutt, 4, 3; Pug,
  28. 5, 4; Cymric, 6, 5; Pug, 7, 6; Manx, 8, 7;
  29. 7 6 5 4 3 2 1 0
  30. [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Manx]
  31. [Rat, Manx, Cymric, Cymric, Rat, EgyptianMau, Hamster,
  32. EgyptianMau]
  33. */

链表LinkedList

它在中间插入跟删除比较高效,但是在随机访问上不那么效率,LinkedList 还添加了一些方法,使其可以被用作栈、队列或双端队列(deque)
相关方法

  • getFirst()element() 是相同的,它们都返回列表的头部(第一个元素)而并不删除它,如果 List 为空,则抛出 NoSuchElementException 异常。 peek() 方法与这两个方法只是稍有差异,它在列表为空时返回 null
  • removeFirst()remove() 也是相同的,它们删除并返回列表的头部元素,并在列表为空时抛出 NoSuchElementException 异常。 poll() 稍有差异,它在列表为空时返回 null
  • addFirst() 在列表的开头插入一个元素。
  • offer()add()addLast() 相同。 它们都在列表的尾部(末尾)添加一个元素。
  • removeLast() 删除并返回列表的最后一个元素。

堆栈stack

后进先出,有时候也被称为叠加栈, 压入push(), 弹出pop()->返回并删除栈顶元素, peek()->返回并不删除栈顶元素

  1. // onjava/Stack.java
  2. // A Stack class built with an ArrayDeque
  3. package onjava;
  4. import java.util.Deque;
  5. import java.util.ArrayDeque;
  6. public class Stack<T> {
  7. private Deque<T> storage = new ArrayDeque<>();
  8. public void push(T v) { storage.push(v); }
  9. public T peek() { return storage.peek(); }
  10. public T pop() { return storage.pop(); }
  11. public boolean isEmpty() { return storage.isEmpty(); }
  12. @Override
  13. public String toString() {
  14. return storage.toString();
  15. }
  16. }

这里用ArrayDeque来实现stack
注意java util 跟on java包里都有stack 是重名的

集合Set

set里面是非重复的, 用set的另一个目的是检查归属性, hashSet它来查数据是最快的,hashSet使用散列存储模式, treeSet是使用红黑树结构存储会进行排序,linkedSet也是使用散列,但其注重顺序

队列Queue

先进先出,因此被用作一种可靠的传输方法(因为插入跟取出的顺序是相同的)linkedList实现了Queue接口,并提供了一些方法实现队列
offer() 是与 Queue 相关的方法之一,它在允许的情况下,在队列的尾部插入一个元素,或者返回 falsepeek()element() 都返回队头元素而不删除它,但是如果队列为空,则 element() 抛出 NoSuchElementException ,而 peek() 返回 nullpoll()remove() 都删除并返回队头元素,但如果队列为空,poll() 返回 null ,而 remove() 抛出 *NoSuchElementException

优先级队列PriorityQueue

正常的先进先出 出的那个是等待的时间最长的那个元素, 而这个优先级的先进先出 出去的是优先级最高的那个元素
当在 PriorityQueue 上调用 offer() 方法来插入一个对象时,该对象会在队列中被排序。[^5]默认的排序使用队列中对象的自然顺序(natural order),但是可以通过提供自己的 Comparator 来修改这个顺序。 PriorityQueue 确保在调用 peek()poll()remove() 方法时,获得的元素将是队列中优先级最高的元素。

image.png
可以看到,实际上只有四个基本的集合组件: MapListSetQueue ,它们各有两到三个实现版本(Queuejava.util.concurrent 实现未包含在此图中)。最常使用的集合用黑色粗线线框表示。
虚线框表示接口,实线框表示普通的(具体的)类。带有空心箭头的虚线表示特定的类实现了一个接口。实心箭头表示某个类可以生成箭头指向的类的对象。例如,任何 Collection 都可以生成 IteratorList 可以生成 ListIterator (也能生成普通的 Iterator ,因为 List 继承自 Collection )。

除了treeSet, 其他的set都具有collection相同的接口, list跟collection存在明显的不同,尽管list的方法都在collection中,Queue的方法是独立的, 不需要调用collection,Map跟collection唯一的交集是Map的entrySet跟value会产生collection