集合類的要點總結
1. Collections.addAll VS Collection.addAll
Collection.addAll只能添加一個Collection類型的對象,而Collections.addAll支持可變參數列表。
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
list1.add("a");
list1.add("b");
list1.add("c");
List<String> list2 = new ArrayList<String>();
list2.addAll(list1);//list2 爲[a,b,c]
Collections.addAll(list2, "e","f");
Collections.addAll(list2, list1.toArray(new String[]{}));//list2爲[a,b,c,e,f,a,b,c]
for(int i=0; i<list2.size(); i++){
System.out.println(list2.get(i));
}
}
2. Arrays.asList
這個方法接收一個可變參數,然後返回一個List類型的變量,但請注意,由於返回的List的內部實現包含的是
Private final E[] a;這樣的東西,所以返回的List對象不可以add和remove,否則就會拋出java.lang.UnsupportedOperationException這個異常。
public static void main(String[] args) {
List<String> strList = Arrays.asList("a","b","c");
strList.add("d");//拋出java.lang.UnsupportedOperationException
strList.remove(0);//拋出java.lang.UnsupportedOperationException
System.out.println(strList);
}
3. 判斷一個集合類是否包含另一個集合類
利用Collection的非靜態方法containsAll(Collection col)進行判定,注意這裏採用的實現方法是遍歷col,調用contains方法一個一個進行判定,而contains方法則利用了equals方法進行判定。
class User{
int age;
String name;
public User(int age , String name){
this.age = age;
this.name = name;
}
public boolean equals(Object object){
User user = (User)object;
return ( this.age==user.age && this.name.equals(user.name) );
}
}
public final class ContainsAllTest {
public static void main(String[] args) {
List<User> list1 = new ArrayList<User>();
list1.add(new User(1,"a"));
list1.add(new User(2,"b"));
list1.add(new User(3,"c"));
List<User> list2 = new ArrayList<User>();
list2.add(new User(1,"a"));
System.out.println(list1.containsAll(list2));//true
}
}
4. Comparable VS Comparator(兩大比較器)
若想讓兩個對象具有可比性,有兩種方式,一種是讓該類直接實現Comparable接口,然後實現其compareTo方法,另一種方法是提供一個Comparator(比較器),比如在Collections.sort中可以自己提供一個比較器,從而可以適用各種各樣的比較。採用Comparable接口的方式只能實現一種比較方法,而採用Comparator則可以實現多種比較(每次比較提供不同的比較器),這其實便是設計模式中的策略模式。
一個使用Comparable的例子
public final class CompareTest {
private static class User implements Comparable{
String name;
int age;
private User(String name , int age){
this.name = name;
this.age = age;
}
//先比較名字,大者則大,若名字相等再比較年齡
public int compareTo(Object obj){
User user = (User)obj;
int result = this.name.compareTo(user.name);
if(result != 0){
return result;
}
return this.age>user.age?1:(this.age<user.age?-1:0);
}
public String toString(){
return name + ":" + age ;
}
}
public static void main(String[] args) {
List<User> users = new ArrayList<User>();
users.add(new User("zhangsan",20));
users.add(new User("lisi",18));
users.add(new User("wangwu",22));
Collections.sort(users);
for(User user : users){
System.out.println(user);
}
}
}
//輸出結果爲
//lisi:18
//wangwu:22
//zhangsan:20
把該例子換成使用Comparator
public final class CompareTest {
private static class User{
String name;
int age;
private User(String name , int age){
this.name = name;
this.age = age;
}
public String toString(){
return name + ":" + age ;
}
}
private static class ComparatorImpl implements Comparator{
@Override
public int compare(Object o1, Object o2) {
User user1 = (User)o1;
User user2 = (User)o2;
int result = user1.name.compareTo(user2.name);
if(result != 0){
return result;
}
return user1.age>user2.age?1:(user1.age<user2.age?-1:0);
}
}
public static void main(String[] args) {
List<User> users = new ArrayList<User>();
users.add(new User("zhangsan",20));
users.add(new User("lisi",18));
users.add(new User("wangwu",22));
Collections.sort(users , new ComparatorImpl());
for(User user : users){
System.out.println(user);
}
}
}
//輸出結果爲
//lisi:18
//wangwu:22
//zhangsan:20
5. 求兩個Collection的交集
利用Collection的retainAll方法
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
list1.add("a");
list1.add("b");
List<String> list2 = new ArrayList<String>();
list2.add("b");
list2.add("c");
list1.retainAll(list2);
System.out.println(list1);
}
//輸出結果爲
//[b]
6. Iterator的三個基本方法
Iterator有三個方法,hasNext,next,remove,其中,remove刪除前一個next返回的那個元素。
public static void main(String[] args) {
List<String> strs = new ArrayList<String>();
strs.add("a");
strs.add("b");
strs.add("c");
Iterator<String> it = strs.iterator();
while(it.hasNext()){
System.out.println(it.next());
it.remove();//刪除上面打出的元素
}
System.out.println("size = " + strs.size());
}
//輸出結果爲:
a
b
cvs
size = 0
7. 專門服務於List的ListIterator
Iterator只有三個基本的方法,支持向前的迭代訪問,而專門針對於List,可以返回一個ListIterator的迭代器,它支持前後雙向的迭代,功能較強大。基本方法有
hasNext,next,hasPrevious,previous,nextIndex,previousIndex,remove,set,add.
8. Stack
Java.util包中有一個叫Stack的類,它直接繼承自Vector,我們知道,Vector 是同步的,所以此種Stack自然也是同步的。由於Vector中有許多不適用於Stack的方法,所以一般不使用此Stack。當要用到Stack的時候,一般情況下我們可以利用LinkedList方便的實現自己的Stack.
如下是一個簡單的自定義Stack的實現
public final class StaclTest {
private static class Stack<T>{
LinkedList<T> list = new LinkedList<T>();
public boolean empty(){
return list.isEmpty();
}
public T peek(){
return list.getFirst();
}
public T pop(){
return list.removeFirst();
}
public void push(T target){
list.addFirst(target);
}
public int size(){
return list.size();
}
}
public static void main(String[] args) {
Stack<String> stack = new Stack<String>();
stack.push("a");
stack.push("b");
stack.push("c");
printStack(stack);
System.out.println("size = " + stack.size());
}
public static <T> void printStack(Stack<T> stack){
int size = stack.size();
for(int i=0; i<size; i++){
System.out.println(stack.pop());
}
}
}
//輸出結果如下
c
b
a
size = 0
9. 認識map中的幾個主要方法
Map是非常重要的一種數據結構,有幾個比較重要的方法,如
containsKey,containsValue,keySet,values,注意keySet方法。此方法返回一個Set類型的集合,但是這個Set裏邊裝的是Map.Entry這種類型的引用,何爲Map.Entry呢?其實,一個Map.Entry裏邊有一個key和value,所以一個Map.Entry就是對一對鍵值對的包裝,所以Map.Entry有getKey和getValue方法也就非常自然了。看一個簡單的例子
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
Set<Map.Entry<String, String>> keySets = map.entrySet();
map.put("1", "a");
map.put("2", "a");
System.out.println(keySets);
Collection<String> values = map.values();
System.out.println(values);
}
// 輸出結果爲
[2=a, 1=a]
[a, a]
10. 瞭解PriorityQueue。
我想從它的名字就可以猜出它是一個有優先級作爲指導的隊列了,就像我們系統中有很多個進程一樣,每個進程都有不同的優先級,這是在j2se1.5中才新引入的。那麼如何設置其優先級呢?其實問題歸結到底還是迴歸到了Comparator(比較器)。
PriorityQueue有如下構造方法
PriorityQueue(int initialCapacity,
Comparator<? super
E> comparator)
第一個參數爲初始化容量大小,第二個爲一個比較器,這樣,你完全可以提供自己的比較器的實現類來指導PriorityQueue如何對元素按優先級進行訪問。注意,隊列只能在一端進行訪問,在另一端進行插入。PriorityQueue能夠保證每次獲取的數據都是按你所願的。但是如果你一下子打印出整個隊列的話,那麼它並不會整個都是排好序的,如下
public final class PriorityQueueTest {
private static class ComparatorImpl implements Comparator{
public int compare(Object obj1 , Object obj2){
int result = ((Integer)obj1).compareTo((Integer)obj2);
return result>0?-1:(result<0?1:0);
}
}
public static void main(String[] args) {
Queue<Integer> priorityQueue = new PriorityQueue<Integer>(10 , new ComparatorImpl());
priorityQueue.add(10);
priorityQueue.add(20);
priorityQueue.add(8);
priorityQueue.add(11);
while(!priorityQueue.isEmpty()){
System.out.println(priorityQueue);
System.out.println("poll():" + priorityQueue.poll());
}
}
}
//運行結果如下
[20, 11, 8, 10]
poll():20
[11, 10, 8]
poll():11
[10, 8]
poll():10
[8]
poll():8
可以看出,直接打出PriorityQueue中的所有元素時並不是都排好序了,但是第一個元素絕對是正確的排序的。這跟它的具體實現有關,具體可以查看源代碼。(底層採用樹型結構存儲)
11. Iterable接口的妙用
Jdk1.5中新增了加強的for語句,也就是foreach statement,它跟Iterable有何關係呢?其實,當一個類實現了Iterable接口後,便可用於foreach statement。看如下例子
public final class IterableTest {
protected User[] users = new User[4];
public User[] getUsers(){
return this.users;
}
private static class User{
private String name;
public User(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
private class MyCollection<T> implements Iterable<T>{
private int index = 0;
@Override
public Iterator<T> iterator() {
return new Iterator<T>(){
@Override
public boolean hasNext() {
return index < users.length;
}
@Override
public T next() {
if(hasNext()){
return (T)users[index++];
}else{
return null;
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
public static void main(String[] args) {
IterableTest myIterable = new IterableTest();
User[] users = myIterable.getUsers();
users[0] = new User("a");
users[1] = new User("b");
users[2] = new User("c");
users[3] = new User("d");
MyCollection<User> myColl = myIterable.new MyCollection<User>();
for(User user : myColl){
System.out.println(user.getName());
}
}
}
//輸出結果如下
a
b
c
d
注意如下代碼
MyCollection<User> myColl = myIterable.new MyCollection<User>();
這是非靜態內部類的創建方式。
當執行時,jvm會自動去調用myColl 中的iterator方法,然後利用返回的Iterator進行迭代。