Chapter 11: Collections of Objects Rags")i turn public s :u: ola maIn (String[] args) I System println(fill(new Arraylist( )) System println(fill(new Hashset())) Syst println(fill(new HashMap( )))i monitor. expect(new String[] i [dog, dog, cat] [dog, cat] (dog=Spot, cat=Rags h 正如前面所讲的,Java的容器类分成两种基本类型。它们的区别就在, 每个位置能放多少对象。 Collection只允许每个位置上放一个对象(这 个名字有点误导,因为容器类库也常被统称为 collections)。它包括“以 定顺序持有一组对象”的List,以及“只能允许添加不重复的对象” 的set。 Array List是一种List,而 Hash set则是一种set。你可以 用ad()方法往 Collection里面加对象。 Map保存的是“键(key)—值”形式的pair,很像是一个微型数据库 上面这段程序用了一种叫 Hash Map的Map。如果你建了一个“州和首 府”的Map,然后想查一下Ohio的首府在哪里,你就可以用它来找 了。用法和用下标查数组是一样的。(Map又被称为关联性数组 associative array。)你可以用put()方法往Map里面加元素。它接 受键一值形式pair作参数。例程只演示了怎样把元素加进去,它没做査 询。这部分的内容我们以后再讲。 fi()方法还为 Collection和Map作了重载。如果你看过输出,就会 发现默认情况下(使用容器类的 tostring()方法)的打印效果已经很不错 了,所以我们就不再提供额外的打印支持了。打印出来的 Collection会 用方括号括起来,元素与元素之间用逗号分开。Map会用花括号括起 来,键和值之间用等号联起来(键在左边,值在右边)。 你能一眼就看出各种容器的基本行为。List会老老实实地持有你所输入 的所有对象,既不做排序也不做编辑。Set则每个对象只接受一次,而且 还要用它自己的规则对元素进行重新排序(一般情况下,你关心的只是 set包没包括某个对象,而不是它到底排在哪里——如果是那样,你最好 还是用List)。而Map也不接收重复的pair,至于是不是重复,要由 key来决定。此外,它也有它自己的内部排序规则,不会受输入顺序影 响。如果插入顺序是很重要的,那你就只能使用 LinkedHash set或 LinkedHashMap了。 填充容器 第26页共106页 www.wgqqh.com/shhgs/tij.html emailshhgsasohu.com
Chapter 11: Collections of Objects 第 26 页 共 106 页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com m.put("cat", "Rags"); return m; } public static void main(String[] args) { System.out.println(fill(new ArrayList( ))); System.out.println(fill(new HashSet( ))); System.out.println(fill(new HashMap( ))); monitor.expect(new String[] { "[dog, dog, cat]", "[dog, cat]", "{dog=Spot, cat=Rags}" }); } } ///:~ 正如前面所讲的,Java 的容器类分成两种基本类型。它们的区别就在, 每个位置能放多少对象。Collection 只允许每个位置上放一个对象(这 个名字有点误导,因为容器类库也常被统称为 collections)。它包括“以 一定顺序持有一组对象”的 List,以及“只能允许添加不重复的对象” 的 Set。ArrayList 是一种 List,而 HashSet 则是一种 Set。你可以 用 add( )方法往 Collection 里面加对象。 Map 保存的是“键(key)—值”形式的 pair,很像是一个微型数据库。 上面这段程序用了一种叫 HashMap 的 Map。如果你建了一个“州和首 府”的 Map,然后想查一下 Ohio 的首府在哪里,你就可以用它来找 了。用法和用下标查数组是一样的。(Map 又被称为关联性数组 associative array。)你可以用 put( )方法往 Map 里面加元素。它接 受键—值形式 pair 作参数。例程只演示了怎样把元素加进去,它没做查 询。这部分的内容我们以后再讲。 fill( )方法还为 Collection 和 Map 作了重载。如果你看过输出,就会 发现默认情况下(使用容器类的 toString( )方法)的打印效果已经很不错 了,所以我们就不再提供额外的打印支持了。打印出来的 Collection 会 用方括号括起来,元素与元素之间用逗号分开。Map 会用花括号括起 来,键和值之间用等号联起来(键在左边,值在右边)。 你能一眼就看出各种容器的基本行为。List 会老老实实地持有你所输入 的所有对象,既不做排序也不做编辑。Set 则每个对象只接受一次,而且 还要用它自己的规则对元素进行重新排序(一般情况下,你关心的只是 Set 包没包括某个对象,而不是它到底排在哪里——如果是那样,你最好 还是用 List)。而 Map 也不接收重复的 pair,至于是不是重复,要由 key 来决定。此外,它也有它自己的内部排序规则,不会受输入顺序影 响。如果插入顺序是很重要的,那你就只能使用 LinkedHashSet 或 LinkedHashMap 了。 填充容器
虽然容器的打印问题是解决了,但它的填充却还跟 java util. Arrays 样,有着相同的不足。和 Arrays一样, Collection也有一个叫 Collections的辅助类,它包含了一些静态的实用工具方法,其中就有 个f()。这个f()也只是把同一个对象的 reference复制到整个 容器,而且它还只能为List,不能为set和Map工作。 //: c1l: FillingLists java // The Collections. fill() method kel. simpletes ublic cl 11 private static Test monitor new Test( )i public static void main(String[] args) i Listlist nti=0;i<10;i++) Collections. fill(list, Hello")i System. out tln(list) monitor. expect(new String[] t [Hello, Hello, Hello, Hello, Hello }) 实际上这个方法还不如 Arrays,因为它只能在替换,而不是在往List 里面加新的元素。 为了能创建一些有实际意义的例子,我补充了一个带fl()方法的 Collections2类库(为方便起见,我把它放进了 com. bruceeckel, util)。它能用 generator加元素,而且还能让你指 定要ad()多少元素。前面定义的 Generator能同 Collections 同工作,但是Map需要一个它自己的 generator interface,因为每 次调用它的next()的时候要生成两个对象。下面就是这个Pair类: //: com: bruceeckel: util: Pair. java package com. bruceeckel.util; public class pair t public Object key, value; public Pair (object k, Object v) key = k value=y }///:~ 接下来是生成这个Pair的 generator的 interface 第27页共106页 www.wgqqh.com/shhgs/tij.html emailshhgsasohu.com
Thinking in Java 3rd Edition 第 27 页 共 106 页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com 虽然容器的打印问题是解决了,但它的填充却还跟 java.util.Arrays 一 样,有着相同的不足。和 Arrays 一样,Collection 也有一个叫 Collections 的辅助类,它包含了一些静态的实用工具方法,其中就有 一个 fill( )。这个 fill( )也只是把同一个对象的 reference 复制到整个 容器,而且它还只能为 List,不能为 Set 和 Map 工作。 //: c11:FillingLists.java // The Collections.fill( ) method. import com.bruceeckel.simpletest.*; import java.util.*; public class FillingLists { private static Test monitor = new Test( ); public static void main(String[] args) { List list = new ArrayList( ); for(int i = 0; i < 10; i++) list.add(""); Collections.fill(list, "Hello"); System.out.println(list); monitor.expect(new String[] { "[Hello, Hello, Hello, Hello, Hello, " + "Hello, Hello, Hello, Hello, Hello]" }); } } ///:~ 实际上这个方法还不如 Arrays,因为它只能在替换,而不是在往 List 里面加新的元素。 为了能创建一些有实际意义的例子,我补充了一个带 fill( )方法的 Collections2 类库(为方便起见,我把它放进了 com.bruceeckel.util)。它能用 generator 加元素,而且还能让你指 定要 add( )多少元素。前面定义的 Generator 能同 Collections 一 同工作,但是 Map 需要一个它自己的 generator interface,因为每 次调用它的 next( )的时候要生成两个对象。下面就是这个 Pair 类: //: com:bruceeckel:util:Pair.java package com.bruceeckel.util; public class Pair { public Object key, value; public Pair(Object k, Object v) { key = k; value = v; } } ///:~ 接下来是生成这个 Pair 的 generator 的 interface:
Chapter 11: Collections of Objects //: com: bruceeckel: util: MapGenerator java package com. bruceeckel util; public interface MapGenerator i Pair next()i J 做完准备之后,我们就能开始编写容器类的实用工具了: // com: bruceed 1: Collections.3 // To fill any type of container using a generator package com. bruceeckel util public class collections 2 // Fill an array using a generator: public static void fill(Collection c, Generator gen, int count) i for (int 0; 1< count; i++) public static void fill(Map m, MapGenerator gen, int count Pair p m put(p. key, p. value)i public static class RandStringPairGenerator implements MapGenerator t private Arrays2. RandstringGenerator gen public RandstringPairGenerator (int len) t gen new Arrays2. RandstringGenerator (len) ublic pair next return new Pair(gen next(), gen next( ) // Default object so you don't have to create yo Own public static RandStringPairGenerator rsp new Randstring PairGenerator (10)i public static class StringPairGenerator implements MapGenerator t private int index =-1 private string[][] d public StringPairGenerator (String[][] data)i d datai public Pair next() // Force the index to wrap index =(index 1)&d length return new Pair(d[index][o], dlindex][1])i public StringPairGenerator reset() 第28页共106页 www.wgqqh.com/shhgs/tij.html
Chapter 11: Collections of Objects 第 28 页 共 106 页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com //: com:bruceeckel:util:MapGenerator.java package com.bruceeckel.util; public interface MapGenerator { Pair next( ); } ///:~ 做完准备之后,我们就能开始编写容器类的实用工具了: //: com:bruceeckel:util:Collections2.java // To fill any type of container using a generator object. package com.bruceeckel.util; import java.util.*; public class Collections2 { // Fill an array using a generator: public static void fill(Collection c, Generator gen, int count) { for(int i = 0; i < count; i++) c.add(gen.next( )); } public static void fill(Map m, MapGenerator gen, int count) { for(int i = 0; i < count; i++) { Pair p = gen.next( ); m.put(p.key, p.value); } } public static class RandStringPairGenerator implements MapGenerator { private Arrays2.RandStringGenerator gen; public RandStringPairGenerator(int len) { gen = new Arrays2.RandStringGenerator(len); } public Pair next( ) { return new Pair(gen.next( ), gen.next( )); } } // Default object so you don't have to create your own: public static RandStringPairGenerator rsp = new RandStringPairGenerator(10); public static class StringPairGenerator implements MapGenerator { private int index = -1; private String[][] d; public StringPairGenerator(String[][] data) { d = data; } public Pair next( ) { // Force the index to wrap: index = (index + 1) % d.length; return new Pair(d[index][0], d[index][1]); } public StringPairGenerator reset( ) { index = -1; return this; }
Thinking in Java 3Edition // Use a predefined dataset public static StringPairGenerator geography new StringPairGenerator(CountryCapitals pairs) Produce a sequence 2D array public static class stringGenerator implement Generator private string[][] private int posit te int index public StringGenerator(string[][ data, int pos d public Object next( he index to wrap: return d[index] [position ,9th index =(index +1)dler public StringGenerator reset()i index // Use a predefined dataset public static StringGenerator countries ew StringGenerator (Countrycapitals. pairs, 0) public static StringGenerator capitals new String Generator (Countrycapitals. pairs, 1) 这两个f川()都要根据参数来决定要往容器里面加多少元素。此外, Map有两个 generator: RandstringPairGenerator和 String PairGenerator。前者会生成随机的字符串pair,其长度要由 构造函数的参数决定;而后者会根据一个两维的字符串数组,生成字符串 pair. String Generator也接受一个两维的字符串数组,但是它生成 的是单个的,而不是成对的元素。 static的rsp, geography, countries以及 capitals对象提供了预设的 generator,其中后面三 个会用到国家及其首都。注意,如果你要创建更多的对象pair, generator就会循环到数组的开头,但是如果你把这些对象par放进 Map,那么这些重复的东西就会被忽略掉 下面就是预定义的数据集。它包括了国家的名字及其首都 //: com: bruceeckel:util: Countrycapitals java package com. bruceeckel util public class CountryCapitals i public static final String[][] pairs = i / Africa ALGERIA","Algiers"),I"ANGOLA","luanda"), [BENIN","Porto-Novo"),[ "BOTSWANA","Gaberone"), 第29页共106页 www.wgqqh.com/shhgs/tij.html emailshhgsasohu.com
Thinking in Java 3rd Edition 第 29 页 共 106 页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com } // Use a predefined dataset: public static StringPairGenerator geography = new StringPairGenerator(CountryCapitals.pairs); // Produce a sequence from a 2D array: public static class StringGenerator implements Generator{ private String[][] d; private int position; private int index = -1; public StringGenerator(String[][] data, int pos) { d = data; position = pos; } public Object next( ) { // Force the index to wrap: index = (index + 1) % d.length; return d[index][position]; } public StringGenerator reset( ) { index = -1; return this; } } // Use a predefined dataset: public static StringGenerator countries = new StringGenerator(CountryCapitals.pairs, 0); public static StringGenerator capitals = new StringGenerator(CountryCapitals.pairs, 1); } ///:~ 这两个 fill( )都要根据参数来决定要往容器里面加多少元素。此外, Map 有两个 generator:RandStringPairGenerator 和 StringPairGenerator。前者会生成随机的字符串 pair,其长度要由 构造函数的参数决定;而后者会根据一个两维的字符串数组,生成字符串 pair。StringGenerator 也接受一个两维的字符串数组,但是它生成 的是单个的,而不是成对的元素。static 的 rsp,geography, countries 以及 capitals 对象提供了预设的 generator,其中后面三 个会用到国家及其首都。注意,如果你要创建更多的对象 pair, generator 就会循环到数组的开头,但是如果你把这些对象 pair 放进 Map,那么这些重复的东西就会被忽略掉。 下面就是预定义的数据集。它包括了国家的名字及其首都: //: com:bruceeckel:util:CountryCapitals.java package com.bruceeckel.util; public class CountryCapitals { public static final String[][] pairs = { // Africa {"ALGERIA","Algiers"}, {"ANGOLA","Luanda"}, {"BENIN","Porto-Novo"}, {"BOTSWANA","Gaberone"}
Chapter 11: Collections of Objects ["BURKINA FASO","Ouagadougou"1, ["BURUNDI","Bujumbura") [CAMEROON","Yaounde"),["CAPE VERDE","Praia LIC ["CHAD","N'djamena"), I"COMOROS","Moroni"), ["CONGO","Brazzaville") ("DJIBOUTI","Dijibouti"] [EGYPT","Cairo"),["EQUATORIAL GUINEA","Malabo") [ERITREA","Asmara"h,["ETHIOPIA","Addis Ababa") I GABON","Libreville"),I"THE GAMBIA","Banjul), ["GHANA","Accra"),I"GUINEA","Conakry") ["GUINEA","-),(BISSAU","Bissau") I"COTE D'IVOIR (IVORY COAST),"Yar [KENYA","Nairobi),("lESOTHO","Maseru"), ["LIBERIA","Monrovia"), I"LIBYA","Tripoli"), [" MADAGASCAR","Antananarivo") ("MALAWI","Lilongwe")r [ MALI","Bamako"),[MAURITANIA","Nouakchott") ["MAURITIUS","Port louis",("MOROCCO","Rabat") ["MOZAMBIQUE","Maputo"),I"NAMIBIA","Windhoek"), ["NIGER","Niamey"),I"NIGERIA","Abuja"), [RWANDA","Kigali", ["SAO TOME E PRINCIPE","Sao Tome"), [SENEGAL","Dakar"),I"SEYCHELLES","Victoria"I ["SIERRA LEONE","Freetown") (" SOMALIA","Mogadishu")r ["SOUTH AFRICA","Pretoria/Cape Town"), [" SUDAN","Khartoum"I ["SWAZILAND","Mbabane"),I"TANZANIA","Dodoma") ["UGANDA","Kampala") [" DEMOCRATIC REPUBLIC OF THE CONGO (ZAIRE)", "Kinshasa"), ["ZAMBIA","Lusaka"),("ZIMBABWE","Harare") ["AFGHANISTAN","Kabul"),["BAHRAIN","Manama"] ["BANGLADESH"," Dhaka"),["BHUTAN","Thimphu"), ["BRUNEI","Bandar Seri Begawan"), I" CAMBODIA","Phnom Penh"] ["CHINA","Beijing"),("CYPRUS","Nicosia") [INDIA","New Delhi",("INDONESIA","Jakarta") ["IRAN","Tehran"),I"IRAQ",Baghdad") ["ISRAEL","Tel Aviv"),("JAPAN","Tokyo"] ["JORDAN","Amman"),("KUWAIT","Kuwait city"), [lAOS","Vientiane"),["lEBANON","Beirut" I"MALAYSIA",Kuala Lumpur),I"THE MALDIVES","Male"), [MONGOLIA","Ulan Bator" [" MYANMAR (BURMA) rAngoon [NEPAL","Katmandu"),I"NORTH KOREA","P yongyang"), [ OMAN","Muscat"),("PAKISTAN","Islamabad") [PHILIPPINES","Manila"),(QATAR","Doha"), ["SAUDI ARABIA","Riyadh"), ("SINGAPORE","Singapore"), [SOUTH KOREA","Seoul"," sRI LANKA","Colombo") ["SYRIA","Damascus"), I TAIWAN (REPUBLIC OF CHINA)","Taipei ) [" THAILAND","Bang kok"),I"TURKEY","Ankara"I 第30页共106页 www.wgqqh.com/shhgs/tij.html emailshhgsasohu.com
Chapter 11: Collections of Objects 第 30 页 共 106 页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com {"BURKINA FASO","Ouagadougou"}, {"BURUNDI","Bujumbura"}, {"CAMEROON","Yaounde"}, {"CAPE VERDE","Praia"}, {"CENTRAL AFRICAN REPUBLIC","Bangui"}, {"CHAD","N'djamena"}, {"COMOROS","Moroni"}, {"CONGO","Brazzaville"}, {"DJIBOUTI","Dijibouti"}, {"EGYPT","Cairo"}, {"EQUATORIAL GUINEA","Malabo"}, {"ERITREA","Asmara"}, {"ETHIOPIA","Addis Ababa"}, {"GABON","Libreville"}, {"THE GAMBIA","Banjul"}, {"GHANA","Accra"}, {"GUINEA","Conakry"}, {"GUINEA","-"}, {"BISSAU","Bissau"}, {"COTE D'IVOIR (IVORY COAST)","Yamoussoukro"}, {"KENYA","Nairobi"}, {"LESOTHO","Maseru"}, {"LIBERIA","Monrovia"}, {"LIBYA","Tripoli"}, {"MADAGASCAR","Antananarivo"}, {"MALAWI","Lilongwe"}, {"MALI","Bamako"}, {"MAURITANIA","Nouakchott"}, {"MAURITIUS","Port Louis"}, {"MOROCCO","Rabat"}, {"MOZAMBIQUE","Maputo"}, {"NAMIBIA","Windhoek"}, {"NIGER","Niamey"}, {"NIGERIA","Abuja"}, {"RWANDA","Kigali"}, {"SAO TOME E PRINCIPE","Sao Tome"}, {"SENEGAL","Dakar"}, {"SEYCHELLES","Victoria"}, {"SIERRA LEONE","Freetown"}, {"SOMALIA","Mogadishu"}, {"SOUTH AFRICA","Pretoria/Cape Town"}, {"SUDAN","Khartoum"}, {"SWAZILAND","Mbabane"}, {"TANZANIA","Dodoma"}, {"TOGO","Lome"}, {"TUNISIA","Tunis"}, {"UGANDA","Kampala"}, {"DEMOCRATIC REPUBLIC OF THE CONGO (ZAIRE)", "Kinshasa"}, {"ZAMBIA","Lusaka"}, {"ZIMBABWE","Harare"}, // Asia {"AFGHANISTAN","Kabul"}, {"BAHRAIN","Manama"}, {"BANGLADESH","Dhaka"}, {"BHUTAN","Thimphu"}, {"BRUNEI","Bandar Seri Begawan"}, {"CAMBODIA","Phnom Penh"}, {"CHINA","Beijing"}, {"CYPRUS","Nicosia"}, {"INDIA","New Delhi"}, {"INDONESIA","Jakarta"}, {"IRAN","Tehran"}, {"IRAQ","Baghdad"}, {"ISRAEL","Tel Aviv"}, {"JAPAN","Tokyo"}, {"JORDAN","Amman"}, {"KUWAIT","Kuwait City"}, {"LAOS","Vientiane"}, {"LEBANON","Beirut"}, {"MALAYSIA","Kuala Lumpur"}, {"THE MALDIVES","Male"}, {"MONGOLIA","Ulan Bator"}, {"MYANMAR (BURMA)","Rangoon"}, {"NEPAL","Katmandu"}, {"NORTH KOREA","P'yongyang"}, {"OMAN","Muscat"}, {"PAKISTAN","Islamabad"}, {"PHILIPPINES","Manila"}, {"QATAR","Doha"}, {"SAUDI ARABIA","Riyadh"}, {"SINGAPORE","Singapore"}, {"SOUTH KOREA","Seoul"}, {"SRI LANKA","Colombo"}, {"SYRIA","Damascus"}, {"TAIWAN (REPUBLIC OF CHINA)","Taipei"}, {"THAILAND","Bangkok"}, {"TURKEY","Ankara"}