Map集合的实现类

Map集合的实现类

HashMap和Hashtable(没写错哦~就是小写)实现类

HashMap是Map集合的典型实现类,它与Hashtable的关系,就像ArrayList与Vector的关系。

Hashtable是一个老实现类了(从JDK1.0),他有两个繁琐的方法:elements() 和 keys(),这俩相当于Map接口的 values()和 keySet() 方法,现在很少使用这两个方法。

除此之外,Hashtable和HashMap有两点典型区别:

  • Hashtable 是一个线程安全的Map实现,而HashMap是线程不安全的map实现,因此HashMap性能更高一些。

  • Hashtable 不允许使用null作为key和value,会引发NullPointException异常;但HashMap可以使用null作为key

    和value(由于key不允许重复,所以keySet中只能有一个null,value中就可以由无数个null)

虽然Hashtable线程安全,但还是不建议使用Hashtable类,如果需要创建线程安全的Map实现类,可以通过Collections工具类把HashMap变成线程安全的。

HashMap与Hashtable中key不允许重复的判断依据和HashSet一样。如果使用自定义类作为key,重写该类的equals()和hashCode()的判断标准应该保持一致————当两个key通过equals方法返回true时,它们的hashCode()也应该相同。

与Hashset相同,尽量不要使用可变对象作为HashMap、Hashtable的key,如果确实需要使用可变对象作为HashMap和Hashtable的key,则尽量不要在程序中修改作为key的可变对象,否则会给访问带来很大麻烦。

LinkedHashMap实现类

就像HashSet有一个LinkedHashSet子类,HashMap也有一个LinkedHashMap子类。

LinkedHashMap也使用双向链表来维护key-value对的次序(其实只考虑key的次序)。该链表负责维护Map的迭代顺序,迭代顺序key-value的插入顺序保持一致。

LinkedHashMap可以避免对HashMap,Hashtable里的key-value进行排序(只需要保持插入顺序即可),同时又可避免使用TreeMap所增加的成本。

LinkedHashMap需要维护元素的插入顺序,所以性能略低于HashMap,但因为它以链表的形式来维护内部顺序,因此在迭代访问Map中的全部元素时有更好的性能。

LinkedHashMap linkedHashMap = new LinkedHashMap();
linkedHashMap.put("saber","阿尔托莉雅");
linkedHashMap.put("archer","吉尔伽美什");
linkedHashMap.put("emiya", "卫宫士郎");
//按put顺序输出
linkedHashMap.forEach((key,val)-> System.out.println(key+":"+val));

Properties 读写属性文件

Properties类是Hashtable类的子类,正如它的名字所暗示的,该对象在处理属性文件时特别方便(例如windows下的ini)。Properties类可以把Map对象和属性文件关联起来,而从把Map对象中的key-value对写入属性文件中。也可以把属性文件中“属性名=属性值“加载到Map对象中。

package com.woshi;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class PropertiesTest {
    public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
        properties.setProperty("username","woshi");
        properties.setProperty("password","666");
        //将Properties中的key-value对保存到a.ini文件中
        properties.store(new FileOutputStream("a.ini"),"comment line");

        Properties prop = new Properties();
        prop.setProperty("address","中国");
        //加载配置文件到prop中
        prop.load(new FileInputStream("a.ini"));
        System.out.println(prop);
    }
}

a.ini:

#comment line
#Mon Mar 16 16:51:52 CST 2020
password=666
username=woshi

Properties还可以把key-value的形式以xml文件保存起来,也可以从xml文件中加载key-value对。

SortedMap接口和TreeMap实现类

正如Set接口中派生出SortedSet子接口,SortedSet接口有一个TreeSet实现类一样,Map接口也有一个SortedMap接口,SortedMap接口也有一个TreeMap实现类。

TreeMap就是一个红黑树数据结构,每个key-value对即作为红黑树的一个节点。TreeMap存储key-value对(节点)时,需要根据key对节点进行排序。TreeMap可以保证所有的key-value对处于有序状态。

TreeMap也有两种排序方式:

  • 自然排序:TreeSet的所有key必须实现Comparable接口,而且所有的key应该是同一个类的实例,否则会抛出ClassCastException异常。
  • 定制排序:创建TreeMap时,传入一个Comparable对象,该对象负责对TreeMap中的所有key进行排序。采用定制排序时,不要求key实现Comparable接口。

类似于TreeSet中判断两个元素相等的标准,TreeMap中判断两个key相等的标准是:两个key通过compareTo()方法返回0。TreeMap则认为两个key是相等的。

所以,如果使用自定义类作为TreeMap的key,想让TreeMap良好的工作,则重写该类的equals()方法和compareTo()方法时应该保持一致的结果,一个返回true时,另一个返回0。

package com.woshi;

import java.util.TreeMap;


class R implements Comparable{

    int count;

    public R(int count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "R{" +
                "count=" + count +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        R r = (R) o;
        return count == r.count;
    }

    @Override
    public int compareTo(Object o) {
        R r = (R)o;
        return count > r.count ? 1 : count < r.count ? -1 : 0;
    }
}

public class TreeMapTest {
    public static void main(String[] args) {
        TreeMap treeMap = new TreeMap();
        treeMap.put(new R(3),"3");
        treeMap.put(new R(-9), "-9");
        treeMap.put(new R(-2), "-2");
        treeMap.put(new R(5), "5");
        System.out.println(treeMap);
        //返回该TreeMap的第一个对象
        System.out.println(treeMap.firstEntry());
        //返回该TreeMap的最后一个对象
        System.out.println(treeMap.lastEntry());
        //返回该TreeMap的比new R(2)大的最小key值
        System.out.println(treeMap.higherKey(new R(2)));
        //返回该TreeMap的比new R(2)小的最大key-value
        System.out.println(treeMap.lowerEntry(new R(2)));
        //返回该TreeMap的子TreeMap(仍然是前包括后不包括)
        System.out.println(treeMap.subMap(new R(-10),new R(3)));
    }
}

输出结果:

{R{count=-9}=-9, R{count=-2}=-2, R{count=3}=3, R{count=5}=5}
R{count=-9}=-9
R{count=5}=5
R{count=3}
R{count=-2}=-2
{R{count=-9}=-9, R{count=-2}=-2}

猜你喜欢

转载自www.cnblogs.com/woshi123/p/12505149.html
今日推荐