JavaSE之Map
Map概述
Map是按<键,值>对的形式存储数据的
java.util.Map集合框架:
Map的基本操作
void clear() 清除所有的<键,值>对.
boolean containsKey(Object key) 判断是否包含指定的键.
boolean containsValue(Object value) 判断是否包含指定的值
Set<Map.Entry<K,V>> entrySet() 返回Entry的集合, 一个<键,值>对就是一个Entry
boolean equals(Object o).
V get(Object key) 返回key对应的值
boolean isEmpty() 判断 是否为空.
Set keySet() 返回键的集合
V put(K key, V value) 向Map中添加<key,value>对, 如果键key已存在, 使用value值替换原来的值, Map中的键是不重复的
void putAll(Map<? extends K,? extends V> m)
V remove(Object key) 只要key匹配就删除对应的<键,值>对
default boolean remove(Object key, Object value)要求<key,value>都匹配才会删除
default V replace(K key, V value) 替换
default boolean replace(K key, V oldValue, V newValue)
int size() 返回<键,值>对的数量.
Collection values() 返回值的集合
- 存储顺序可能和添加顺序不一样
- 当键不存在是,会得到null
- 对不存在的键进行修改时,没有任何影响
HashMap
HashMap底层是哈希表(散列表), 哈希表就是一个数组,数组的每个元素是一个单向链表; 在put( k, v )添加键值对时, 先根据键的hashCode计算数组的索引值(下标), 访问数组元素, 如果该元素为null, 创建一个新的结点保存到数组元素中; 如果数组元素不为null, 遍历单向链表的各个结点, 如果有某个结点的key与当前的键equals相等, 就使用新的值v替换结点原来的value值, 如果整个链表中所有结点的key都不匹配, 就创建一个新的结点插入到链表的头部.
HashTable
HashTable 与 HashMap
- 底层都是哈希表(散列表), 但是HashTable是线程安全的, HashMap不是线程安全的
- HashMap的父类是AbstractMap, HashTable的父类是Dictionary
- HashMap默认的初始化容量: 16 , HashTable默认初始化容量: 11
- 加载因子: 0.75 , 当<键,值>对的数量 大于 数组的容量(哈希桶的容量) * 加载因子时 , 数组要扩容
- HashMap扩容默认: 2倍大小; HashTable扩容: 2倍 + 1
- HashMap的键与值都可以为null, HashTable的键与值都不能为null
- HashMap在创建时, 可以指定一个初始化容量, 系统会调整为2的幂次方, 为了快速计算出数组的下标
- HashTable也可以指定初始化容量, 系统不调整
Properties
Properties继承了HashTable, 键与值都是String
经常用于设置/读取系统属性, setPropertty(属性名, 属性值) , getProperty(属性名)
使用Properties读取配置文件
- 经常把属性保存到配置文件中
- 一般情况下,会在当前工程中单独创建一个资源包, 在该包中添加配置文件, 配置文件的后缀名是.properties
在src目录中.java源文件自动编译为.class保存到bin目录中, src目录中非 .java源文件自动复制到bin目录中
3.可以使用Properties读取配置文件的属性
加载配置文件的三种方式
public static void main(String[] args) throws IOException {
//创建Properties对象
Properties properties = new Properties();
//加载配置文件
//单线程程序,使用以下方式
// InputStream inStream = Test07.class.getResourceAsStream("/com/cc/chapter05/resources/config.properties");
//如果在多线程程序中, 也可以使用以下方式
InputStream inStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/cc/chapter05/resources/config.properties");
properties.load(inStream); //如果本行出现空指针异常,一般就是资源文件路径不正确
//读取配置信息
System.out.println( properties.getProperty("username"));
System.out.println( properties.get("password"));
//加载资源时, 不需要扩展名(前提配置文件的扩展名必须是properties), 也不需要斜杠开头
ResourceBundle bundle = ResourceBundle.getBundle("com/cc/chapter05/resources/config");
System.out.println( bundle.getString("username"));
System.out.println( bundle.getString("password"));
}
TreeMap
TreeMap中的键可以是自定义类型, 这种情况很少见
- TreeMap实现了SortedMap, 可以根据键自然排序, 排序原理是二叉树原理
- TreeMap的键必须是可比较的
指定Comparator比较器
如果没有Comparator比较器, 元素的类实现Comparable接口
如何选择HashMap和TreeMap
如果不需要根据键排序就选择HashMap
如果需要根据键排序,就选择TreeMap
注意:
HashMap中的键需要重写equals()/hashCode()方法
TreeMap中的键是根据Comparator/Comparable的比较结果是否为0来判断是否相同