Collection與Map
一、collection框架
(1)LIST
list是一種collection,作用是收集對象,並以索引的方式保留收集的對象的順序。其操作類之一就是Java.utl.ArrayList.ArrayList特性:隨機查找(list.get[i]),ArrayList內部就是用Object來保存收集的對象。此時就考慮到了數組的特性。根據數據結構內容我們只數組的好處就是隨機存儲速度快,排序等就可以考慮使用ArrayList
package Learn; import java.util.ArrayList; import java.util.Iterator; importView Codejava.util.List; import java.util.Scanner; public class ListDemo { public static void main(String[] args) { List name=new ArrayList();//收集信息的list collectNameTo(name);//收集函數 System.out.println("輸出訪客名單:"); printUpperCase(name);//輸出收集到的信息 } /** *@authorwbm *@param List *@deprecated通過控制臺輸入訪客的名稱,如果遇到quit則退出輸入訪客名稱的循環,每次循環都把收集到的信息通過List.add(信息對象)收集到list中去 */ static void collectNameTo(List names){ Scanner console=new Scanner(System.in);//控制臺輸入信息 while(true){ System.out.println("訪客名稱:"); String name=console.nextLine(); if(name.equals("quit")){ break; } names.add(name);//把控制臺輸入的信息放入到list中去 } } /** *通過for循環把傳進來的List通過索引獲取list元素並轉換為string性,然後通過string的toUpperCase()轉為大寫 */ static void printUpperCase(List names){ for (int i = 0; i < names.size(); i++) { String name=(String) names.get(i);//通過索引獲得收集的信息 System.out.println(name.toUpperCase()); } } }
LinkedList特性:采用鏈接結構。鏈接結構簡單代碼如下。
package Learn; public class LinkListDemo { private class Node{ Object o; Node next; Node(Object o){ this.o=o; } } private Node first; public void add(Object elem){ Node node=new Node(elem); if(first==null){ first=node; } else{ append(node); } } private void append(Node node){ Node last=first; while(first.next!=null){ last=last.next; } last.next=node; } public int size(){ int count=0; Node last=first; while(last.next!=null){ last=last.next; count++; } return count; } public Object get(int index){ checkSize(index); return findElemof(index); } private void checkSize(int index)throws IndexOutOfBoundsException{ int size=size(); if(index>=size){ throw new IndexOutOfBoundsException( String.format("index:%d size:%d", index,size)); } } private Object findElemof(int index){ int count=0; Node last=first; while(count<index){ last=last.next; count++; } return last.next; } }View Code
(2)set
也是收集對象,但是對象相同則不重復收集。知道不重復單詞個數有幾個代碼如下。
public static void mian(String[] args) { // TODO Auto-generated method stub Scanner scanner=new Scanner(System.in); System.out.println("請輸入英文"); Set words=tokenSet(scanner.nextLine());//scanner.nextLine()String類型 System.out.printf("不重復的字有%d個:%s%n",words.size(),words); } static Set tokenSet(String line){ String[] tokens=line.split(" ");//根據空白切割字符串 return new HashSet(Arrays.asList(tokens));//使用HashSet收集字符串 }View Code
使用set時得告訴怎樣的對象是相同,這時要用對象的hashCode()和equals()來判斷對象是夠相同。HashSet的操作哦該娘是,在內存中開設空間,每個空間都會有哈希編碼,這些空間稱為哈希桶,如果對象要加入哈希桶,則要調用對象的hashcode(),並嘗試放入對應的哈希桶中,如果哈希桶中沒有對象就放入,如果有對象就調用equals()進行比較。有無equals和hashcode的對比代碼如下
package Learn; import java.util.HashSet; import java.util.Set; class Student { private String name; private String number; Student(String name,String number){ this.name=name; this.number=number; } @Override public String toString() { return "Student [name=" + name + ", number=" + number + "]"; } } package Learn; import java.util.HashSet; import java.util.Set; public class Students { public static void main(String[] args) { Set students=new HashSet(); students.add(new Student("b","c")); students.add(new Student("b","c")); students.add(new Student("q","c")); System.out.println(students); } } 結果: [Student [name=q, number=c], Student [name=b, number=c], Student [name=b, number=c]] package Learn; import java.util.HashSet; import java.util.Set; class Student { private String name; private String number; Student(String name,String number){ this.name=name; this.number=number; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((number == null) ? 0 : number.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (number == null) { if (other.number != null) return false; } else if (!number.equals(other.number)) return false; return true; } @Override public String toString() { return "Student [name=" + name + ", number=" + number + "]"; } } 結果: [Student [name=b, number=c], Student [name=q, number=c]]View Code
java.util.TreeSet不僅有收集不重復對象的能力,還可以用紅黑樹的方式排序收集到的對象,條件就是收集到的對象必須是Comparable(否則會拋出ClassCastException),或者是在創建的是後指定comparator對象
(3)quene
支持隊列操作,收集的對象加入至尾部,取得的對象時從前部,quene繼承自collection所以有add、remove、element等方法然而quene定義了自己的offer、poll、peak等方法主要區別在於,add、remove、element等方法操作失敗時會拋出異常,而offer、poll、peak會返回特定的值。對象需要使用隊列且長度受限是用通常使用poll、offer、peak方法。從架構圖可知linkedList不僅操作了queue的行為也操作了list的行為。所以可以將linkedlist當做隊列來使用。
簡單的代碼實例如下:
package Learn; public interface Request { void execute(); } package Learn; import java.util.*; /** * offer是在隊列前端加入對象成功會返回trues失敗會返回false。 * poll是去除隊列的前端對象,若隊列為空則返回null。 * peak是取得前端對象但是不取出若為空則返回null。 * */ public class RequestQuene{ public static void main(String[] args) { Queue requests=new LinkedList(); offerRequestTo(requests); process(requests); } static void offerRequestTo(Queue requests){ //請求加入隊列 for(int i=1;i<6;i++){ Request request=new Request(){ @Override public void execute() { // TODO Auto-generated method stub System.out.printf("處理數據%f%n",Math.random()); } }; requests.offer(request); System.out.println(requests.offer(request)); } } static void process(Queue requests){ //處理隊列中的請求 while(requests.peek()!=null){ Request request=(Request)requests.poll(); request.execute(); } } }View Code
如果想要對隊列的前端和尾端進行操作,在前端加入對象和取出對象,在尾端加入對象和取出對象,queue的子接口Deque就定義了該行為。deque中定義addFirst()、removeFirst()、getFirst()、addLast()、
removeLast()、getLast()等方法,操作失敗時會拋出異常。而offerFirst()、pollFirst()、peekFirst()、offerLast()、pollLast()、peekLast()操作失敗會返回特定的值。java.util.ArrayDeque操作了Deque接口,操作使用容量有限的堆棧的簡單實例如下
package Learn; import java.util.*; public class Stack { private Deque elems=new ArrayDeque(); private int capacity; Stack(int capacity){ this.capacity=capacity; } public boolean push(Object elem){ if(isFull()){ return false; } else{ return elems.offerLast(elem); } } private boolean isFull(){ return elems.size()+1>capacity; } public Object pop(){ return elems.pollLast(); } public Object peek(){ return elems.peekLast(); } public int size(){ return elems.size(); } public static void main(String[] args) { Stack stack=new Stack(5); stack.push("justin"); stack.push("wbm"); stack.push("wcy"); System.out.println(stack.pop()); System.out.println(stack.pop()); System.out.println(stack.pop()); } } 結果: wcy wbm justin 堆棧是先進後出View Code
queue的操作類之一java.util.PriorityQueue也是,收集至PriorityQueue的對象,會根據你指定的優先權來決定對象在隊列中的順序,優先的告知,要不是對象必須是comparable,或者是在創建PriorityQueue時指定comparator對象。
(3)Interable與Iterator
iterator方法JDK5之前是定義在collection中在JDK5之後定義在iterable;具體的一些好處和細節如下代碼。
//收集LIst對象 static void forEachList(List list){ int size=list.size(); for(int i=0;i<size;i++){ System.out.println(list.get(i)); } } //收集set對象 static void forEachSet(Set set){ for(Object o:set.toArray()){ System.out.println(o); } } //收集queue對象 static void forEachQueue(Queue queue){ while(queue.peek()!=null){ System.out.println(queue.poll()); } } //含有這個方法的類是util,那麽你就可以指定使用util.<String> elemOf()的方式指定E的實際類型 public static<E> E elemOf(E[] objs,int index){ return objs[index]; } //無論是Queue、List、Set都會有iterator方法JDK5之前是定義在collection中在JDK5之後定義在iterable static void forEachCollection(Collection collection){ Iterator iterator=collection.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } } static void forEachIterable(Iterable iterable){ Iterator iterator=iterable.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } }View Code
package Learn; import java.util.ArrayDeque; import java.util.Arrays; import java.util.HashSet; import java.util.List; public class forEach { public static void main(String[] args) { List names=Arrays.asList("ww","bb","mm");//靜態方法aslist接收不定長自變量將其指定為List forEach(names);//list是一種Iterable. forEach(new HashSet(names));//List是一種collection,hashSet是一種collection接收collection的構造函數所以list可以用來創建hashset forEach(new ArrayDeque(names));//同理 } static void forEach(Iterable iterable){ for (Object object : iterable) { System.out.println(object); } } }View Code
(4)comparable與comparator
1. comparable(comparaTo())
在收集對象之後,對對象排序是常用的動作,我們不用親自操作排序算法,java.util.collections
List numbers=Arrays.asList(10,5,1,9,8,9,7);
Collections.sort(numbers);
System.out.println(numbers);
結果為:[1, 5, 7, 8, 9, 9, 10]
View Code
如果沒有說明list元素的比較會出現錯誤
package Learn; import java.util.HashSet; import java.util.Set; class Student { private String name; private String number; Student(String name,String number){ this.name=name; this.number=number; } @Override public String toString() { return "Student [name=" + name + ", number=" + number + "]"; } } package Learn; import java.util.Arrays; import java.util.Collections; import java.util.List; public class Students { public static void main(String[] args) { List students=Arrays.asList(new Student("b","c"),new Student("b","c"),new Student("q","c")); Collections.sort(students); System.out.println(students); } } 出現: java.lang.ClassCastException:View Code
collections.sort()的操作對象必須操作java.lang.comparable接口,這個接口有compareTo()方法的返回值必須大於0,等於0或小於0的整數。
package Learn; import java.util.HashSet; import java.util.Set; public class Student implements Comparable<Student> { private String name; private String number; Student(String name,String number){ this.name=name; this.number=number; } @Override public String toString() { return "Student [name=" + name + ", number=" + number + "]"; } @Override public int compareTo(Student o) { // TODO Auto-generated method stub return Integer.parseInt(this.number)-Integer.parseInt(o.number); } } package Learn; import java.util.Arrays; import java.util.Collections; import java.util.List; public class Students { public static void main(String[] args) { List students=Arrays.asList(new Student("b","1"),new Student("b","3"),new Student("q","2")); Collections.sort(students); System.out.println(students); } } 結果為 [Student [name=b, number=1], Student [name=q, number=2], Student [name=b, number=3]]View Code
2.compatator(compare())
如果對象無法操作comparable的話呢?比如String本身有操作Comparable,所以可以按字母的排序如果我想要把字母排序的順序反過來呢?String是final的類型不能被繼承所以無法重新定義compareTo()方法。Collection有另一個重載版本,可以接受java.lang.Comparator接口的操作對象。流程:1.定義一個comparator:class StringComparator implements<String>{ public int compare(String s1,String s2){ return s1.compareTo(s2);}} 2.調用:Collections.sort(List,new StringComparator());
package Learn; import java.util.Comparator; public class StringComparator implements Comparator <String> { @Override public int compare(String o1, String o2) { // TODO Auto-generated method stub return -o1.compareTo(o2); } } package Learn; import java.util.Arrays; import java.util.Collections; import java.util.List; public class sort { public static void main(String[] args) { List<String> words=Arrays.asList("B","A","C"); Collections.sort(words,new StringComparator()); System.out.println(words); } } 結果 [C, B, A]View Code
二、Map框架
三、簡單泛型的使用
在使用Collection收集對象時,由於事先不知道對象的形態使用的是Object來收集,取回對象也是Object,所以執行期間失去了形態的信息。所以取回對象之後要記得對象的真正的類型,然後讓對象重新扮演
自己的類型。
List names=Array.asList("ww","bb","mm"); String name=(String)name.get(0); ArrayList<String> names= new ArrayList<String>(); names.add("justin"); names.add("wbm"); names.add(new Long(10));//編譯會出錯沒法通過。 String name1=names.get(0); string nmae2=names.get(1);View Code
靜態方法上定義類型
//含有這個方法的類是util,那麽你就可以指定使用util.<String> elemOf()的方式指定E的實際類型 public static<E> E elemOf(E[] objs,int index){ return objs[index]; }
Utilizes
Collections:是針對集合類的一個幫助類,提供了操作集合的工具方法:一系列靜態方法實現對各種集合的搜索、排序、線程
安全化等操作。
Arrays:針對數組的一個幫助類,提供了操作arrays的工具方法:一系列靜態方法對各種數組的搜索、排序等操作
Collection與Map