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

//声明:部分内容引自《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:
        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。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值