Java集合中的框架2
一、HashMap类和Hashtable类的用法TreeMap与ConcurrentHashMap
Map接口--集合接口--主要处理的是键值对结构的数据
键值对结构的数据---就是一个完成的数据是由键和键所对应的值组合而成的数据
例如:
书的目录就是一种键值对结构
【标题----页码】
Map接口下的子类
1.HashMap类--public class HashMap【基于哈希表的实现的Map接口】
允许null的值和null键
数据保存是无序的
不能有重复的键,重复的键被算作是一个数据。
构造方法:
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.hashmaptest;
import java.util.HashMap;
public class HashMapTest1 {
public static void main(String[] args) {
//Map 接口下的子类
//HashMap类
//允许null的值和null键
//数据保存时无序的
//不能有重复的键,重复的键被算作是一个数据
//构造方法:
//HashMap()构造一个空的HashMap,默认初始容量(16)和默认负载系数(0.75)
HashMap<Object, Object> hashMap=new HashMap<>();
//HashMap(int initialCapacity)构造一个空的HashMap具有指定的初始容量和默认负载因子(0.75)
HashMap<Object, Object> hashMap2=new HashMap<>(30);
//HashMap(int initialCapacity,float loadFactor)构造一个空的HashMap具有指定的初始容量和指定的负载因子
HashMap<Object, Object> hashMap3=new HashMap<>(30, 0.5F);
//HashMap(Map m)构造一个新的HashMap与指定的相同的映射Map
HashMap<Object, Object> hashMap4=new HashMap<>(hashMap3);
}
}
实例方法:
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.hashmaptest;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class HashMapTest2 {
public static void main(String[] args){
//HashMap类的常用实例方法
//允许null的值和null键
//数据保存是无序的
//不能有重复的键,重复的键被算作是一个数据
HashMap<Object, Object> hashMap=new HashMap<>();
//Object put(Object key,Object value)向集合中添加键值对数据
hashMap.put("hello", 1234);
hashMap.put(1234, "hello");
hashMap.put(12.5, true);
hashMap.put(false, 123.1);
hashMap.put(null, "null键");
hashMap.put("null值", null);
hashMap.put(null, null);//会被算作一个
// int size()得到集合中键值对元素的个数
System.out.println("size=="+hashMap.size());
//boolean containsKey(Object key)判断集合中是否包含指定的键
String containsKey=(hashMap.containsKey("helloworld"))?"存在":"不存在";
System.out.println("containskey=="+containsKey);
//boolean containsValue(Object value)判断集合中是否存在指定的值
String containsValue=(hashMap.containsValue("helloworld"))?"存在":"不存在";
System.out.println("containsvaule=="+containsValue);
//Object get(Object key)根据指定的键得到该键对应的值
System.out.println("get=="+hashMap.get("hello"));
//V remove(Object key)根据指定的键删除对应的键值对数据值
hashMap.remove("null值");
System.out.println("size=="+hashMap.size());
//void clear()清空集合
//hashMap.clear();
//boolean isEmpty()判断集合是否为空
String pd=(hashMap.isEmpty())?"是":"否";
System.out.println("集合是否为空?"+pd);
/*
* Set keySet()得到集合中所有的键保存到Set集合中
* Collectionvalue()方法用于检查HashMap中的单个键或多个键是否映射了特定值。它使用Value作为参数,如果该值由映射中的任何键映射,则返回True
* Set<Map.Entry<k,v>> entrySet()得到集合中所有的键值对数据Set集合中
*
*/
Set set=hashMap.keySet();
boolean collection=hashMap.containsValue("hello");
System.out.println(collection);
Set<Map.Entry<Object,Object>> maps=hashMap.entrySet();
System.out.println("maps=="+maps);
}
}
遍历HashMap集合:
package com.wangxing.hashmaptest;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapTest3 {
public static void main(String[] args) {
//HashMap的遍历
HashMap<Object,Object> hashMap=new HashMap<Object, Object>();
hashMap.put("hello",1234);
hashMap.put(1234,"hello");
hashMap.put(12.5,true);
hashMap.put(false,168.5);
hashMap.put(null,"null键");
hashMap.put("null值",null);
//遍历集合中所有的键保存到Set集合中Set keySet()
Set<Object> objects=hashMap.keySet();
for (Object key : objects) {
System.out.println("key=="+key);
}
System.out.println("----------");
Iterator<Object> iterator=objects.iterator();
while(iterator.hasNext()){
Object object=iterator.next();
System.out.println("key2=="+object);
}
System.out.println("-------------");
//遍历集合中所有值保存到Collection集合中 values()
Collection<Object> collection=hashMap.values();
for (Object val : collection) {
System.out.println("val=="+val);
}
System.out.println("----------------");
Iterator<Object> iterator2=collection.iterator();
while(iterator2.hasNext()){
Object val2=iterator2.next();
System.out.println("val2=="+val2);
}
System.out.println("------------------");
//Set<Map.Entry<K,V>> entrySet()得到集合中所有的键值对数据Set集合中
Set<Map.Entry<Object, Object>> objects2=hashMap.entrySet();
System.out.println("obj1=="+objects2);
for (Map.Entry<Object, Object> entry : objects2) {
System.out.println(entry.getKey()+"---"+entry.getValue());
}
for (Object object : objects2) {
System.out.println("obj22"+object);
}
}
}
2.Hashtable类---public class Hashtable<K,V> 该类实现了一个哈希表,它将键映射到值。
- 无序
- 不能有null键/null值
- 用作键的对象必须实现hashCode方法和equals方法。
- 不能有重复的键,重复的键被算作是一个数据。
- 线程安全
构造方法
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.HashMap;
import java.util.Hashtable;
public class HashtableTest1 {
public static void main(String[] args) {
//Hashtable类
//无序
//不能有null键/null值
//用作键的对象必须实现hashCode方法和equals方法
//不能有重复的键,重复的键被算作是一个数据
//线程安全
//构造方法
//Hashtable()构造一个新的,空的散列表,默认初始容量(11)和负载因子(0.75)
Hashtable<Object, Object> hashtable=new Hashtable<>();
//Hashtable(int initialCapacity)构造一个新的,空的哈希表,具有指定的初始容量和默认的负载因子
Hashtable<Object, Object> hashtable2=new Hashtable<>(30);
//Hashtable(int initialCaoacity,float loadDactor)构造一个新的,空的哈希表,具有指定的初始容量和指定的负载因子
Hashtable<Object, Object> hashtable3 = new Hashtable<>(30, 0.5F);
//Hashtable(Map t)构造一个与给定地图相同的映射的新的哈希表
Hashtable<Object, Object> hashtable4=new Hashtable<>(hashtable);
HashMap<Object, Object> hashMap=new HashMap<>();
Hashtable<Object, Object> hashtable5=new Hashtable<>(hashMap);
}
}
实例方法
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() 返回此散列表中值的枚举。 |
//创建一个作为put方法参数的对象
package com.wangxing.hashtable;
public class UserBean {
}
package com.wangxing.hashtable;
import java.util.Enumeration;
import java.util.Hashtable;
public class HashteabeTest2 {
public static void main(String[] args) {
//Hashtable类的常用实例方法
//无序
//不能有null键/null值
//用作键的对象必须实现hashCode方法和equals方法
//不能有重复的键,重复的键被算作是一个数据
//线程安全
Hashtable<Object, Object> hashtable=new Hashtable<>();
//Object put(Object key,Object Value)向集合中添加键值对数据
hashtable.put("hello", 12134);
hashtable.put(1234, "hello");
hashtable.put(12.3, "hello");
hashtable.put(true, false);
// java.lang.NullPointerException
// at java.util.Hashtable.put(Unknown Source)
//hashtable.put(null, "null键");
//用作键的对象必须实现hashCode方法和equals方法
UserBean user=new UserBean();
hashtable.put(user, "userBean");
//int size()得到集合中键值对与元素的个数
System.out.println("size=="+hashtable.size());
//boolean containsKey(Object key)判断集合中是否半酣指定的键
System.out.println("containskey=="+hashtable.containsKey("user"));
//boolean containsValue(Object value)判断集合中是否包含指定的值
System.out.println("containsValue=="+hashtable.containsValue("userBean"));
//Object get(Object key)根据指定的键得到该键对应的值
System.out.println("get=="+hashtable.get(user));
//V remover(Object key)根据指定的键删除对应的键的值
hashtable.remove("hello");
System.out.println("size=="+hashtable.size());
//void clear()清空集合 hashtable.clera();
//isEmpty()判断集合是否为空
System.out.println("isEmpty=="+hashtable.isEmpty());
/*
Set keySet() 得到集合中所有的键保存到Set集合中
Collection values() 得到集合中所有的值保存到Collection集合中
Set<Map.Entry<K,V>> entrySet() 得到集合中所有的键值对数据Set集合中
Enumeration<K> keys() 返回此散列表中键的枚举。
Enumeration<V> elements() 返回此散列表中值的枚举。
*/
Enumeration<Object> enumeration=hashtable.keys();
while (enumeration.hasMoreElements()) {
Object key = (Object) enumeration.nextElement();
System.out.println("key=="+key);
}
Enumeration<Object> enumeration2=hashtable.elements();
while (enumeration2.hasMoreElements()) {
Object value = (Object) enumeration2.nextElement();
System.out.println("value=="+value);
}
}
}
遍历Hashtable集合:
package com.wangxing.hashtable;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.print.attribute.standard.MediaName;
public class HashtableTest3 {
public static void main(String[] args) {
//Hashtable类的遍历
Hashtable<Object, Object> hashtable=new Hashtable<>();
hashtable.put("hello",1234);
hashtable.put(1234,"hello");
hashtable.put(12.5,true);
hashtable.put(false,168.5);
//遍历所有键 Set keyset()/Enumeration<K> keys()
Set<Object> keys=hashtable.keySet();
for (Object key : keys) {
System.out.println("key=="+key);
}
System.out.println("----------------------");
Iterator<Object> iterator=keys.iterator();
while (iterator.hasNext()) {
Object key = (Object) iterator.next();
System.out.println("key=="+key);
}
System.out.println("------------------");
/*
Set keySet() 得到集合中所有的键保存到Set集合中
Collection values() 得到集合中所有的值保存到Collection集合中
Set<Map.Entry<K,V>> entrySet() 得到集合中所有的键值对数据Set集合中
Enumeration<K> keys() 返回此散列表中键的枚举。
Enumeration<V> elements() 返回此散列表中值的枚举。
*/
Enumeration<Object> enumeration=hashtable.keys();
while (enumeration.hasMoreElements()) {
Object key = (Object) enumeration.nextElement();
System.out.println("key=="+key);
}
System.out.println("------------");
//遍历所有值 Collection values()/Enumeration<V> elements()
Collection<Object> collection=hashtable.values();
for (Object value : collection) {
System.out.println("value=="+value);
}
System.out.println("------------");
Iterator<Object> iterator2=collection.iterator();
while (iterator2.hasNext()) {
Object value= (Object) iterator2.next();
System.out.println("value=="+value);
}
System.out.println("------------------");
Enumeration<Object> enumeration2=hashtable.elements();
while(enumeration2.hasMoreElements()){
Object val=enumeration2.nextElement();
System.out.println("val=="+val);
}
System.out.println("-----------------");
//Set<Map.Entry<K,V>> entrySet()得到集合中所有键值对数据Set集合中
Set<Map.Entry<Object, Object>> set=hashtable.entrySet();
for(Object val:set){
System.out.println("val=="+val);
}
System.out.println("------------------");
for (Map.Entry<Object, Object> entry : set) {
System.out.println(entry.getKey()+"~~~"+entry.getValue());
}
}
}
3.TreeMap类--红黑树基于NavigableMap实现【有序】
4.ConcurrentHashMap类---线程安全,支持高并发,哈希表
二、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接口 |
线程不安全 |
线程安全 |
线程不安全 |
三、认识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.Collection;
import java.util.Collections;
public class CollectionsTest1 {
public static void main(String[] args) {
//Collections类【集合类的帮助类】
//此类中的方法都是静态方法,静态方法为了帮助我们更加方便的操作集合中的数据
ArrayList arrayList=new ArrayList<>();
arrayList.add(123);
//类型转换错误
// java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Boolean
//arrayList.add(true);
arrayList.add(12);
arrayList.add(3);
arrayList.add(345);
for (Object object : arrayList) {
System.out.println("排序前:--"+object);
}
//static void sort(List<T>list)根据元素的natural ordering对指定的列表进行排序
Collections.sort(arrayList);
for (Object object : arrayList) {
System.out.println("排序后---"+object);
}
//static void reverse(List<?>list)反转指定列表中的元素顺序
Collections.reverse(arrayList);
for (Object object:arrayList){
System.out.println("反转后=="+object);
}
//static T max(Collection<?extendsT>coll)根据其元素的自然顺序返回给定集合的最大元素
System.out.println("最大元素--"+Collections.max(arrayList));
//static T min(Collection<?extends T>coll)根据其元素的自然顺序返回给定集合的最小元素
System.out.println("最小元素--"+Collections.min(arrayList));
//static <T> void copy(List<?super T>dest,List<? extends T>src)将所有元素从一个列表复制到另一个列表中
ArrayList arrayList2=new ArrayList<>();
arrayList2.add("zhangsan");
arrayList2.add("lisi");
//arrayList2.add("wangwu");
//arrayList2.add("zhaoliu");
//java.lang.IndexOutOfBoundsException: Source does not fit in dest
//下表越界
/*
* copy()方法是:
得到原来集合的大小, int srcSize = src.size();
如果srcSize大于dest.size,将会抛出异常
if (srcSize > dest.size())
throw new IndexOutOfBoundsException(“Source does not fit in dest”);
*/
//arrayList2.add("test");
//源集合arraylist2==目标集合arraylist【源集合中的元素会覆盖目标集合中的元素】
/*
Collections.copy(arrayList, arrayList2);
for(Object object:arrayList){
System.out.println("copy后=="+object);
}
*/
//源集合arrayList2<目标集合arrayList【源集合中的元素会覆盖目标集合中的元素,会有遗留】
/*
Collections.copy(arrayList, arrayList2);
for (Object object : arrayList) {
System.out.println("copy后=="+object);
}
*/
//源集合list2 > 目标集合list1 [java.lang.IndexOutOfBoundsException]
/*
Collections.copy(arrayList, arrayList2);
for(Object obj:arrayList){
System.out.println("copy后--"+obj);
}
*/
注意与Arrays的比较
}
}
四、Collection接口与Collections类的区别
Collection接口 |
Collections类 |
Interface |
Class |
包含了一些集合的基本操作方法【增删改查】 |
集合框架的帮助类对集合的排序,搜索以及序列化的操作 |