Summary of Map System of java_ Collection System (2)

3.3、 LinkedHashMap

3.31 LinkedHashMap features:

Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。此链接列表定义了迭代顺序(即存储的顺序与输出的顺序相同),该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。此实现不是同步的

Note :

①When the key is String or a basic data type wrapper class, the same key automatically replaces the old value with the new value (because they have rewritten the hashCode and equals methods)
②When the key is a custom object, it needs to override the hashCode and equals methods To ensure the uniqueness of the key

3.32 LinkedHashMap usage example

public class LinkedHashMapReview {
    public static void main(String[] args) {
        test1();
        test2();
        test3();
    }

    /**
     * 自定义对象为key
     * 需让其重写hashCode与equals方法才能保证key的唯一性
     */
    private static void test3() {
        LinkedHashMap<Info, Integer> map=new LinkedHashMap<Info, Integer>();
        map.put(new Info(0, "vvv"), 000);
        map.put(new Info(0, "vvv"), 333);
        map.put(new Info(1, "ccc"), 111);
        System.out.println(map);
        // output :  当Info没有重写hashCode与equals方法,
//      {Info [id=0, adress=vvv]=0, Info [id=0, adress=vvv]=333, Info [id=1, adress=ccc]=111}

        // output :  当Info重写hashCode与equals方法
//      {Info [id=0, adress=vvv]=333, Info [id=1, adress=ccc]=111}

    }

    /**
     * 基本数据类型包装类重写了hashCode与equals方法,键相同自动替换旧值为新值
     */
    private static void test2() {
        LinkedHashMap<Integer, Integer> map=new LinkedHashMap<Integer, Integer>();
        map.put(1, 66);
        map.put(2, 67);
        map.put(3, 68);
        map.put(1, 69);  // 自动装箱 Integer.valueOf(69)
        System.out.println(map);
        // output
//      {1=69, 2=67, 3=68}
        // 输出顺序与存储相同,重复添加已有的键会替换掉旧值
    }

    /**
     * String做key
     * String类实现了hashCode与equals方法,键相同自动替换旧值为新值
     */
    private static void test1() {
        LinkedHashMap<String, String> map=new LinkedHashMap<String, String>();
        map.put("aa", "121");
        map.put("bb", "122");
        map.put("cc", "123");
        map.put("aa", "122");
        map.put("dd", "122");
        map.put("ee", "122");

        System.out.println(map);
        // output 
        // {aa=122, bb=122, cc=123, dd=122, ee=122}
        // 输出顺序与存储相同,重复添加已有的键会替换掉旧值
    }
}

3.4、 Hashtable

Hashtable是同步的,它不允许使用 null 值和 null 键。除此之外与HashMap大致相同,示例略 

3.41 Using Properties

The Properties class inherits from Hashtable and represents a persistent set of properties consisting of key-value pairs .

Unlike Hashtable , each key and its corresponding value in the Properties property list is a string , so it is not recommended to use Hashtable's put method to add properties to Properties.

Properties can be stored in the stream via the store method or loaded from the stream via the load method. The following three ways:

1. Input and output streams through bytes

 void load(InputStream inStream) 
                  从输入流中读取属性列表(键和元素对)。 
 void store(OutputStream out, String comments) 
                  以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。 

2. Input and output streams through characters

 void load(Reader reader) 
              按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 
void store(Writer writer, String comments) 
              以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。 

3. Via xml

void loadFromXML(InputStream in) 
              将指定输入流中由 XML 文档所表示的所有属性加载到此属性表中。   
void storeToXML(OutputStream os, String comment) 
              发出一个表示此表中包含的所有属性的 XML 文档。 
void storeToXML(OutputStream os, String comment, String encoding) 
              使用指定的编码发出一个表示此表中包含的所有属性的 XML 文档。  

Access key-values ​​through the following methods

 String getProperty(String key) 
              用指定的键在此属性列表中搜索属性。 
String getProperty(String key, String defaultValue) 
              用指定的键在属性列表中搜索属性。 
 Object setProperty(String key, String value) 
              调用 Hashtable 的方法 put。 

 void list(PrintStream out) 
              将属性列表输出到指定的输出流。 
 void list(PrintWriter out) 
              将属性列表输出到指定的输出流。 
 Set<String> stringPropertyNames() 
              返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。 

Below is an example using Properties
1. Create a properties file

/**
     * 创建一个属性文件
     * @throws IOException
     */
    private static void create() throws IOException {
        // 创建一个空的属性文件
        Properties prop = new Properties();
        // 创建一个文件输出流,用于写出属性文件到本地
        FileWriter writer = new FileWriter("config.properties");//亦可以使用FileOutputStream
        // 设置属性键与值
        prop.setProperty("name", "pecuyu");
        prop.setProperty("character", "kind");
        // 通过字符输出流将键值对写入属性文件
        prop.store(writer, "this is new");
        writer.close();
    }

2. Read the content of the properties file

    /**
     * 读取一个属性文件
     */
    private static void load() throws FileNotFoundException, IOException {
        // 创建属性文件
        Properties prop=new Properties();
        // 从流中读取属性列表到属性文件
        prop.load(new FileInputStream("config.properties"));// 亦可使用FileReader
        // 通过键取值
        String name = prop.getProperty("name");
        String character = prop.getProperty("character");
        //System.out.println("name="+name+" character="+character);

        prop.list(System.out); // 将属性键值对列出并打印到控制台

        Set<String> stringPropertyNames = prop.stringPropertyNames();// 键的set集合
        for (String key : stringPropertyNames) {
            String value = prop.getProperty(key);  // 通过键获取值
            System.out.println("key="+key+" value="+value);
        }

    }

3.5、 WeakHashMap

3.51 Features

以弱键 实现的基于哈希表的 Map。在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除,因此,该类的行为与其他的 Map 实现有所不同。 
null 值和 null 键都被支持

3.52 Implementation Considerations

WeakHashMap 中的值对象由普通的强引用保持。因此应该小心谨慎,确保值对象不会直接或间接地强引用其自身的键,因为这会阻止键的丢弃。注意,值对象可以通过 WeakHashMap 本身间接引用其对应的键;这就是说,某个值对象可能强引用某个其他的键对象,而与该键对象相关联的值对象转而强引用第一个值对象的键。处理此问题的一种方法是,在插入前将值自身包装在 WeakReferences 中,如:m.put(key, new WeakReference(value)),然后,分别用 get 进行解包。 

3.6、 TreeMap

3.61 TreeMap Features

- 基于红黑树(Red-Black tree)的 NavigableMap 实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
- 键值对是红黑树结构,可以保证键的排序和唯一性
- 此实现不是同步的

A sorting scheme must be provided for TreeMap

① Sort according to the natural order of its keys (custom objects must implement the Comparable interface and override the compare method)
② Sort according to the Comparator provided when the map was created, depending on the constructor used.

3.62 Analyze the source code of the put method of TreeMap

1. Determine whether the Entry has an element, if not, create a new one, and add a new element
2. Sort the TreeMap by natural sorting and comparator sorting, and use Comparator first to sort

通过Entry对象来来确保插入元素的唯一性,它建立在compare方法的基础上,此方法返回0时,表示插入的键存在,直接替换旧值并返回。因此在使用TreeMap时,自定义对象须实现Comparable接口并重写compare方法或在创建TreeMap时提供Comparator
    cmp = cpr.compare(key, t.key);
     if (cmp < 0)
          t = t.left;
      else if (cmp > 0)
          t = t.right;
      else
      return t.setValue(value);

3. Readjust the red-black tree (ie the Entry tree) after inserting elements

The source code is as follows

public V put(K key, V value) {
        Entry<K,V> t = root;
        // 判断Entry是否有元素,没有则new一个
        if (t == null) {
         compare(key, key); // type (and possibly null) check
            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null; 
        }
        int cmp;
        Entry<K,V> parent;
        // 通过自然排序与比较器排序
        // split comparator and comparable paths
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        else {
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                Comparable<? super K> k = (Comparable<? super K>) key;
            do {
                parent = t;
                cmp = k.compareTo(t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }

3.63 TreeMap usage example

public class TreeMapReview {
    public static void main(String[] args) {
        test1();
        test2();
    }

    /**
     * 自定义对象做key,需满足以下两个条件之一,否则抛出异常java.lang.ClassCastException:com.yu.bean.Info cannot be cast to java.lang.Comparable
     * ①实现Comparable接口并重写compare方法
     * ②构造TreeMap对象时,需传入Comparator
     * 当两者都有,以Comparator来排序
     */
    private static void test2() {
        TreeMap<Info, String> map=new TreeMap<Info, String>(new Comparator<Info>() {
            @Override
            public int compare(Info o1, Info o2) {
                int num = o2.getId() - o1.getId();
                num = num == 0 ? o2.getAdress().hashCode() - o1.getAdress().hashCode() : num;
                return num;
            }
        });
        map.put(new Info(000, "hhh"), "qqq");
        map.put(new Info(001, "hhh"), "aaa");
        map.put(new Info(002, "hhh"), "zzz");
        map.put(new Info(000, "hhh"), "qqq");

        System.out.println(map);
    }

    /**
     * String类型或基本类型包装类做key
     * String类实现了Comparable接口,可以进行自然排序
     */
    private static void test1() {
        TreeMap<String, String> map = new TreeMap<String, String>();
        map.put("a", "111");
        map.put("b", "123");
        map.put("c", "121");
        map.put("c", "121");

        Set<Entry<String, String>> entrySet = map.entrySet();
        for (Entry<String, String> entry : entrySet) {
            System.out.println("key=" + entry.getKey() + " value="
                    + entry.getValue());
        }
        // output:
//      key=a value=111
//      key=b value=123
//      key=c value=121
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326212532&siteId=291194637