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和其子类都是靠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.
使用足够大的初始化容量能更高效得增加记录。但是太高会浪费空间。
与hashMap基本相似,但是区别在于HashMap的Key保留了对实际对象的强引用。意思就是:只要该HashMap对象不销毁,所有的key引用的对象就不会被垃圾销毁。
但是WeakHashMap对象的key引用的对象没有被其他强引用变量引用,则这些key引用的对象就可能被垃圾回收。举例子:
.....
IdentityHashMap实现类
实现机制与HashMap基本类似。但是对于Key的判断相等不同。IdentityHashMap key===(查下资料)才等,而HashMap equals为true,且hashcode值相等即可。
,举例