学习目录
一、Map 接口☆
1.基本介绍
Map 接口的关系图
Map 接口特点
- Map与Collection并列存在,用于保存具有映射关系的数据:Key-value键值对的形式
- Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node(静态内部类)对象中
- Map中的key不允许重复,Value可以重复,如果添加相同的key,则会替换掉原来的
- Map中的key可以是null,value也可以为null,key中的null只能有一个
- 常用String类作为Map的key
- key和value之间存在单向一对一关系,即通过key总能找到对应的value
- Map存放数据的key-value示意图,一对k-v是放在一个Node中的,因为Node实现了Entry接口,所以一对k-v就是一个Entry
通过实现类HashMap测试
import java.util.HashMap;
import java.util.Map;
class test1{
@SuppressWarnings({"all"})
public static void main(String[] args){
//特点1
Map map = new HashMap();
map.put(1,"tom"); //键值对
map.put(2,"juck");
System.out.println(map); //{1=tom, 2=juck}
//特点3
map.put(1,"小明");
System.out.println(map); //{1=小明, 2=juck}
//特点4
map.put(null,null);
System.out.println(map); //{null=null, 1=小明, 2=juck}
//特点5
map.put("java",1);
map.put(new String("python"),2);
System.out.println(map); //{null=null, 1=小明, 2=juck, python=2, java=1}
//特点6
System.out.println(map.get("java")); //1
System.out.println(map.get(1)); //小明
System.out.println(map.get("python")); //2
}
}
2.常用方法
方法名 | 功能 |
---|---|
put | 添加 |
remove | 删除 |
get | 根据键获取值 |
size | 获取元素个数 |
isEmpty | 判断个数是否为0 |
clear | 清除元素 |
containsKey | 查找键是否存在 |
3.遍历方法
- values():方法时获取集合中的所有的值
- KeySet():将Map中所有的键存入到set集合,KeySet只能通过get()获取key
- entrySet():Set<Map.Entry<K,V>> entrySet() //返回此映射中包含的映射关系的Set视图。Map.Entry表示映射关系。entrySet()取key,e.getValue()取value,返回的是Entry接口
“keySet是key的集合,Set…keySet()的速度比entrySet()慢了很多,使用entrySet则必须将map对象转换为Map.Entry,keySet则不需要。也就是keySet方式遍历Map的性能不如entrySet性能好 为了提高性能,以后多考虑用entry”
import java.util.*;
class test1{
@SuppressWarnings({"all"})
public static void main(String[] args){
Map map = new HashMap();
map.put(1,"java");
map.put(2,"scala");
map.put(3,"python");
map.put(4,"php");
//第一组把所有key取出,通过key取出对应的value
Set keySet = map.keySet();
//方式一:增强for
System.out.println("方式一");
for (Object key : keySet) {
System.out.println(key+"-"+map.get(key));
}
//方式二:迭代器
System.out.println("方式二");
Iterator iterator = keySet.iterator();
while (iterator.hasNext()){
Object key = iterator.next();
System.out.println(key+"-"+map.get(key));
}
//第二组:把所有的value取出来
Collection values = map.values();
//方式三:增强for
System.out.println("方式三");
for (Object value:values) {
System.out.println(value);
}
//方式四:迭代器
System.out.println("方式四");
Iterator iterator1 = values.iterator();
while (iterator1.hasNext()){
Object value = iterator1.next();
System.out.println(value);
}
//第三组: 通过 EntrySet 来获取 k-v
Set entrySet = map.entrySet();// EntrySet<Map.Entry<K,V>>
//方式五:增强for
System.out.println("方式五");
for (Object entry:entrySet) {
//将 entry 转成 Map.Entry
Map.Entry entry1 = (Map.Entry) entry; //向下转型
System.out.println(entry1.getKey()+"-"+entry1.getValue());
}
//方式六:迭代器
System.out.println("方式六");
Iterator iterator2 = entrySet.iterator();
while (iterator2.hasNext()){
Object entry = iterator2.next();
Map.Entry entry2 = (Map.Entry) entry; //向下转型
System.out.println(entry2.getKey()+"-"+entry2.getValue());
}
}
}
二、HashMap
基本介绍
- HashMap是Map接口使用频率最高的实现类
- HashMap是以k-v对的方式来存储数据
- key不能重复,但是值可以重复,允许使用null键和null值
- 如果添加相同的key,则会覆盖原来的key-value,即key保持不变,直接把value值修改了
- 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的
- HashMap没有实现同步,因此是线程不安全的
底层机制解析
- HashMap底层维护了Node类型的数组table,默认为null
- 当创建对象时,将加载因子loadFactor初始化为0.75
- 当添加键值对时,通过key的哈希值得到在table的索引值。然后判断是否有元素,如果没有直接添加;如果该索引处有元素,继续判断该元素的key是否和准备加入的key相等,如果相等,则直接替换value值,如果不相等,需要判断是树结构还是链表结构,做出相应的处理。如果添加时发现容量不够,则需要扩容。
底层扩容机制
扩容机制跟HashSet完全相同,因为HashSet底层是new HashMap
- 第一次添加是,table数组扩容到16,临界值是threshold为12,threshold=加载因子loadFactor为0.75*16=12
- 如果table数组使用到了临界值12,就会扩容到162 = 32,新的临界值= 320.75 = 24;以此类推
- 在java1.8中,如果一条链表的元素个数TREEIFY_THRESHOLD到达默认值8,索引大小MIN_TREEIFY_CAPACITY超过默认值64;则就会树化(红黑树)
三、Hashtable
基本介绍
- 存放元素是键值对
- Hashtable的k-v都不能为null,否则会抛出异常
- Hashtable使用方法和HashMap一样
- Hashtable是线程安全
1.Hashtable和HashMap对比
版本 | 线程安全(同步) | 效率 | k-v允许null | |
---|---|---|---|---|
HashMap | 1.2 | 不安全 | 高 | 可以 |
Hashtable | 1.0 | 安全 | 较低 | 不可以 |
四、Properties
基本介绍
- 存放元素是键值对
- 使用特点跟Hashtable类似
- Properties可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
xxx.properties文件常作为配置文件
五、开发中如何选择集合实现类☆
在开发中,选择什么集合实现类,主要取决于业务操作特点,然后根据集合实现类特点选择,分析如下:
(1)先判断存储类型(一组对象[底层维护了一个双向链表])
(2)一组对象[单列]:Collection接口
允许重复:List
增删多:LinkedList[底层维护了一个双向链表]
改查多:AaaryList[底层维护Object类型的可变数组]
不允许重复:Set
无序:HashSet[底层是HashMap,维护了一个哈希表 即(数组+链表+红黑树)]
排序:TreeSet
插入和取出顺序一致:LinkedHashSet,维护数组+双向链表
(3)一组键值对[双列]:Map
键无序:HashMap [底层是哈希表 即(数组+链表+红黑树)]
键排序:TreeMap
键插入和取出顺序一致:LinkedHashMap
读取文件:Properties
- 先判断存储类型(一组对象[底层维护了一个双向链表])
- 一组对象[单列]:Collection接口
六、Collections工具类
基本介绍
Collections是一个操作Set、List和Map等集合的工具类,提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,具体方法可以查看API
1.常用静态方法
方法名 | 功能 |
---|---|
reverse | 反转List中元素的顺序 |
shuffle | 对List集合元素进行随机排序,每次排序都不同 |
sort | 根据元素的自然顺序对指定的List集合元素按升序排序 |
sort(List,Comparator) | 根据指定的Comparator产生的顺序 对List集合元素进行排序 |
swap(List,int i,int j) | 将指定list集合中的i处元素和j处元素进行交换 |
max | 根据元素的自然顺序,返回给定集合中的最大元素 |
max(Collection,Comparator) | 根据Comparator指定顺序 |
min | 跟max同理 |
frequency | 返回指定集合中指定元素出现的次数 |
replaceAll(List list,Object oldVal,Object newVal) | 使用新值替换List对象的所有旧值 |
Comparator是一个匿名内部类,重写compare方法,在方法中编写自己需求的逻辑
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class test1{
@SuppressWarnings({"all"})
public static void main(String[] args){
System.out.println("-----list1-----");
ArrayList list1 = new ArrayList();
list1.add(5);
list1.add(6);
list1.add(1);
list1.add(9);
list1.add(6);
System.out.println(list1); //[5, 6, 1, 9, 6]
//reverse
Collections.reverse(list1);
System.out.println(list1); //[6, 9, 1, 6, 5]
//shuffle
Collections.shuffle(list1); //每次排序都不同
System.out.println(list1);
//sort
Collections.sort(list1);
System.out.println(list1); //[1, 5, 6, 6, 9]
//sort(List,Comparator)
Collections.sort(list1, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return (int)o2-(int)o1; //进行一个从大到小的排序
}
});
System.out.println(list1); //[9, 6, 6, 5, 1]
System.out.println("-----list2-----");
ArrayList list2 = new ArrayList();
list2.add("java");
list2.add("python");
list2.add("php");
list2.add("php");
System.out.println(list2); //[java, python, php, php]
//swap
Collections.swap(list2,1,2);
System.out.println(list2); //[java, php, python, php]
//max() //默认按照字符串长度取最大值
System.out.println(Collections.max(list2)); //python
//frequency
System.out.println(Collections.frequency(list2,"php")); //2
//replaceAll(List list,Object oldVal,Object newVal)
Collections.replaceAll(list2,"php","scala");
System.out.println(list2); //[java, scala, python, scala]
}
}