概述
- 集合又称对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。
- 与数组的区别:
- (1)数组长度固定,集合长度可变
- (2)数组可以存储基本类型和引用类型,集合只能存储引用类型
- 位置:
java.util.*
各集合继承关系如图:
JDK6快速访问地址
JDK8快速访问地址
Map 接口
Java.util.map<k,v>
特点:Map 接口是双例集合,每个元素由键与值两部分组成,键不可以重复,值可以,每个键只能对应一个值。
注意:基本数据类型不接收null值,应当用包装类来接收可能存在的null值
(1)Set<K> keySet();
详解
代码:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* @author Nigori
* @date 2020/5/17
**/
public class KetSetTest_1 {
public static void main(String[] args) {
//创建Map集合
Map<String,Integer> map = new HashMap<>();
map.put("沉香",235);
map.put("白扣",256);
map.put("白芷",164);
//1.使用Map中的keySet()方法,将Map集合中的所有Key取出来存放到Set集合中
Set<String> set = map.keySet();
//2.创建迭代器,遍历Set集合,拿到每一个key(foreach不在赘述)
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
//3.通过Map集合中的get()方法,获得与之对应的value
Integer value = map.get(key);
System.out.println(key+" = "+value);
}
}
}
(2) Set<Map.Entry<K,V>> entrySet()
详解
代码:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* @author Nigori
* @date 2020/5/17
**/
public class KetSetTest_2 {
public static void main(String[] args) {
//创建Map集合
Map<String,Integer> map = new HashMap<>();
map.put("沉香",235);
map.put("白扣",256);
map.put("白芷",164);
//使用Map集合中的enterSet()方法,把Map集合中多个Entry对象取出来,存储到一个Set集合中
Set<Map.Entry<String,Integer>> set = map.entrySet();
//2.创建迭代器,遍历Set集合,获取每一个Entry对象
Iterator<Map.Entry<String,Integer>> iterator = set.iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
//3.使用Entry对象中的方法getKey()和getValue()获取键与值
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+" = "+value);
}
}
}
Map 接口常用的实现类
1、HashMap
java.util.HashMap<k,v>
实现 Map<k,v>
接口
特点:底层是哈希表;是一个无序集合,使用 Key 的 hashCode() 和 equal() 确保 Key 值唯一。
源码分析:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
hashMap初始容量大小static final int MAXIMUM_CAPACITY = 1 << 30;
hashmap的数组最大容量static final float DEFAULT_LOAD_ACTOR = 0.75f;
默认加载因子static final int TREEIFY_THRESHOLD = 8;
jdk1.8 当链表长度大于8时,调整成红黑数static final int UNTREEIFY_THRESHOLD = 6;
jdk1.8 当链表长度小于6时,调整成链表static final int MIN_TREEIFY_CAPACITY = 64;
jdk1.8 当链表长度大于8时,并且集合元素个数大于等于64时,调整成红黑数transient Node<K, V>[] table;
哈希表中的数组size;
元素个数
特性:
- (1) HashMap刚创建时,table 是 null,为了节省空间,当添加第一个 元素时,table容 量调整为16
- (2) 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数。
- (3) jdk1.8当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的提高执行效率
- (4) jdk1.8以前,链表时头插入,jdk1 .8以后时是尾插入
- ① HashMap存储自定义类型键值
- key:String类型
-
String类型重写hashCode()方法和equal()方法,可以保证key唯一
-
- value:Person类型
-
value可以重复
-
- key:String类型
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author Nigori
* @date 2020/5/17
**/
public class HashMapTest {
public static void main(String[] args) {
test_01();
}
private static void test_01() {
HashMap<String,Person> hashMap = new HashMap<>();
hashMap.put("南京",new Person("小新",25));
hashMap.put("北京",new Person("小月",21));
hashMap.put("天津",new Person("小青",24));
hashMap.put("南京",new Person("小杨",25));
Set<String> set = hashMap.keySet();
for (String key:set) {
Person value = hashMap.get(key);
System.out.println(key+"--->"+value);
/* 结果:
天津--->Person{name='小青', age=24}
南京--->Person{name='小杨', age=25}
北京--->Person{name='小月', age=21}
*/
}
}
}
- ② HashMap存储自定义类型键值
- key:Person类型
-
Person类必须重写hashCode()方法和equal()方法,可以保证key唯一
-
- value:String类型
-
可以重复
-
- key:Person类型
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapTest {
public static void main(String[] args) {
test_02();
}
private static void test_02() {
HashMap<Person,String> hashMap = new HashMap<>();
hashMap.put(new Person("小新",25),"南京");
hashMap.put(new Person("小月",21),"北京");
hashMap.put(new Person("小青",24),"天津");
hashMap.put(new Person("小新",25),"上海");
Set<Map.Entry<Person,String>> set = hashMap.entrySet();
for (Map.Entry<Person,String> entry:set) {
Person key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"--->"+value);
/* 没有重写Person时输出的结果:
Person{name='小新', age=25}--->南京
Person{name='小新', age=25}--->上海
Person{name='小青', age=24}--->天津
Person{name='小月', age=21}--->北京
*/
/* 重写Person时输出的结果:
Person{name='小月', age=21}--->北京
Person{name='小新', age=25}--->上海
Person{name='小青', age=24}--->天津
*/
}
}
}
2、LinkedHashMap
java.util.LinkedHashMap<k,v>
继承 HashMap<k,v>
类
特点:底层是哈希表 + 链表,保证迭代顺序;是一个有序集合;键值不允许重复。
import java.util.LinkedHashMap;
public class LinkedHashMapTest {
public static void main(String[] args) {
LinkedHashMap<String,String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("北京","天安门");
linkedHashMap.put("广州","小蛮腰");
linkedHashMap.put("西安","大雁搭");
linkedHashMap.put("北京","四合院");
System.out.println(linkedHashMap); //{北京=四合院, 广州=小蛮腰, 西安=大雁搭}
}
}
3、TreeMap
特点:实现 SortedMap 接口,可以对 Key 自动排序,底层为红黑树,用法与TreeSet类似
4、HashTable
特点:线程安全,运行效率慢,不允许 null 作为 Key 或 Value
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;
public class LinkedHashMapTest {
public static void main(String[] args) {
/*HashMap<String,String> hashMap = new HashMap<>();
hashMap.put("a",null);
hashMap.put(null,"b");
hashMap.put(null,null);
System.out.println(hashMap); //{null=null, a=null} */
Hashtable<String,String> hashtable = new Hashtable<>();
//hashtable.put("a",null); //java.lang.NullPointerException
//hashtable.put(null,"b"); //java.lang.NullPointerException
}
}
5、Properties
特点:HashTable 的子类,要求 Key 和 Value 都是String,通常用于配置文件的读取
JDK9的新特性:
- List接口, Set接口, Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多 个元素
static <E> List<E> of (E... elements )
- 使用前提:
当集合中存储的元素的个数已经确定了,不在改变时使用 - 注意:
- of方法只适用于List接口, Set接口,Map接口,不适用于接口的实现类
- of方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会抛出异常
- Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常
- 使用前提: