java基础----Java Collections Framework
一、類集概述
1.1、類集的引入
最早的時候可以通過對象數(shù)組保存一組數(shù)據(jù),但是慢慢的發(fā)現(xiàn)如果程序中都使用對象數(shù)組開發(fā)的話,本身會存在大小的限制問題,即:所有的數(shù)組的大小是不可改變的,但是從實際的開發(fā)來看,有很多的時候是根本就無法知道到底要開辟多少的數(shù)組空間,后來通過鏈表解決類此類問題,但是如果每一次的開發(fā)中都使用鏈表的話,肯定很麻煩,所以在Java中專門提供了一套動態(tài)對象數(shù)組的操作類——類集框架,在Java中類集框架實際上也就是對數(shù)據(jù)結(jié)構(gòu)的Java實現(xiàn)。
1.2、主要接口
在Java中類集框架里,為了操作方便提供了一系列的類集的操作接口,主要的操作接口有以下三個:
· Collection:存放單值的最大父接口 public interface?Collection<E>?extendsIterable<E>
· Map:是存放一對的內(nèi)容?????????? ?public? interface?Map<K,V>
· Iterator:輸出作用??????????????public? interface?Iterator<E>
在以上的三個接口中Collection接口并不會被直接使用,而都使用它的兩個子接口:List、Set。
在Collection接口中定義了如下的幾個核心操作:
| No. | 方法名稱 | 類型 | 描述 |
| 1 | public boolean add(E e) | 普通 | 向集合中增加元素 |
| 2 | public void clear() | 普通 | 刪除集合中的全部內(nèi)容 |
| 3 | public boolean contains(Object o) | 普通 | 判斷指定內(nèi)容是否存在 |
| 4 | public Iterator<E> iterator() | 普通 | 為Iterator接口實例化 |
| 5 | public boolean remove(Object o) | 普通 | 從集合中刪除元素 |
| 6 | public int size() | 普通 | 取得集合的大小 |
| 7 | public Object[] toArray() | 普通 | 將集合變?yōu)閷ο髷?shù)組輸出 |
| 8 | public <T> T[] toArray(T[] a) | 普通 | 將集合變?yōu)閷ο髷?shù)組輸出 |
二、允許重復(fù)的子接口:List
List接口本身屬于Collection的子接口,但是List子接口本身大量的擴充了Collection接口,主要的擴充方法如下:
| No. | 方法名稱 | 類型 | 描述 |
| 1 | public void add(int index,E element) | 普通 | 在指定的位置上增加內(nèi)容 |
| 2 | public E get(int index) | 普通 | 取得指定位置上的內(nèi)容 |
| 3 | public E set(int index,E element) | 普通 | 修改指定位置的內(nèi)容 |
| 4 | public ListIterator<E> listIterator() | 普通 | 為ListIterator接口實例化 |
| 5 | public E remove(int index) | 普通 | 刪除指定位置上的內(nèi)容 |
既然要使用接口,那么就一定要依靠子類進行父接口的實例化。
1、新的子類:ArrayList
ArrayList子類是在進行List接口操作中使用最多的一個子類,那么此類定義如下:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable
那么下面通過代碼來觀察基本的使用范例:設(shè)置內(nèi)容
package list;import java.util.ArrayList;import java.util.List;public class ArrayListDemo01 {public static void main(String[] args) {List<String> all = new ArrayList<String>();// 實例化List接口all.add("hello");// 向集合中增加內(nèi)容all.add("hello");// 向集合中增加內(nèi)容all.add("world");// 向集合中增加內(nèi)容all.add("!!!");// 向集合中增加內(nèi)容for (int x = 0; x < all.size(); x++) {System.out.println(all.get(x)) ;}}}2、舊的子類:Vector
?Vector子類實際上是最早的數(shù)據(jù)結(jié)構(gòu)的實現(xiàn)類,也稱為向量,但是在JDK 1.0的時候并沒有所謂現(xiàn)在的類集框架的概念,那么只是單單的提供了一個這樣的操作類而已,后來到了JDK 1.2之后提出了類集的框架,而且也提供了大量的類集的操作接口,所以為了保留此類的使用,在JDK 1.2之后讓其多實現(xiàn)了一個List的接口,這樣才被保留下來繼續(xù)使用。
但是,不管是使用何種子類的,最終的代碼的操作形式永遠(yuǎn)是一樣的,因為所有的子類最終都必須發(fā)生向上轉(zhuǎn)型的關(guān)系為父接口進行對象的實例化。
import java.util.List;import java.util.Vector;public class VectorDemo {public static void main(String[] args) {List<String> all = new Vector<String>();// 實例化List接口all.add("hello");// 向集合中增加內(nèi)容all.add("world");// 向集合中增加內(nèi)容all.add("!!!");// 向集合中增加內(nèi)容for (int x = 0; x < all.size(); x++) {System.out.println(all.get(x)) ;}}}3、ArrayList和Vector的區(qū)別
?從代碼的最終的操作形式上可以發(fā)現(xiàn),代碼的輸出結(jié)果與之前是一樣的,而且沒有區(qū)別,但是兩者的區(qū)別還在于其內(nèi)部的組成上。
| No. | 區(qū)別點 | ArrayList | Vector |
| 1 | 推出時間 | JDK 1.2之后 | JDK 1.0的時候推出 |
| 2 | 線程處理 | ArrayList采用異步處理 | 采用同步處理 |
| 3 | 性能 | 速度較快 | 速度相對較慢 |
| 4 | 安全性 | 非線程安全性的操作 | 屬于線程安全的操作 |
| 5 | 輸出 | 由于都是List接口的子類,所以都可以依靠size()和get()兩個方法完成循環(huán)輸出 | |
| for、Iterator、ListIterator | for、Iterator、ListIterator、Enumeration | ||
三、不允許重復(fù)的子接口:Set
?List接口中的內(nèi)容是允許重復(fù)的,但是如果現(xiàn)在要求集合中的內(nèi)容不允許重復(fù)的話,則就可以使用Set子接口完成,Set接口并不像List接口那樣對Collection接口進行了大量的擴充,而與Collection接口的定義是完全一樣的。與List接口一樣,如果要想使用Set接口則一定也要通過子類進行對象的實例化,常用的兩個子類:HashSet、TreeSet。
3.1、散列存放的子類:HashSet
import java.util.HashSet; import java.util.Set;public class HashSetDemo {public static void main(String[] args) {Set <String> all = new HashSet<String>();all.add("W");all.add("W");//重復(fù)設(shè)置all.add("B");all.add("X");all.add("C");all.add("A");all.add(null);System.out.println(all) ; }} //結(jié)果為 [null, W, A, B, C, X]?在Set接口中不允許有重復(fù)的元素出現(xiàn),而且發(fā)現(xiàn)與List接口不同的是,List采用的是順序的方式加入的元素,而Set中的內(nèi)容并沒有任何的順序,屬于散列存放的。
3.2、排序存放的子類:TreeSet
?TreeSet操作的子類是使用順序的方式保存里面的元素,
import java.util.Set; import java.util.TreeSet;public class TreeSetDemo {public static void main(String[] args) {Set<String> all = new TreeSet<String>();all.add("B");all.add("B");all.add("X");all.add("C");all.add("A");//all.add(null); //不能添加null,否則運行會出現(xiàn)java.lang.NullPointerException異常System.out.println(all); // 結(jié)果是[A, B, C, X]}}此時,沒有重復(fù)的內(nèi)容,而且可以發(fā)現(xiàn)雖然加入的時候沒有任何的順序,但是輸出的時候卻是按照順序的方式輸出。
3.3、關(guān)于排序的說明
TreeSet子類的內(nèi)容是允許進行排序的,那么下面就使用這個子類完成一個任意類型的排序操作。
如果多個對象要想進行排序,則無論在何種情況下都必須使用Comparable接口完成,用于指定排序的規(guī)則。但是在進行排序的時候?qū)嶋H上每一個類中的屬性最好都進行判斷。
package set; import java.util.Set; import java.util.TreeSet;class Person implements Comparable<Person> {private String name;private int age;public Person(String name,int age) {this.name = name;this.age = age;}public String toString() {return"姓名:" +this.name +",年齡:" +this.age;}@Overridepublic int compareTo(Person o) {if (this.age < o.age) {return 1;} else if (this.age > o.age) {return -1;} else {return this.name.compareTo(o.name);}}}public class SortDemo {public static void main(String[] args) {Set<Person> all = new TreeSet<Person>(); all.add(new Person("A", 18));all.add(new Person("B", 20));all.add(new Person("B", 20));//這個添加不進去all.add(new Person("C", 20));System.out.println(all);}} //[姓名:B,年齡:20, 姓名:C,年齡:20, 姓名:A,年齡:18]3.4、關(guān)于重復(fù)元素的說明(TreeSet靠compareTo方法判斷重復(fù)元素,而HashSet靠equals()和hashCode()來判斷重復(fù)元素),
證明如下。
Comparable可以完成TreeSet類的重復(fù)元素的判斷,如果真的可以通用的話,那么在HashSet中也一樣可以。將上例中的TreeSet改成HashSet,代碼如下所示,發(fā)現(xiàn)可以添加兩個new Person("B", 20),Set接口不是不能添加重復(fù)元素嗎?說明重復(fù)元素的判斷并不想我們想象的那樣。
package set; import java.util.HashSet; import java.util.Set;class Person implements Comparable<Person> {private String name;private int age;public Person(String name,int age) {this.name = name;this.age = age;}public String toString() {return"姓名:" +this.name +",年齡:" +this.age;}@Overridepublic int compareTo(Person o) {if (this.age < o.age) {return 1;} else if (this.age > o.age) {return -1;} else {return this.name.compareTo(o.name);}}}public class SortDemo {public static void main(String[] args) {Set<Person> all = new HashSet<Person>(); all.add(new Person("A", 18));all.add(new Person("B", 20));all.add(new Person("B", 20));//這個能添加進去,因為現(xiàn)在在HashSet中Comparable接口并不能使用。//也就是說真正要去掉重復(fù)元素的操作并不是靠Comparable完成的all.add(new Person("C", 20));System.out.println(all);}} //[姓名:B,年齡:20, 姓名:A,年齡:18, 姓名:B,年齡:20, 姓名:C,年齡:20]但是,從實際的結(jié)果來看,現(xiàn)在并沒有完成此類內(nèi)容,因為現(xiàn)在在HashSet中Comparable接口并不能使用。也就是說真正要去掉重復(fù)元素的操作并不是靠Comparable完成的,而是靠兩個方法的作用,在Object類中定義:
| No. | 方法名稱 | 類型 | 描述 |
| 1 | public boolean equals(Object obj) | 普通 | 判斷是否相等 |
| 2 | public int hashCode() | 普通 | 對象編碼 |
hashCode()就相當(dāng)于一個對象的唯一的編號,而如果要想進行具體的內(nèi)容驗證,就需要使用equals()方法完成。hashCode()方法返回的是一個數(shù)字,那么很明顯,就必須通過一種算法,可以完成一個唯一的編號。hashCode是本地方法, public native int hashCode();和開發(fā)環(huán)境有關(guān)。如果現(xiàn)在使用的是eclipse進行開發(fā)的話,則此工具將會自動生成編號和比較。
package set; import java.util.HashSet;import java.util.Set;class Person{private String name;private int age;public Person(String name,int age) {this.name = name;this.age = age;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result +age;result = prime * result + ((name ==null) ? 0 :name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj ==null)return false;if (getClass() != obj.getClass())return false;Person other = (Person) obj;if (age != other.age)return false;if (name ==null) {if (other.name !=null)return false;} else if (!name.equals(other.name))return false;return true;}public String toString() {return"姓名:" +this.name +",年齡:" +this.age;}}public class RepeatDemo {public static void main(String[] args) {Set<Person> all = new HashSet<Person>();all.add(new Person("張三", 20));Person P1=new Person("李四", 20);Person P2=new Person("李四", 20);System.out.println(P1.equals(P2));System.out.println(P1.hashCode());System.out.println(P2.hashCode());all.add(P1);all.add(P2);all.add(new Person("王五", 19));System.out.println(all);}} /* true 843642 843642 [姓名:張三,年齡:20, 姓名:李四,年齡:20, 姓名:王五,年齡:19] 如果上面的代碼中注釋掉hashcode或者equals任何一個,則兩次new Person("李四", 20)都不會被判別為重復(fù)元素,都能添加進HashSet中去 */上面重寫了hashCode和equals方法,兩個李四年齡和姓名都相同,會被判別為重復(fù)元素,無法插入。如果上面的代碼中注釋掉hashcode或者equals任何一個,則兩次new Person("李四", 20)都不會被判別為重復(fù)元素,都能添加進HashSet中去。hashcode也就是“哈希碼”的作用就是為支持?jǐn)?shù)據(jù)結(jié)構(gòu)中的哈希表結(jié)構(gòu)而存在的,換句話說,也就是只有用到集合框架的 Hashtable、HashMap、HashSet的時候,才需要重載hashCode()方法。否則hashCode就是本地方法,和開發(fā)環(huán)境有關(guān)。?? public native int hashCode();
四、集合迭代輸出:
4.1、Iterator
只要是碰見集合的輸出問題,不要思考,直接使用Iterator輸出。
?Iterator本身是一個專門用于輸出的操作接口,其接口定義了三種方法:
| No. | 方法名稱 | 類型 | 描述 |
| 1 | public boolean hasNext() | 普通 | 判斷是否有下一個元素 |
| 2 | public E next() | 普通 | 取出當(dāng)前元素 |
| 3 | public void remove() | 普通 | 刪除當(dāng)前內(nèi)容 |
在Collection接口中已經(jīng)定義了iterator()方法,可以為Iterator接口進行實例化操作。
范例:集合輸出的標(biāo)準(zhǔn)操作
import java.util.ArrayList;import java.util.Iterator;import java.util.List;publicclass IteratorDemo {publicstaticvoid main(String[] args) {List<String> all = new ArrayList<String>();all.add("hello");all.add("world");Iterator<String> iter = all.iterator();while (iter.hasNext()) {// 指針向下移動,判斷是否有內(nèi)容String str = iter.next();System.out.print(str +"、");}}}?4.2、雙向迭代輸出:ListIterator
Iterator接口的主要的功能只能完成從前向后的輸出,而如果現(xiàn)在要想完成雙向(由前向后、由后向前)則可以通過ListIterator接口完成功能,此接口定義如下:
| public interface ListIterator<E> extends Iterator<E> |
???????? ListIterator是Iterator的子接口,除了本身繼承的方法外,此接口又有如下兩個重要方法:
| No. | 方法名稱 | 類型 | 描述 |
| 1 | public boolean hasPrevious() | 普通 | 判斷是否有前一個元素 |
| 2 | public E previous() | 普通 | 取出當(dāng)前的元素 |
但是需要注意的是,如果要想進行由后向前的輸出,必須先由前向后。但是在Collection接口中并沒有為ListIterator接口實例化的操作,但是在List接口中存在此方法:public ListIterator<E> listIterator()
import java.util.ArrayList; import java.util.List; import java.util.ListIterator;public class ListIteratorDemo {public static void main(String[] args) {List<String> all = new ArrayList<String>();all.add("hello");all.add("world");ListIterator<String> iter = all.listIterator();//必須先由前向后輸出再由后向前輸出System.out.println("=========== 由前向后輸出 ============");while (iter.hasNext()) {System.out.print(iter.next() +"、");}System.out.println("\n=========== 由后向前輸出 ============");while (iter.hasPrevious()) {System.out.print(iter.previous() +"、");}}}五、Map接口
Collection接口操作的時候每次都會向集合中增加一個元素,但是如果現(xiàn)在增加的元素是一對的話,則就可以使用Map接口完成功能,Map接口的定義如下:
| public interface? Map<K,V> |
?在Map接口中有以下幾個常用方法:
| No. | 方法名稱 | 類型 | 描述 |
| 1 | public V put(K key,V value) | 普通 | 向集合中增加元素 |
| 2 | public V get(Object key) | 普通 | 根據(jù)key取得value |
| 3 | public Set<K> keySet() | 普通 | 取出所有的key |
| 4 | public Collection<V> values() | 普通 | 取出所有的value |
| 5 | public V remove(Object key) | 普通 | 刪除一個指定的key |
| 6 | public Set<Map.Entry<K,V>> entrySet() | 普通 | 將所有的集合變?yōu)?/span>Set集合 |
需要說明的是,在Map接口中還定義了一個內(nèi)部接口—— Map.Entry。
| public static? interface Map.Entry<K,V> |
Entry是在Map接口中使用的static定義的內(nèi)部接口,所以就是一個外部接口。
5.1、新的子類:HashMap
如果要使用Map接口的話,可以使用HashMap子類為接口進行實例化操作。
范例:驗證增加和查詢
import java.util.HashMap; import java.util.Map;public class HashMapDemo01 {public static void main(String[] args) {Map<String, String> all =new HashMap<String, String>();all.put("BJ","BeiJing");all.put("NJ","NanJing");String value = all.get("BJ");// 根據(jù)key查詢出valueSystem.out.println(value);System.out.println(all.get("TJ"));}}在Map的操作中,可以發(fā)現(xiàn),是根據(jù)key找到其對應(yīng)的value,如果找不到,則內(nèi)容為null。
而且現(xiàn)在由于使用的是HashMap子類,所以里面的key允許一個為null。? all.put(null,"NULL");
現(xiàn)在所有的內(nèi)容都有了,下面可以通過keySet()方法取出所有的key集合。Set<String> set = all.keySet();
5.2、Map集合的輸出
按照最正統(tǒng)的做法,所有的Map集合的內(nèi)容都要依靠Iterator輸出,以上雖然是完成了輸出,但是完成的不標(biāo)準(zhǔn),Map集合本身并不能直接為Iterator實例化,如果此時非要使用Iterator輸出Map集合中內(nèi)容的話,則要采用如下的步驟
? 1、??將所有的Map集合通過entrySet()方法變成Set集合,里面的每一個元素都是Map.Entry的實例;
? 2、??利用Set接口中提供的iterator()方法為Iterator接口實例化;
? 3、??通過迭代,并且利用Map.Entry接口完成key與value的分離。
import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;public class MapPrint {public static void main(String[] args) {Map<String, String> all =new HashMap<String, String>();all.put("BJ","BeiJing");all.put("NJ","NanJing");all.put(null,"NULL");Set<Map.Entry<String, String>> set = all.entrySet();Iterator<Map.Entry<String, String>> iter = set.iterator();while (iter.hasNext()) {Map.Entry<String, String> me = iter.next();System.out.println(me.getKey() +" --> " + me.getValue());}}}5.3、有序的存放:TreeMap
HashMap子類中的key都屬于無序存放的,如果現(xiàn)在希望有序(按key排序)則可以使用TreeMap類完成,但是需要注意的是,由于此類需要按照key進行排序,而且key本身也是對象,那么對象所在的類就必須實現(xiàn)Comparable接口。
import java.util.Iterator;import java.util.Map;import java.util.Set;import java.util.TreeMap;public class TreeMapDemo {public static void main(String[] args) {Map<String, String> all = new TreeMap<String, String>();all.put("NJ", "NanJing");all.put("BJ", "BeiJing");Set<Map.Entry<String, String>> set = all.entrySet();Iterator<Map.Entry<String, String>> iter = set.iterator();while (iter.hasNext()) {Map.Entry<String, String> me = iter.next();System.out.println(me.getKey() + " --> " + me.getValue());}}} //BJ --> BeiJing NJ --> NanJing5.4、舊的子類:Hashtable
?Hashtable與Vector都是屬于JDK 1.0的時候推出的操作類,在JDK 1.2之后讓其實現(xiàn)了Map接口,那么不管使用何種子類,肯定最終還是依靠Map接口完成功能。
import java.util.Hashtable;import java.util.Iterator;import java.util.Map;import java.util.Set;public class HashtableDemo {public static void main(String[] args) {Map<String, String> all =new Hashtable<String, String>();all.put("NJ","NanJing");all.put("BJ","BeiJing");Set<Map.Entry<String, String>> set = all.entrySet();Iterator<Map.Entry<String, String>> iter = set.iterator();while (iter.hasNext()) {Map.Entry<String, String> me = iter.next();System.out.println(me.getKey() +" --> " + me.getValue());}}} // BJ --> BeiJing // NJ --> NanJing5.5、HashMap與Hashtable的區(qū)別
HashMap和Hastable在使用上相似,那么兩者的區(qū)別如下:
| No. | 區(qū)別點 | HashMap | Hashtable |
| 1 | 推出時間 | JDK 1.2之后 | JDK 1.0的時候推出 |
| 2 | 線程處理 | 采用異步處理 | 采用同步處理 |
| 3 | 性能 | 速度較快 | 速度相對較慢 |
| 4 | 安全性 | 非線程安全性的操作 | 屬于線程安全的操作 |
| 5 | 保存null | 允許key設(shè)置成null | 不允許設(shè)置,否則出現(xiàn)NullPointerException |
5.6、關(guān)于key的說明
在HashMap中,中如果一個任意類的對象需要作為key保存的話,則對象所在的類必須實現(xiàn)Object類中的equals()和hashCode()兩個方法。
1. HashSet是通過HashMap實現(xiàn)的,TreeSet是通過TreeMap實現(xiàn)的,只不過Set用的只是Map的key
2. Map的key和Set都有一個共同的特性就是集合的唯一性.TreeMap更是多了一個排序的功能.
Hashtable待研究
import java.util.HashMap;import java.util.Map;class Person {private String name;private int age;public Person(String name,int age) {this.name = name;this.age = age;}public String toString() {return"姓名:" +this.name +",年齡:" +this.age;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result +age;result = prime * result + ((name ==null) ? 0 :name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj ==null)return false;if (getClass() != obj.getClass())return false;Person other = (Person) obj;if (age != other.age)return false;if (name ==null) {if (other.name !=null)return false;} else if (!name.equals(other.name))return false;return true;}}public class MapKeyDemo {public static void main(String[] args) {Map<Person, String> all =new HashMap<Person, String>();all.put(new Person("張三", 20), "ZS");System.out.println(all.get(new Person("張三", 20)));}}不過從一般的開發(fā)來看,使用String作為key的情況是最多的。
六、Stack類
?Stack表示的是棧的操作類,棧是一種典型的先進后出的程序,此類的定義如下:
| public class? Stack<E> extends Vector<E> |
?Stack是Vector類的子類,棧的主要操作方法:
????????? ·入棧:public E push(E item)
????????? ·出棧:public E pop()
范例:觀察入棧和出棧的操作
import java.util.Stack;public class StackDemo {public static void main(String[] args) {Stack<String> s = new Stack<String>();s.push("A");s.push("B");s.push("C");System.out.println(s.pop());System.out.println(s.pop());System.out.println(s.pop());System.out.println(s.pop());//EmptyStackException}}七、Properties類
?Properties類的主要功能是用于操作屬性,在各個語言(包括操作系統(tǒng))都會存在著許多的配置文件。所有的屬性文件中的屬性都是按照“key=value”的形式保存的,而且保存的內(nèi)容都是String(字符串),此類定義如下:
| public class? Properties extends Hashtable<Object,Object> |
此類是Hashtable的子類,而且已經(jīng)默認(rèn)指定好了泛型是Object,但是所有的屬性操作中的類型肯定都是字符串,那么操作的時候主要使用的是Properties類完成。
Properties類中定義的主要操作方法:
| No. | 方法名稱 | 類型 | 描述 |
| 1 | public Object setProperty(String key,String value) | 普通 | 設(shè)置屬性 |
| 2 | public String getProperty(String key) | 普通 | 根據(jù)屬性的名字取得屬性的內(nèi)容,如果沒有返回null結(jié)果 |
| 3 | public String getProperty(String key,String? defaultValue) | 普通 | 根據(jù)屬性的名字取得屬性內(nèi)容,如果沒有則返回默認(rèn)值(defaultValue) |
| 4 | public void list(PrintStream out) | 普通 | 從一個輸出流中顯示所有的屬性內(nèi)容 |
| 5 | public void store(OutputStream out,String comments)? throws IOException | 普通 | 向輸出流中輸出屬性 |
| 6 | public void load(InputStream inStream) throws? IOException | 普通 | 從輸入流中讀取屬性內(nèi)容 |
| 7 | public void storeToXML(OutputStream os,String? comment)? throws IOException | 普通 | 以XML文件格式輸出屬性內(nèi)容 |
| 8 | public void loadFromXML(InputStream in) throws? IOException,InvalidPropertiesFormatException | 普通 | 以XML文件格式輸入屬性內(nèi)容 |
7.1、設(shè)置、保存和讀取屬性
所有的屬性的內(nèi)容都是可以通過輸出和輸入流進行保存和讀取的,下面先通過代碼觀察如何保存在普通的文件之中。
此時通過一個普通的文件流將所有的屬性保存在了文件之中,而且一定要記住,所有的屬性文件一定要使用“*.properties”作為后綴。
import java.io.File;import java.io.FileOutputStream;import java.util.Properties;public class PropertiesDemo02 {public static void main(String[] args) throws Exception {Properties pro = new Properties();pro.setProperty("BJ", "BeiJing");pro.setProperty("NJ", "NanJing");pro.store(new FileOutputStream(new File("D:" + File.separator+ "area.properties")), "AREA INFO");}}以上是將屬性保存在了普通文件之中,也可以將其保存在XML文件之中,代碼如下:
import java.io.File;import java.io.FileOutputStream;import java.util.Properties;public class PropertiesDemo04 {public static void main(String[] args) throws Exception {Properties pro = new Properties();pro.setProperty("BJ", "BeiJing");pro.setProperty("NJ", "NanJing");pro.storeToXML(new FileOutputStream(new File("D:" + File.separator+ "area.xml")), "AREA INFO");}}結(jié)果為
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>AREA INFO</comment> <entry key="BJ">BeiJing</entry> <entry key="NJ">NanJing</entry> </properties>以后肯定也只能從XML文件格式中讀取屬性了。
import java.io.File;import java.io.FileInputStream;import java.util.Properties;public class PropertiesDemo05 {public static void main(String[] args) throws Exception {Properties pro = new Properties();pro.loadFromXML(new FileInputStream(new File("D:" + File.separator+ "area.xml")));System.out.println(pro.getProperty("BJ"));System.out.println(pro.getProperty("TJ"));System.out.println(pro.getProperty("TJ", "沒有此地區(qū)"));}}7.2、列出屬性
在實際的開發(fā)中,如果使用了IO流進行操作的話,有可能由于編碼的不同而造成亂碼的問題,因為程序的編碼和本地環(huán)境的編碼不統(tǒng)一,所以會造成亂碼的顯示,那么該如何查詢本地編碼呢,就需要通過Properties類的list()方法完成。
public class PropertiesDemo06 {public static void main(String[] args) throws Exception {System.getProperties().list(System.out);}}7.3、工廠設(shè)計終極版
???????? 工廠設(shè)計經(jīng)過發(fā)展已經(jīng)有兩種模型:
???????? 1、??簡單工廠,所有的工廠類隨著子類的增加而要修改
???????? 2、??反射工廠,只要傳遞進去完整的包.類,就可以完成實例化操作
import java.io.File;import java.io.FileInputStream;import java.util.Properties;interface Area {public void getInfo();}class BeiJing implements Area {public void getInfo() {System.out.println("你在北京,歡迎您!");}}class NanJing implements Area {public void getInfo() {System.out.println("你在南京,歡迎您!");}}class Factory {public static Area getInstance(String className) {Area a = null;try {a = (Area) Class.forName(className).newInstance();} catch (Exception e) {}return a;}}public class FactoryDemo {public static void main(String[] args) throws Exception {Properties pro = new Properties();pro.load(new FileInputStream(new File("D:" + File.separator+ "area.properties")));Area a = Factory.getInstance(pro.getProperty("NJ"));a.getInfo();}}配置文件:area.properties
#AREA INFO #Sun Nov 04 16:33:49 CST 2012 BJ=BeiJing NJ=NanJing現(xiàn)在的程序中可以發(fā)現(xiàn),都是通過配置文件控制的,而且只要配置文件改變了,程序可以立刻發(fā)生改變。達(dá)到了配置文件與程序相分離的目的。
總結(jié)
1、??類集就是動態(tài)對象數(shù)組
2、??類集中的主要接口:Collection、List、Set、Map、Iterator、ListIterator、Enumeration
List 內(nèi)容可以重復(fù)
?? ????ArrayList
?????? Vector
Set? 內(nèi)容不可以重復(fù)
???? 散列存放的子類:HashSet
???? 排序存放的子類:TreeSet
?
?
1. HashSet是通過HashMap實現(xiàn)的,TreeSet是通過TreeMap實現(xiàn)的,只不過Set用的只是Map的key
2. Map的key和Set都有一個共同的特性就是集合的唯一性.TreeMap更是多了一個排序的功能.
Map鍵值對 ?鍵不能相同,相同的put會被覆蓋,
HashMap?HashMap子類中的key都屬于無序存放的,子類key允許一個為null
TreeMap有序的存放,根據(jù)Comparable借口的compareTo方法的比較
Hashtable?key不允許為null,同步的。jdk1.0推出的。
3、??類集的主要目的就是為了保存數(shù)據(jù)和輸出數(shù)據(jù)
4、??所有的屬性都依靠Iterator完成
5、??就是各個子類的不同
6、? map的標(biāo)準(zhǔn)輸出
7、? Stack表示的是棧的操作類,棧是一種典型的先進后出的程
總結(jié)
以上是生活随笔為你收集整理的java基础----Java Collections Framework的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WinJS实用开发技巧(4):Appba
- 下一篇: StringFarmat控制字符串居中显