JAVA8除了给Map集合新增了方法remove(Object key,Object value)默认方法外

还增加了以下方法

Object replace(Object key,Object value),与put方法不同,他如果发现原来key不存在也不会增加新的key-value

boolean  replace(Object key,V Oldvalue,V Newvalue)

Object putIfAbsent(Object key,Object value)自动检测该key对应的VALUE是否为空,如果为空,则用value替换原来的 NULL

Object getOrDefault(Object key,V defaultValue)获得指定的Key的value,如果为空就返回默认值defaultValue

其他方法似乎不常用,用到再补充啦

HashMap与HashTable的关系好像ArrayList与Vetor,HashTable比较老旧,HashMap是改进版本,在存在key冲突时候依然有比较好的性能(HashMap采用链表解决冲突)

他们有以下两个典型的区别、

HashMap是线程不安全的,HashTable是线程安全的,所以HashMap有比较好的性能。但是如果多个线程访问Map集合,HashTable的性能更好(尽量少用HashMap

HashTable键值对都不能放null作为key,value HashMap可以null为空,不能重复,value可以多个空

看如下代码:

package Test01;

import java.util.HashMap;

public class TestHashMap {
  public static void main(String[] args) {
    HashMap m  = new HashMap();
    m.put(null, null);
    m.put(null, null);
    m.put("a", "9");
    System.out.println(m);
}
}

 

 运行结果可看,不能把两个null放入HashMap

为了成功在HashMap和HashTable中存储对象,作为Key的Object 的对象必须实现hashcode()和equals方法。也就是说作为key的对象,通过equals返回true后,hashcode()值也必须相等。

那么对于value值呢,HashMap和HashTable都有containValue方法,可判断是否包含了指定的value,那如何判断value相等呢?返回equals比较相等即可。

 

package Test01;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
 class C{
    public int count;
    public  C(int count) {
        this.count =count;
    }
    public  boolean equals(Object obj) {
        if(this == obj) {
            return true;
        }
        if(obj != null && obj.getClass() == C.class) {
            C m =(C) obj;
            return this.count == m.count;
        }
        return false;
    }
    public  int hashcode() {
        return this.count;
    }
    public String toString() {
        return "试试C[count=" + count + "]";
    }
     
}
class B{

    @Override
    public boolean equals(Object arg0) {
        // TODO Cuto-generated method stub
        return true;
    }
    
}
public class TestMap{
   @SuppressWarnings("unchecked")
public static void main(String[] args){
       HashMap m =new HashMap();
       B b= new B();
       m.put(new C(200), "第一次");
       m.put(new C(39), "第二次");
       m.put(new C(450), "第三次");
       m.put(new C(2222), b);
       System.out.println(b.equals("erer "));
      System.out.println( m.containsValue("测试字符串"));   //按理不是返回true,结果返回false
    }
}

 

 与HashSet类似,也尽量不要把可变对象作为hashMap和Hashtable作为key,如果非得,也尽量不要在程序里修改他的实例变量。

HashSet有个子类是LinkedHashSet,hashMap也有子类LinkedhashMap子类    LinkedhashMap用一个双向链表维护Key-value顺序。迭代顺序和插入顺序一致。可以维持顺序的同时又避免使用TreeMap增加的成本。

 

package Test01;

import java.util.LinkedHashMap;

public class D{
  public static void main(String[] args) {
    LinkedHashMap  m =new LinkedHashMap();
    m.put("语文", 80);
    m.put("数学", 23);
    m.put("英语", 123);
    m.forEach((key,value) -> System.out.println( key +" -->"+value));
}
}

 

 下面讲解下Properties类,他是Hashtable的子类(Properties类是一个Key,value都是String类的Map),它处理属性文件(windows的Ini文件就是一种属性文件)特别方便。有以下方法

String getProperty(String key)获得指定属性名的属性值

String getProperty(String key,String defaultValue)获得指定属性名的属性值,如果没有,就设置为defaultValue

Object  setProperty(String key,String Value)设置属性值,;类似Hashtable的put方法

另外还有两种方法读写属性文件

 void load(InputStream inputStream) 从属性文件中(以输入流的形式展示)加载属性值,把加载到的Key-value追加到Properties类里。

void store(OutputStream outputStream,String comments) 把Properties中的Key-value输出到指定的属性文件中,以输出流显示。

package Test01;

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

public class TestProperties {
  public static void main(String[] args) throws FileNotFoundException, IOException {
    Properties properties =new Properties();
    properties.setProperty("a", "今天");
    properties.setProperty("b", "天气");
    properties.store(new FileOutputStream("a.ini"), "contrm");
    System.out.println(properties.getProperty("a"));
    Properties prop2 =new Properties();
    prop2.setProperty("c", "不错");
    prop2.load(new FileInputStream("a.ini"));
    System.out.println(prop2);
}
}

 

 比较HashSet与HashMap的性能选项:

hashSet和其子类都是靠hash算法来决定集合元素的存储位置,并控制集合的大小。

对于Hashtable和HashMap和子类来说,采用hash算法决定Map中key的存储,可增加Key集合大小。

hash表里可以存储元素的位置被称为“桶”,单个桶存储一个元素是有最好的性能。

通过hashcode值算出桶的存储位置。接着从桶里取出元素。

但是hash表是open 的,发生hash冲突时单个桶可以存储多个元素,元素以链表形式存储,必须按顺序搜索。

hash表有以下属性:

容量:hash表的桶的数量

初始化容量:创建hash表时桶的数量,在构造器中指定初始化容量。 

尺寸:当前hash表记录的数量。

负载因子:为0表示空的hash表,0.5表示半满的。轻负载的hash表表示冲突少,适合插入和查询。

还有个负载极限:决定最大填满程度,达到负载极限时自动的成倍增加容量。将原有的对象重新分配 ,放入新的桶里,叫做rehashing.较低的负载极限可以提高查询数据的性能,但会增加hash表

所占用的内存的开销。


如果最开始就知道HashSet和HashMap Hashtable会保存许多记录,就在创建时用较大的初始化容量。初始化容量大于 包含的最大记录数除以负载极限就不会rehashing.

使用足够大的初始化容量能更高效得增加记录。但是太高会浪费空间。
 
 
对比下:
WeakHashMap实现类

与hashMap基本相似,但是区别在于HashMap的Key保留了对实际对象的强引用。意思就是:只要该HashMap对象不销毁,所有的key引用的对象就不会被垃圾销毁。

但是WeakHashMap对象的key引用的对象没有被其他强引用变量引用,则这些key引用的对象就可能被垃圾回收。举例子:

.....

IdentityHashMap实现类

实现机制与HashMap基本类似。但是对于Key的判断相等不同。IdentityHashMap key===(查下资料)才等,而HashMap equals为true,且hashcode值相等即可。

,举例
.....