JAVA基础_物件容器(Container)
转自:良葛格学习笔记(http://caterpillar.onlyfun.net/Gossip/)
物件容器(Container)
物件容器可以您持有象,在Java中分作大:Collection Map。前者可持有各自立的物件,後者持有成的key-value物件。
* Collection
Collection 包括了 List Set ,List 以放置物件至容器中的序排列物件,Set 不接受重覆的物件,有自己的一套排序。
o ArrayList
o LinkedList
o HashSet
o TreeSet
o EnumSet
* Map
在物件存入 Map,需要配合一把key,您要取回物件就是根把key,Map中的key是唯一的,Map有自己的排序制。
o HashMap
o TreeMap
o EnumMap
ArrayList
ArrayList作了List介面,List介面是Collection介面的子介面,主要增加了根索引取得物件的方法。
ArrayList使用列作List介面,所以於快速的取得物件,使用ArrayList可以得到好的效能,不在移除物件或插入物件,ArrayList就比慢(使用 LinkedList 在方面就好的多)。
看看一ArrayList的例:
* ArrayListDemo.java
package onlyfun.caterpillar;
import java.util.*;
public class ArrayListDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<String> list = new ArrayList<String>();
System.out.println("入名(quit束)");
while(true) {
System.out.print("# ");
String input = scanner.next();
if(input.equals("quit"))
break;
list.add(input);
}
System.out.print("示入: ");
for(int i = 0; i < list.size(); i++)
System.out.print(list.get(i) + " ");
System.out.println();
}
}
在 J2SE 5.0 之後新增了泛型(Generic)的功能,使用物件容器建容器中存的物件型,如此您的物件在存入容器被限定您所宣告的型,而取出,也不至於失去原的型,可以避免型的。
使用add()方法可以一物件加入ArrayList中,使用size()方法可以回目前的ArrayList的度,使用get()可以回指定索引的物件,使用toArray()可以ArrayList中的物件物件列。
以下是行果:
入名(quit束)
# Justin
# caterpillar
# momor
# quit
示入: Justin caterpillar momor
您可以使用get()方法指定索引值取出物件,然而如果您的目的是要循序取出容器中所有的物件,您可以使用Iterator,Iterator作 Iterator 模式,看例子:
* ArrayListDemo.java
package onlyfun.caterpillar;
import java.util.*;
public class ArrayListDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<String> list = new ArrayList<String>();
System.out.println("入名(quit束)");
while(true) {
System.out.print("# ");
String input = scanner.next();
if(input.equals("quit"))
break;
list.add(input);
}
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
}
}
iterator()方法回一Iterator物件,物件提供的遍的方法,hasNext()方法Iterator中是否有物件,如果有的,可以使用next()取出。
事上,在J2SE 5.0您也不必使用iterator()了,使用增的for圈可以直接遍List的所有元素,例如:
* ArrayListDemo.java
package onlyfun.caterpillar;
import java.util.*;
public class ArrayListDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<String> list = new ArrayList<String>();
System.out.println("入名(quit束)");
while(true) {
System.out.print("# ");
String input = scanner.next();
if(input.equals("quit"))
break;
list.add(input);
}
for(String s : list) {
System.out.print(s + " ");
}
System.out.println();
}
}
LinkedList
List是以物件加入(add)容器的序排列它,如果您的物件加入之後大都是了取出,而不常作移除或插入(Insert)的作,使用ArrayList,如果您常容器中作移除或插入物件的作,使用LinkedList得好的效能。
LinkedList作了List介面,增加了一些移除插入物件的特定方法,像是addFirst()、addLast()、 getFirst()、getLast()、removeFirst( )、removeLast()等等,由於在插入移除有好的效能,合拿作堆(Stack)列(Queue)。
以下作一的FILO(First-In, Last-Out)堆,可以存入字串:
* StringStack.java
package onlyfun.caterpillar;
import java.util.*;
public class StringStack {
private LinkedList<String> linkedList;
public StringStack() {
linkedList = new LinkedList<String>();
}
public void push(String name) {
linkedList.addFirst(name);
}
public String top() {
return linkedList.getFirst();
}
public String pop() {
return linkedList.removeFirst();
}
public boolean isEmpty() {
return linkedList.isEmpty();
}
}
而於FIFO(First-In, First-Out)的列,我也可以使用LinkedList作:
* StringQueue.java
package onlyfun.caterpillar;
import java.util.*;
public class StringQueue {
private LinkedList<String> linkedList;
public StringQueue() {
linkedList = new LinkedList<String>();
}
public void put(String name) {
linkedList.addFirst(name);
}
public String get() {
return linkedList.removeLast();
}
public boolean isEmpty() {
return linkedList.isEmpty();
}
}
事上,如果您要使用列的功能,您也不用自作,在J2SE 5.0中,LinkedList也作了新加入的java.util.Queue介面,介面有五必作的方法:
element() 取得但不移除列第一元件,列空出例外
offer() 加入一元素至列中
peek() 取得但不移除列第一元件
poll() 取得移去列第一元件,列空回null
remove() 取得移除列第一元件
要使用列的功能,您只要似的宣告:
Queue<String> queue = new LinkedList<String>();
HashSet
HashSet作Set介面,Set介面承Collection介面,Set容器中的物件都是唯一的,加入 Set容器中的物件都必重新定equals()方法,作唯一性的,Set容器有自己的一套排序。
HashSet的排序是利用Hash Table,所以加入HashSet容器的物件必重新定hashCode()方法,利用Hash的方式,可以您快速的找到容器中的物件,在比加入Set容器中的物件是否相同,先比hashCode()方法回的值是否相同,如果相同,再使用equals()方法比,如果者都相同,相同的物件。
事上,在撰新的,最好是重新定equals()hashCode()方法,以符合Java的,您可以考 Object 中的介解如何重新定equals()hashCode()。
看一例子:
* HashSetDemo.java
package onlyfun.caterpillar;
import java.util.*;
public class HashSetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("caterpillar");
set.add("justin");
set.add("momor");
set.add("justin");
Iterator iterator = set.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
}
}
行果:
momor justin caterpillar
如上所示的,即使重覆加入了"justin"字串,HashSet中仍只有一"justin"字串物件,另一要注意的是,选代所有的值,其序您加入的序是不一的,选代所有值的序是HashSet排序後的序。
LinkedHashSet是HashSet的子,它在部作使用Hash Code行排序,然而允您在列行像是LinkedList,的改上面的程式即可解:
* LinkedHashSetDemo.java
package onlyfun.caterpillar;
import java.util.*;
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<String>();
set.add("caterpillar");
set.add("justin");
set.add("momor");
set.add("justin");
Iterator iterator = set.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
}
}
行果:
caterpillar justin momor
可以在行果中看到的,选代的序正是您加入值的序。
TreeSet
TreeSet作Set介面SortedSet介面,提供相的方法您有序的取出位置的物件,像是 first()、last()等方法,TreeSet是J2SE中唯一作SortedSet介面的,它使用黑加入的物件行排序。
看的例子:
* TreeSetDemo.java
package onlyfun.caterpillar;
import java.util.*;
public class TreeSetDemo {
public static void main(String[] args) {
Set<String> set = new TreeSet<String>();
set.add("justin");
set.add("caterpillar");
set.add("momor");
set.add("justin");
Iterator iterator = set.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
}
}
由於加入的是String物件,行果自依字典序行排序的作:
caterpillar justin momor
依字典序排序String物件是TreeSet的,如果您物件有自己的一套排序序,您要作一 Comparator 物件,您要作compare()方法,它必回整值,如果物件序相同回0,回正整表示compare()方法的第一物件大於第二物件,反之回整。
的例子,假您想要改TreeSet依字典序排列加入的物件相反的序:
* CustomComparator.java
package onlyfun.caterpillar;
import java.util.Comparator;
public class CustomComparator<T> implements Comparator<T> {
public int compare(T o1, T o2) {
if (((T) o1).equals(o2))
return 0;
return ((Comparable<T>) o1).compareTo((T) o2) * -1;
}
}
在自的Comparator中,如果物件的序相同回0,在TreeSet中表示物件是同一物件,TreeSet要求入的物件必作java.lang.Comparable介面,例中只是的原compareTo()回的值乘以一,如此在TreeSet中就可以的排列序相反。
在建TreeSet例一指定自的Comparator,例如:
* TreeSetDemo2.java
package onlyfun.caterpillar;
import java.util.*;
public class TreeSetDemo2 {
public static void main(String[] args) {
// 自Comparator
Comparator<String> comparator =
new CustomComparator<String>();
Set<String> set =
new TreeSet<String>(comparator);
set.add("justin");
set.add("caterpillar");
set.add("momor");
// 使用 enhanced for loop 示物件
for(String name : set) {
System.out.print(name + " ");
}
System.out.println();
}
}
行的果是相反的:
momor justin caterpillar
EnumSet
EnumSet的名明了其作用,它是在J2SE 5.0後加入的新,可以助您建立列值的集合,它提供了一系列的方法,可以您指定不同的集合建立方式,例如:
* EnumSetDemo.java
package onlyfun.caterpillar;
import java.util.*;
enum FontConstant { Plain, Bold, Italic }
public class EnumSetDemo {
public static void main(String[] args) {
EnumSet<FontConstant> enumSet =
EnumSet.of(FontConstant.Plain, FontConstant.Bold);
showEnumSet(enumSet);
showEnumSet(EnumSet.complementOf(enumSet));
}
public static void showEnumSet(
EnumSet<FontConstant> enumSet) {
Iterator iterator = enumSet.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
}
}
您可以指定列值加入EnumSet中,of()方法返回一EnumSet的例,中包括您所指定的列值,您也可以使complementOf()指定一EnumSet的互集,以下是行的果:
Plain Bold
Italic
EnumSet作了Set介面,所以您可以使用Set介面的所有方法它所包括的列值,例如一集合中是否包括 FontConstant.Bold:
if(enumSet.contains(FontConstant.Bold)) {
....
}
您也可以建立一空的EnumSet,然後自己逐加入列值,例如:
* EnumSetDemo.java
package onlyfun.caterpillar;
import java.util.*;
enum FontConstant { Plain, Bold, Italic }
public class EnumSetDemo {
public static void main(String[] args) {
EnumSet<FontConstant> enumSet =
EnumSet.noneOf(FontConstant.class);
enumSet.add(FontConstant.Bold);
enumSet.add(FontConstant.Italic);
showEnumSet(enumSet);
}
public static void showEnumSet(
EnumSet<FontConstant> enumSet) {
Iterator iterator = enumSet.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
}
}
行果:
Bold Italic
您也可以由一容器物件中建立EnumSet:
List<FontConstant> list = new ArrayList<FontConstant>();
list.add(FontConstant.Bold);
list.add(FontConstant.Italic);
showEnumSet(EnumSet.copyOf(list));
HashMap
HashMap作Map介面,部作使用Hash Table,您在常可以得key/value。
所的key/value,的,您Map容器物件作一有很多房的房子,每房的有一把匙,您物件存至房中,要便有一把匙,下次要取回物件,就是根把匙取得。
以一的例子作明:
* HashMapDemo.java
package onlyfun.caterpillar;
import java.util.*;
public class HashMapDemo {
public static void main(String[] args) {
Map<String, String> map =
new HashMap<String, String>();
map.put("caterpillar", "caterpillar's message!!");
map.put("justin", "justin's message!!");
System.out.println(map.get("justin"));
System.out.println(map.get("caterpillar"));
}
}
在宣告Map型,您指定了key/value各自的型,都是宣告String,也就是以String物件作key物件的型,而 value也是以String物件作其型。
使用Map的put()方法物件存入,必同指定key/value,而要取回物件,指定key,程式的行果如下:
justin's message!!
caterpillar's message!!
HashMap是被常使用的物件,您可以考下面例子中HashMap的用:
* Command 模式
* Thread-Specific Storage 模式
* 控制器(Servlet)
可以使用values()方法返回一Collection物件,如果您需要一次选代Map中所有的物件,很有用,例如:
* HashMapDemo.java
package onlyfun.caterpillar;
import java.util.*;
public class HashMapDemo {
public static void main(String[] args) {
Map<String, String> map =
new HashMap<String, String>();
map.put("justin", "justin's message!!");
map.put("momor", "momor's message!!");
map.put("caterpillar", "caterpillar's message!!");
Collection collection = map.values();
Iterator iterator = collection.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
行果:
momor's message!!
justin's message!!
caterpillar's message!!
HashMap使用Hash Table,因而它有自己的排序方式,如果您想要在选代所有的物件,依照插入的序排序,可以使用LinkedHashMap,它是HashMap 的子,使用values()所返回的Collection物件,其含物件之序即初您加入物件之序,例如:
* LinkedHashMapDemo.java
package onlyfun.caterpillar;
import java.util.*;
public class LinkedHashMapDemo {
public static void main(String[] args) {
Map<String, String> map =
new LinkedHashMap<String, String>();
map.put("justin", "justin's message!!");
map.put("momor", "momor's message!!");
map.put("caterpillar", "caterpillar's message!!");
Collection collection = map.values();
Iterator iterator = collection.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
行果:
justin's message!!
momor's message!!
caterpillar's message!!
TreeMap
TreeMap作Map介面SortedMap介面,提供相的方法您有序的取出位置的物件,像是 firstKey()、lastKey()等方法,TreeMap是J2SE中唯一作SortedMap介面的,它使用黑加入的物件行排序。
看的例子:
* TreeMapDemo.java
package onlyfun.caterpillar;
import java.util.*;
public class TreeMapDemo {
public static void main(String[] args) {
Map<String, String> map =
new TreeMap<String, String>();
map.put("justin", "justin's message!!");
map.put("momor", "momor's message!!");
map.put("caterpillar", "caterpillar's message!!");
Collection collection = map.values();
Iterator iterator = collection.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
由於您加入的是String物件,行果自依key的字典序行排序的作:
caterpillar's message!!
justin's message!!
momor's message!!
依字典序排序String物件是TreeMap的,如果您物件有自己的一套排序序,您要作一 Comparator 物件,它有必作的方法,compare()equals(),前者必回整值,如果物件序相同回0,回正整表示compare ()方法的第一物件大於第二物件,反之回整,後者是定物件是否相等。
EnumMap
EnumMap是列型的,方便您使用列型及Map物件,直接例:
* EnumMapDemo.java
package onlyfun.caterpillar;
import java.util.*;
enum Action {TURN_LEFT, TURN_RIGHT, SHOOT}
public class EnumMapDemo {
public static void main(String[] args) {
Map<Action, String> map =
new EnumMap<Action, String>(Action.class);
map.put(Action.TURN_LEFT, "向左");
map.put(Action.TURN_RIGHT, "向右");
map.put(Action.SHOOT, "射");
for(Action action : Action.values( ) ) {
System.out.println(map.get(action));
}
}
}
行果:
向左
向右
射
的使用HashMap比起的差是,在上面的程式中,EnumMap根列的序物件的排列序,下面程式可以看大概:
* EnumMapDemo2.java
package onlyfun.caterpillar;
import java.util.*;
enum Action {TURN_LEFT, TURN_RIGHT, SHOOT}
public class EnumMapDemo2 {
public static void main(String[] args) {
Map<Action, String> map =
new EnumMap<Action, String>(Action.class);
map.put(Action.SHOOT, "射");
map.put(Action.TURN_RIGHT, "向右");
map.put(Action.TURN_LEFT, "向左");
for(String value : map.values( )) {
System.out.println(value);
}
}
}
行果:
向左
向右
射
遍的果可以看出,物件的序是根列序排列的。