链表
- arrayList:随机访问性能好,插入和删除效率差
- LinkedList:插入和删除效率高,随机访问性能差
初始化
// 1.使用 Arrays.asList 将数组转化为容器进行初始化,速度最慢
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(1,2,3));
// 2.使用 Collection.addAll() 进行初始化,速度比第一种方案快,但是只能接受容器作为参数
List<Integer> list2 = new ArrayList<Integer>();
list2.addAll(list1);
// 3. 使用 Collections.addAll() 进行初始化,速度最快且参数灵活,首选方案
List<Integer> list3 = new ArrayList<Integer>();
Collections.addAll(list3,1,2,3);
// Array.asList() 与 Collections.addAll() 都是可变参数列表,但是他们有一些区别
List<Snow> snow1 = Arrays.asList(new Powder(),new Crusty(),new Slush());
// 这样创建编译器会报错, 方法无法得到要创建的链表的类型信息
//List<Snow> snow2 = Arrays.asList(new Powder(),new Light(),new Heavy());
List<Snow> snow3 = new ArrayList<Snow>();
// 方法从第一个参数获取类型信息
Collections.addAll(snow3,new Powder(),new Crusty(),new Slush());
class Snow {}
class Powder extends Snow {}
class Light extends Powder {}
class Heavy extends Powder {}
class Crusty extends Snow {}
class Slush extends Snow {}
打印
// 对于数组打印需要使用 Array.toString() 但是容器可以直接打印
System.out.println(Arrays.toString(new Integer[]{1,2,3}));
System.out.println(list1);
链表常用方法
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.isEmpty();
arrayList.contains("red");
arrayList.containsAll(Arrays.asList("red","black"));
arrayList.addAll(Arrays.asList("red","blue","green","white","yellow","grey"));
arrayList.add("black");
//在当前位置插入即 2
arrayList.add(2,"pink");
arrayList.get(2);
arrayList.set(2,"red");
arrayList.remove(4);
//删除出现的第一个
arrayList.remove("red");
arrayList.add("red");
arrayList.add("red");
// 遍历,所有的都删除
arrayList.removeAll(Arrays.asList("red","blue"));
arrayList.indexOf("red");
arrayList.lastIndexOf("red");
List<String> subList = arrayList.subList(1,3);
System.out.println(subList);
System.out.println(subList.indexOf("yellow"));
// 对 subList 的修改会作用到原链表
subList.add("golden");
System.out.println(arrayList);
subList.clear();
System.out.println(arrayList);
LinkedList 除了与 ArrayList 提供的链表常用的方法之外,还提供了对栈,队列,以及双端队列的支持。所以 LinkedList 的方法比 ArrayList 丰富,并且将 LinkedList 向上转型为 List 时,这些这栈,队列,双端队列支持的方法也将不能使用。
队列
Queue 接口 继承了 Collection 接口,并在 COllection 接口的基础上扩展了对容器元素的插入,提取,以及检查操作。每种操作都提供了两种不同的方法,当相应的操作失败时,一种抛出异常而另一种返回一个特殊值(null 或者 false)。插入失败的接口设计针对的是容量大小有限制的队列,一般情况下不会失败。
抛出异常 | 返回特殊值 |
---|---|
add(e) | offer(e) |
remove() | poll() |
element() | peek() |
在队列的使用中,不应该插入 null 值,尽管它的实现 LinkedList 允许插入,但是也不应该这样做,应为队列 poll() 使用 null 作为队列为空的标志。
双端队列(double ended queue)
抛出异常 | 返回特殊值 |
---|---|
addFirst(e)/addLast(e) | offerFirst(e)/offerLast(e) |
removeFirst()/removeLast() | pollFirst()/pollLast() |
getFirst()/getLast() | peekFirst()/peekLast() |
queue和deque 方法对比
queue | deque |
---|---|
add(e) | addFirst(e) |
offer(e) | offerFirst(e) |
remove() | removeFirst() |
poll() | pollFirst() |
element() | getFirst() |
peek() | peekFirst() |
双端队列的接口设计时提供了对栈的支持,即可以将双端队列作为栈来操作。而这种用法要优于旧的 Stack 类。
stack | deque |
---|---|
push(e) | addFirst(e) |
pop() | removeFirst() |
peek() | peekFirst() |
优先队列
在优先队列上调用 offer() 方法插入对象时,这个对象在队列内会被排序。自己定义的类需要实现 comparable 或者提供自动的比较器。
Set
- HashSet
- TreeSet
- LinkedHashSet
Map
- HashMap
- TreeMap
- LinkedHashMap
Collection,Iterator,Iterable
- Collection 和 Iterator 提供了面向接口而不是具体实现的编程方式。除 Map 以外其他的容器都实现了Collection 接口,而所有的 Collection 都有一个返回 Iterator 的方法。
public static <T> void display(Collection<T> collection){
for(T obj : collection){
System.out.print(obj + " ");
}
System.out.println();
}
public static <T> void display(Iterator<T> iterator){
while(iterator.hasNext()){
T obj = iterator.next();
System.out.print(obj + " ");
}
System.out.println();
}
public static void main(String[] args){
String[] array = new String[]{"red","blue","black","red"};
List<String> linkedList = new LinkedList<String>(Arrays.asList(array));
Set<String> hashSet = new HashSet<String>(Arrays.asList(array));
CollectionTest.display(linkedList);
CollectionTest.display(hashSet);
CollectionTest.display(linkedList.iterator());
CollectionTest.display(hashSet.iterator());
}
Map 通过 keySet(),values() 可以返回 COllection ,从而与 Collection 建立联系。
Collection 可以直接使用 foreach 语法,但是 Iterator 不能。但是两者各有优缺点。Collection 接口可以通过继承 AbstractColleciton 类因此有多继承的限制,而使用 Iterator 只需要在类定义一个返回该接口实例的方法。
public class MyCollection extends AbstractCollection<String> {
private String[] array;
public MyCollection(){
super();
array = new String[]{"red","blue","black"};
}
public Iterator<String> iterator() {
return new Iterator<String>() {
private int index = 0;
public boolean hasNext() {
return index < size();
}
public String next() {
return array[index++];
}
};
}
public int size() {
return array.length;
}
public static void main(String[] args){
MyCollection myCollection = new MyCollection();
CollectionTest.display(myCollection);
}
}
public class MyCollection {
private String[] array;
public MyCollection(){
super();
array = new String[]{"red","blue","black"};
}
public Iterator<String> iterator() {
return new Iterator<String>() {
private int index = 0;
public boolean hasNext() {
return index < size();
}
public String next() {
return array[index++];
}
};
}
public int size() {
return array.length;
}
public static void main(String[] args){
MyCollection myCollection = new MyCollection();
CollectionTest.display(myCollection.iterator());
}
}
- Iterable 是 Java SE5 之后添加的新接口,任何实现该接口的类都可以使用 foreach 语句,Colleciton 接口继承了 Iterable 接口。但是数组虽然可以使用 foreach,但是数组并没有实现 Iterable 接口。
public class MyCollection implements Iterable<String> {
private String[] array;
public MyCollection(){
super();
array = new String[]{"red","blue","black"};
}
public Iterator<String> iterator() {
return new Iterator<String>() {
private int index = 0;
public boolean hasNext() {
return index < size();
}
public String next() {
return array[index++];
}
};
}
public int size() {
return array.length;
}
public static void main(String[] args){
MyCollection myCollection = new MyCollection();
for(String color : myCollection){
System.out.print(color + " ");
}
}
}
- 使用适配器模式显式的调用 foreach 语法。
通过上面的例子可以知道,当需要支持 foreach 语法时可以实现 Iterable 接口。但是假设我们希望有多个不同方式来进行迭代,这时可以采用适配器模式。
public Iterable<String> reversed(){
return new Iterable<String>() {
public Iterator<String> iterator() {
return new Iterator<String>() {
private int i = size();
public boolean hasNext() {
return i > 0;
}
public String next() {
return array[--i];
}
};
}
};
}
MyCollection myCollection = new MyCollection();
for(String color : myCollection){
System.out.print(color + " ");
}
System.out.println();
for(String color : myCollection.reversed()){
System.out.print(color + " ");
}