集合框架-2
8.7.HashMap类和Hashtable类的用法TreeMap与ConcurrentHashMap
Map接口--集合接口--主要处理的是键值对结构的数据
键值对结构的数据---就是一个完成的数据是由键和键所对应的值组合而成的数据
例如:书的目录就是一种键值对结构 【标题----页码】
Map接口下的子类 HashMap类--public class HashMap【基于哈希表的实现的Map接口】
1.允许null的值和null键
2.数据保存是无序的
3. 不能有重复的键,重复的键被算作是一个数据。
构造方法:
HashMap() 构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。 |
HashMap(int initialCapacity) 构造一个空的 HashMap具有指定的初始容量和默认负载因子(0.75)。 |
HashMap(int initialCapacity, float loadFactor) 构造一个空的 HashMap具有指定的初始容量和负载因子。 |
HashMap(Map<? extends K,? extends V> m) 构造一个新的 HashMap与指定的相同的映射 Map 。 |
package com.wangxing.hashmap;
import java.util.HashMap;
public class Test1 {
public static void main(String[] args) {
//Map接口下的子类
//HashMap类
//允许null的值和null键
//数据保存是无序的
//不能有重复的键,重复的键被算作是一个数据。
//构造方法:
//HashMap() 构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。
HashMap map1=new HashMap();
//HashMap(int initialCapacity) 构造一个空的 HashMap具有指定的初始容量和默认负载因子
//(0.75)。
HashMap map2=new HashMap(30);
//HashMap(int initialCapacity, float loadFactor) 构造一个空的 HashMap具有指定的初始
//容量和负载因子。
HashMap map3=new HashMap(40,0.9f);
//HashMap(Map m) 构造一个新的 HashMap与指定的相同的映射 Map 。
HashMap map4=new HashMap(map2);
}
}
实例方法:
void | clear() 清空集合。 |
Object | put(Object key, Object value) 向集合中添加键值对数据 |
boolean | containsKey(Object key) 判断集合中是否包含指定的键 |
boolean | containsValue(Object value) 判断集合中是否包含指定的值 |
Object | get(Object key) 根据指定的键得到该键对应的值 |
boolean | isEmpty() 判断集合是否为空。 |
int | size() 得到集合中键值对元素的个数 |
V | remove(Object key) 根基指定的键删除对应的键值对数据值 |
Set | keySet() 得到集合中所有的键保存到Set集合中 |
Collection | values() 得到集合中所有的值保存到Collection集合中 |
Set<Map.Entry<K,V>> | entrySet() 得到集合中所有的键值对数据Set集合中 |
package com.wangxing.hashmap;
import java.util.HashMap;
public class Test2 {
public static void main(String[] args) {
//HashMap的实例方法
//允许null的值和null键
//数据保存是无序的
//不能有重复的键,重复的键被算作是一个数据。
HashMap map1=new HashMap();
//Object put(Object key, Object value) 向集合中添加键值对数据
map1.put("hello",1234);
map1.put(1234,"hello");
map1.put(12.5,true);
map1.put(false,168.5);
map1.put(null,"null键");
map1.put("null值",null);
//int size() 得到集合中键值对元素的个数
System.out.println("size=="+map1.size());//6
//boolean containsKey(Object key) 判断集合中是否包含指定的键
System.out.println("containsKey=="+map1.containsKey(1234));//true
String st1=(map1.containsKey(1234))?"存在":"不存在";
System.out.println(st1);//存在
//boolean containsValue(Object value) 判断集合中是否包含指定的值
System.out.println("containsValue=="+map1.containsValue(168.5));//true
String st2=(map1.containsValue(168.5))?"存在":"不存在";
System.out.println(st2);//存在
//Object get(Object key) 根据指定的键得到该键对应的值
System.out.println("ger=="+map1.get(null));//null键
//V remove(Object key) 根基指定的键删除对应的键值对数据值
map1.remove(null);
System.out.println(map1.size());//5
//void clear() 清空集合。
map1.clear();
System.out.println(map1.size());//0
//boolean isEmpty() 判断集合是否为空。
System.out.println(map1.isEmpty());//true
}
}
HashMap的遍历方法
package com.wangxing.hashmap;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Test3 {
public static void main(String[] args) {
//HashMap的遍历方法
HashMap<Object,Object> map1=new HashMap();
map1.put("hello",1234);
map1.put(1234,"hello");
map1.put(12.5,true);
map1.put(false,168.5);
map1.put(null,"null键");
map1.put("null值",null);
//遍历集合中所有的键保存到Set集合中Set keySet()
//增强的for循环
Set s=map1.keySet();
for(Object obj:s){
System.out.println("键=="+obj);
}
System.out.println("------------");
//遍历集合中所有的键保存到Set集合中Set keySet()
//iterator迭代器方法
Iterator it=s.iterator();
while(it.hasNext()){
Object obj=it.next();
System.out.println("键=="+obj);
}
System.out.println("------------");
//遍历集合中所有的值保存到Collection集合中 values()
//增强的for循环
Collection c1=map1.values();
for(Object obj2:c1){
System.out.println("值=="+obj2);
}
System.out.println("------------");
//遍历集合中所有的值保存到Collection集合中 values()
//iterator迭代器方法
Iterator it2=c1.iterator();
while(it2.hasNext()){
Object obj3=it2.next();
System.out.println("值=="+obj3);
}
System.out.println("------------");
//Set<Map.Entry<K,V>> entrySet() 得到集合中所有的键值对数据Set集合中
Set keyval=map1.entrySet();
for(Object obj4:keyval){
System.out.println("键值对=="+obj4);
}
System.out.println("------------");
Iterator it3=keyval.iterator();
while(it3.hasNext()){
Object obj5=it3.next();
System.out.println("键值对=="+obj5);
}
//调整成自己想要的格式输出
System.out.println("------------");
for(Map.Entry<Object, Object> ent:map1.entrySet()){
System.out.println("键值对=="+ent.getKey()+"--"+ent.getValue());
}
}
}
Hashtable类---public class Hashtable<K,V> 该类实现了一个哈希表,它将键映射到值
1.无序
2.不能有null键/null值
3.用作键的对象必须实现hashCode方法和equals方法。
4.不能有重复的键,重复的键被算作是一个数据。
5.线程安全
构造方法:
Hashtable() 构造一个新的,空的散列表,默认初始容量(11)和负载因子(0.75)。 |
Hashtable(int initialCapacity) 构造一个新的,空的哈希表,具有指定的初始容量和默认负载因子(0.75)。 |
Hashtable(int initialCapacity, float loadFactor) 构造一个新的,空的哈希表,具有指定的初始容量和指定的负载因子。 |
Hashtable(Map<? extends K,? extends V> t) 构造一个与给定地图相同的映射的新哈希表。 |
package com.wangxing.hashtable;
import java.util.Hashtable;
public class Test1 {
public static void main(String[] args) {
//Hashtable类
//无序
//不能有null键/null值
//用作键的对象必须实现hashCode方法和equals方法。
//不能有重复的键,重复的键被算作是一个数据。
//线程安全
//构造方法
//Hashtable() 构造一个新的,空的散列表,默认初始容量(11)和负载因子(0.75)。
Hashtable t1=new Hashtable();
//Hashtable(int initialCapacity) 构造一个新的,空的哈希表,具有指定的初始容量和默认负
//载因子(0.75)。
Hashtable t2=new Hashtable(50);
//Hashtable(int initialCapacity, float loadFactor) 构造一个新的,空的哈希表,具有指
//定的初始容量和指定的负载因子。
Hashtable t3=new Hashtable(60,0.99f);
//Hashtable(Map t) 构造一个与给定地图相同的映射的新哈希表。
Hashtable t4=new Hashtable(t2);
}
}
实例方法:
void | clear() 清空集合。 |
Object | put(Object key, Object value) 向集合中添加键值对数据 |
boolean | containsKey(Object key) 判断集合中是否包含指定的键 |
boolean | containsValue(Object value) 判断集合中是否包含指定的值 |
Object | get(Object key) 根据指定的键得到该键对应的值 |
boolean | isEmpty() 判断集合是否为空。 |
int | size() 得到集合中键值对元素的个数 |
V | remove(Object key) 根基指定的键删除对应的键值对数据值 |
Set | keySet() 得到集合中所有的键保存到Set集合中 |
Collection | values() 得到集合中所有的值保存到Collection集合中 |
Set<Map.Entry<K,V>> | entrySet() 得到集合中所有的键值对数据Set集合中 |
Enumeration<K> | keys() 返回此散列表中键的枚举。 |
Enumeration<V> | elements() 返回此散列表中值的枚举。 |
package com.wangxing.hashtable;
//创建一个空的Student类
public class Student {
}
package com.wangxing.hashtable;
import java.util.Hashtable;
public class Test2 {
public static void main(String[] args) {
//Hashtable类
//无序
//不能有null键/null值
//用作键的对象必须实现hashCode方法和equals方法。
//不能有重复的键,重复的键被算作是一个数据。
//线程安全
//常用的实例方法
Hashtable t1=new Hashtable();
//Object put(Object key, Object value) 向集合中添加键值对数据
t1.put("hello",1234);
t1.put(1234,"hello");
t1.put(12.5,true);
t1.put(false,168.5);
//不能有null键/null值
//java.lang.NullPointerException
//t1.put(null, 1234);
//t1.put(2334, null);
//用作键的对象必须实现hashCode方法和equals方法。
Student stu1=new Student();
t1.put(stu1, 789);
//int size() 得到集合中键值对元素的个数
System.out.println("size=="+t1.size());//5
//boolean containsKey(Object key) 判断集合中是否包含指定的键
System.out.println("containsKey=="+t1.containsKey(false));//true
String st1=(t1.containsKey(false))?"存在":"不存在";
System.out.println(st1);//存在
//boolean containsValue(Object value) 判断集合中是否包含指定的值
System.out.println("containsValue=="+t1.containsValue(1234));//true
String st2=(t1.containsValue(1234))?"存在":"不存在";
System.out.println(st2);//存在
//Object get(Object key) 根据指定的键得到该键对应的值
System.out.println("get=="+t1.get(false));//168.5
//V remove(Object key) 根基指定的键删除对应的键值对数据值
t1.remove(false);
System.out.println(t1.size());//4
//void clear() 清空集合。
//boolean isEmpty() 判断集合是否为空。
t1.clear();
System.out.println(t1.size());//0
System.out.println("isEmpty=="+t1.isEmpty());//true
}
}
Hashtable类的遍历
package com.wangxing.hashtable;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Test3 {
public static void main(String[] args) {
//Hashtable类的遍历
Hashtable<Object,Object> t1=new Hashtable();
t1.put("hello",1234);
t1.put(1234,"hello");
t1.put(12.5,true);
t1.put(false,168.5);
//遍历所有键Set keySet()/Enumeration<K> keys()
Set s1=t1.keySet();
for(Object obj1:s1){
System.out.println("键=="+obj1);
}
System.out.println("------------");
Iterator it=s1.iterator();
while(it.hasNext()){
Object obj2=it.next();
System.out.println("键=="+obj2);
}
System.out.println("------------");
//遍历所有值Collection values() /Enumeration<V> elements()
Collection c1=t1.values();
for(Object obj3:c1){
System.out.println("值=="+obj3);
}
System.out.println("------------");
Iterator it2=c1.iterator();
while(it2.hasNext()){
Object obj4=it2.next();
System.out.println("值=="+obj4);
}
System.out.println("------------");
//Set<Map.Entry<K,V>> entrySet() 得到集合中所有的键值对数据Set集合中
Set set1=t1.entrySet();
for(Object obj5:set1){
System.out.println("键值对=="+obj5);
}
System.out.println("------------");
//调整成自己想要的输出格式
for(Map.Entry<Object,Object> ent:t1.entrySet()){
System.out.println("键值对=="+ent.getKey()+"---"+ent.getValue());
}
}
}
TreeMap类--红黑树基于NavigableMap实现【有序】
ConcurrentHashMap类---线程安全,支持高并发,哈希表
8.8.HashMap类与Hashtable类与TreeMap类与ConcurrentHashMap类的区别
HashMap类 | Hashtable类 |
可以有null键/null值 | 不能有null键/null值 |
HashMap继承AbstractMap类 | Hashtable继承Dictionary类 |
默认容量为16 | 默认容量为11 |
将容量变为原来的2倍。 | 将容量变为原来的2倍加1 |
线程不安全 | 线程安全 |
HashMap底层实现原理:HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 HashMap在每个链表节点中储存键值对对象。当两个不同的键对象的hashcode相同时会发生什么? 它们会储存在同一个bucket位置的链表中。键对象的equals()方法用来找到键值对。
HashMap类 | ConcurrentHashMap类 |
线程不安全 | 线程安全 |
Hashtable类 | ConcurrentHashMap类 |
线程安全高并发是效率低 | 线程安全高并发是效率高 |
HashTable里使用的是synchronized关键字,这其实是对对象加锁,锁住的都是对象整体,当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。
ConcurrentHashMap使用了分割,将一个map分成多个小的hashtable,对map的一部分进行上锁。保证同步的同时,有提高了性能。
HashMap类 | Hashtable类 | TreeMap类 |
无序 哈希表 | 无序 哈希表 | 有序的key-value集合 红黑树实现 |
HashMap继承AbstractMap类 | Hashtable继承Dictionary类 | 继承AbstractMap类 NavigableMap接口 |
线程不安全 | 线程安全 | 线程不安全 |
8.9.认识Collections类【集合类的帮助类】
public class Collections----此类仅由静态方法组合或返回集合。此类中的方法都是静态方法,静态方法为了帮助我们更加方便的操作集合中的数据。
static <T extends Comparable<? super T>> | sort(List<T> list) 根据其元素的natural ordering对指定的列表进行排序。 |
static void | reverse(List<?> list) 反转指定列表中元素的顺序。 |
static <T> void | copy(List<? super T> dest, List<? extends T> src) 将所有元素从一个列表复制到另一个列表中。 |
static <T extends Object & Comparable<? super T>> | max(Collection<? extends T> coll) 根据其元素的 自然顺序返回给定集合的最大元素。 |
static <T extends Object & Comparable<? super T>> | min(Collection<? extends T> coll) 根据其元素的 自然顺序返回给定集合的最小元素。 |
此类中的方法都是静态方法,静态方法为了帮助我们更加方便的操作集合中的数据。
package com.wangxing.collections;
import java.util.ArrayList;
import java.util.Collections;
public class Test1 {
public static void main(String[] args) {
//Collections类【集合类的帮助类】
//此类中的方法都是静态方法,静态方法为了帮助我们更加方便的操作集合中的数据。
ArrayList list1=new ArrayList();
list1.add(123);
list1.add(12);
list1.add(3);
list1.add(345);
for(Object obj:list1){
System.out.println("排序前=="+obj);
}
System.out.println("------------------");
//Collections.sort--升序
Collections.sort(list1);
for(Object obj1:list1){
System.out.println("排序后=="+obj1);
}
System.out.println("------------------");
//Collections.reverse(list1)--反序
Collections.reverse(list1);
for(Object obj2:list1){
System.out.println("反序后=="+obj2);
}
//static T max(Collection<? extends T> coll) 根据其元素的 自然顺序返回给定集合的最
//大元素。
System.out.println("MAX=="+Collections.max(list1));//345
//static T min(Collection<? extends T> coll) 根据其元素的 自然顺序返回给定集合的最
//小元素。
System.out.println("MIN=="+Collections.min(list1));//3
//static <T> void copy(List<? super T> dest, List<? extends T> src) 将所有元素从
//一个列表复制到另一个列表中。
ArrayList list2=new ArrayList();
list2.add("zhangsan");
list2.add("lisi");
list2.add("wangwu");
list2.add("zhaoliu");
list2.add("test");
/*
//源集合list2 == 目标集合list1 [源集合中的元素会覆盖目标集合中的元素]
Collections.copy(list1, list2);
for(Object obj:list1){
System.out.println("copy后--"+obj);
}
*/
/*
//源集合list2 < 目标集合list1 [源集合中的元素会覆盖目标集合中的元素,会有遗留]
Collections.copy(list1, list2);
for(Object obj:list1){
System.out.println("copy后--"+obj);
}
*/
//源集合list2 > 目标集合list1 [java.lang.IndexOutOfBoundsException]
//原集合的元素多于目标集合中的 元素,会运行出现错误
/*
Collections.copy(list1, list2);
for(Object obj:list1){
System.out.println("copy后--"+obj);
}
*/
}
}
8.10.Collection接口与Collections类的区别
Collection接口 | Collections类 |
Interface | Class |
包含了一些集合的基本操作方法【增删改查】 | 集合框架的帮助类对集合的排序,搜索以及序列化的操作 |