您的位置:首页 > 编程语言 > Java开发

Thinking in Java 第17章 容器深入研究(17.1-17.7)

2016-07-20 10:00 696 查看
//声明:部分内容引自《Java编程思想(第四版)》机械工业出版社

【完整的容器分类法】



【填充容器】

– fill()。

– Generator。

– Map 生成器。

– Abstract 类。享元模式:它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。例:

//: net/mindview/util/Countries.java
// "Flyweight" Maps and Lists of sample data.
package net.mindview.util;
import java.util.*;
import static net.mindview.util.Print.*;

public class Countries {
public static final String[][] DATA = {
// Africa
{"ALGERIA", "Algiers"}, {"ANGOLA", "Luanda"},
{"BENIN", "Porto-Novo"}, {"BOTSWANA", "Gaberone"},
{"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"},
{"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", "Jerusalem"}, {"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"},
{"UNITED ARAB EMIRATES", "Abu Dhabi"},
{"VIETNAM", "Hanoi"}, {"YEMEN", "Sana'a"},
// Australia and Oceania
{"AUSTRALIA", "Canberra"}, {"FIJI", "Suva"},
{"KIRIBATI", "Bairiki"},
{"MARSHALL ISLANDS", "Dalap-Uliga-Darrit"},
{"MICRONESIA", "Palikir"}, {"NAURU", "Yaren"},
{"NEW ZEALAND", "Wellington"}, {"PALAU", "Koror"},
{"PAPUA NEW GUINEA", "Port Moresby"},
{"SOLOMON ISLANDS", "Honaira"}, {"TONGA", "Nuku'alofa"},
{"TUVALU", "Fongafale"}, {"VANUATU", "< Port-Vila"},
{"WESTERN SAMOA", "Apia"},
// Eastern Europe and former USSR
{"ARMENIA", "Yerevan"}, {"AZERBAIJAN", "Baku"},
{"BELARUS (BYELORUSSIA)", "Minsk"},
{"BULGARIA", "Sofia"}, {"GEORGIA", "Tbilisi"},
{"KAZAKSTAN", "Almaty"}, {"KYRGYZSTAN", "Alma-Ata"},
{"MOLDOVA", "Chisinau"}, {"RUSSIA", "Moscow"},
{"TAJIKISTAN", "Dushanbe"}, {"TURKMENISTAN", "Ashkabad"},
{"UKRAINE", "Kyiv"}, {"UZBEKISTAN", "Tashkent"},
// Europe
{"ALBANIA", "Tirana"}, {"ANDORRA", "Andorra la Vella"},
{"AUSTRIA", "Vienna"}, {"BELGIUM", "Brussels"},
{"BOSNIA", "-"}, {"HERZEGOVINA", "Sarajevo"},
{"CROATIA", "Zagreb"}, {"CZECH REPUBLIC", "Prague"},
{"DENMARK", "Copenhagen"}, {"ESTONIA", "Tallinn"},
{"FINLAND", "Helsinki"}, {"FRANCE", "Paris"},
{"GERMANY", "Berlin"}, {"GREECE", "Athens"},
{"HUNGARY", "Budapest"}, {"ICELAND", "Reykjavik"},
{"IRELAND", "Dublin"}, {"ITALY", "Rome"},
{"LATVIA", "Riga"}, {"LIECHTENSTEIN", "Vaduz"},
{"LITHUANIA", "Vilnius"}, {"LUXEMBOURG", "Luxembourg"},
{"MACEDONIA", "Skopje"}, {"MALTA", "Valletta"},
{"MONACO", "Monaco"}, {"MONTENEGRO", "Podgorica"},
{"THE NETHERLANDS", "Amsterdam"}, {"NORWAY", "Oslo"},
{"POLAND", "Warsaw"}, {"PORTUGAL", "Lisbon"},
{"ROMANIA", "Bucharest"}, {"SAN MARINO", "San Marino"},
{"SERBIA", "Belgrade"}, {"SLOVAKIA", "Bratislava"},
{"SLOVENIA", "Ljuijana"}, {"SPAIN", "Madrid"},
{"SWEDEN", "Stockholm"}, {"SWITZERLAND", "Berne"},
{"UNITED KINGDOM", "London"}, {"VATICAN CITY", "---"},
// North and Central America
{"ANTIGUA AND BARBUDA", "Saint John's"},
{"BAHAMAS", "Nassau"},
{"BARBADOS", "Bridgetown"}, {"BELIZE", "Belmopan"},
{"CANADA", "Ottawa"}, {"COSTA RICA", "San Jose"},
{"CUBA", "Havana"}, {"DOMINICA", "Roseau"},
{"DOMINICAN REPUBLIC", "Santo Domingo"},
{"EL SALVADOR", "San Salvador"},
{"GRENADA", "Saint George's"},
{"GUATEMALA", "Guatemala City"},
{"HAITI", "Port-au-Prince"},
{"HONDURAS", "Tegucigalpa"}, {"JAMAICA", "Kingston"},
{"MEXICO", "Mexico City"}, {"NICARAGUA", "Managua"},
{"PANAMA", "Panama City"}, {"ST. KITTS", "-"},
{"NEVIS", "Basseterre"}, {"ST. LUCIA", "Castries"},
{"ST. VINCENT AND THE GRENADINES", "Kingstown"},
{"UNITED STATES OF AMERICA", "Washington, D.C."},
// South America
{"ARGENTINA", "Buenos Aires"},
{"BOLIVIA", "Sucre (legal)/La Paz(administrative)"},
{"BRAZIL", "Brasilia"}, {"CHILE", "Santiago"},
{"COLOMBIA", "Bogota"}, {"ECUADOR", "Quito"},
{"GUYANA", "Georgetown"}, {"PARAGUAY", "Asuncion"},
{"PERU", "Lima"}, {"SURINAME", "Paramaribo"},
{"TRINIDAD AND TOBAGO", "Port of Spain"},
{"URUGUAY", "Montevideo"}, {"VENEZUELA", "Caracas"},
};

// Use AbstractMap by implementing entrySet()
private static class FlyweightMap
extends AbstractMap<String, String> {
private static class Entry
implements Map.Entry<String, String> {
int index;

Entry(int index) {
this.index = index;
}

public boolean equals(Object o) {
return DATA[index][0].equals(o);
}

public String getKey() {
return DATA[index][0];
}

public String getValue() {
return DATA[index][1];
}

public String setValue(String value) {
throw new UnsupportedOperationException();
}

public int hashCode() {
return DATA[index][0].hashCode();
}
}

// Use AbstractSet by implementing size() & iterator()
static class EntrySet
extends AbstractSet<Map.Entry<String, String>> {
private int size;

EntrySet(int size) {
if (size < 0)
this.size = 0;
// Can't be any bigger than the array:

c897
else if (size > DATA.length)
this.size = DATA.length;
else
this.size = size;
}

public int size() {
return size;
}

private class Iter
implements Iterator<Map.Entry<String, String>> {
// Only one Entry object per Iterator:
private Entry entry = new Entry(-1);

public boolean hasNext() {
return entry.index < size - 1;
}

public Map.Entry<String, String> next() {
entry.index++;
return entry;
}

public void remove() {
throw new UnsupportedOperationException();
}
}

public Iterator<Map.Entry<String, String>> iterator() {
return new Iter();
}
}

private static Set<Map.Entry<String, String>> entries =
new EntrySet(DATA.length);

public Set<Map.Entry<String, String>> entrySet() {
return entries;
}
}

// Create a partial map of 'size' countries:
static Map<String, String> select(final int size) {
return new FlyweightMap() {
public Set<Map.Entry<String, String>> entrySet() {
return new EntrySet(size);
}
};
}

static Map<String, String> map = new FlyweightMap();

public static Map<String, String> capitals() {
return map; // The entire map
}

public static Map<String, String> capitals(int size) {
return select(size); // A partial map
}

static List<String> names =
new ArrayList<String>(map.keySet());

// All the names:
public static List<String> names() {
return names;
}

// A partial list:
public static List<String> names(int size) {
return new ArrayList<String>(select(size).keySet());
}

public static void main(String[] args) {
print(capitals(10));
print(names(10));
print(new HashMap<String, String>(capitals(3)));
print(new LinkedHashMap<String, String>(capitals(3)));
print(new TreeMap<String, String>(capitals(3)));
print(new Hashtable<String, String>(capitals(3)));
print(new HashSet<String>(names(6)));
print(new LinkedHashSet<String>(names(6)));
print(new TreeSet<String>(names(6)));
print(new ArrayList<String>(names(6)));
print(new LinkedList<String>(names(6)));
print(capitals().get("BRAZIL"));
}
} /* Output:
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo, BOTSWANA=Gaberone, BULGARIA=Sofia, BURKINA FASO=Ouagadougou, BURUNDI=Bujumbura, CAMEROON=Yaounde, CAPE VERDE=Praia, CENTRAL AFRICAN REPUBLIC=Bangui}
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BULGARIA, BURKINA FASO, BURUNDI, CAMEROON, CAPE VERDE, CENTRAL AFRICAN REPUBLIC]
{BENIN=Porto-Novo, ANGOLA=Luanda, ALGERIA=Algiers}
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo}
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo}
{ALGERIA=Algiers, ANGOLA=Luanda, BENIN=Porto-Novo}
[BULGARIA, BURKINA FASO, BOTSWANA, BENIN, ANGOLA, ALGERIA]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BULGARIA, BURKINA FASO]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BULGARIA, BURKINA FASO]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BULGARIA, BURKINA FASO]
[ALGERIA, ANGOLA, BENIN, BOTSWANA, BULGARIA, BURKINA FASO]
Brasilia
*///:~


FlyweightMap 必须实现 entrySet() 方法,它需要定制的 Set 实现和定制的 Map.Entry 类。这里正是享元部分:每个 Map.Entry 对象都只存储了它的索引,而不是实际的键和值。当你调用 getKey() 和 getValue() 时,它们会使用该索引来返回恰当的 DATA 元素。EntrySet 可以确保它的 size 不会大于 DATA。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 编程