Map集合
现实生活中,我们常会看到这样的一种集合: IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一对应的关系 ,就叫做映射。Java提供了 专门的集合类用来存放这种对象关系的对象,即java.util.Map接口。javo.util.Map<k,v>集合
Map集合的特点:
- Map集合是一个双列集合, 一个元素包含两个值(一个key, 一个value)
- Map集合中的元素, key和value的数据类型可以相同,也可以不同
- Map集合中的元素, key是不允许重复的,value是可以重复的
- Map集合中的元素, key和value是一一对应
Map集合常用的方法:
public V put(K key, V value):把指定的键 与指定的值添加到Map集合中。
返回值:v
存储键值对的时候, key不重复,返回值V是null
存储键值对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value值
public V remove(0bject key): 把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值。
返回值:V
key存在, v返回被删除的值
key不存在, v返回null
public V get(Object key)根据指定的键,在Map集合中获取对应的值。
返回值:
key存在,返回对应的value值
key不存在,返回null
boolean containsKey(object key) 判断集合中是否包含指定的键。
包含返回true,不包含返回false
单列集合和双列集合的对比:
Collection中的集合,元素是孤立存在的(理解为单身) ,向集合中存储元素采用一个个元素的方式存储。Map中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。Collection中的集合称为单列集合. Map中的集合称为双列集合.需要注意的是,Map中的集合个能包含重复的键,值可以重复;每个键只能对应一个值。
Map集合遍历键找值方式:
键找值方式:即通过元素中的键,获取键所对应的值
分析步骤:
- 获取Map中所有的键,由于键是唯一的 ,所以返回一个Set集合存储所有的键。方法提示: keyset()
- 遍历键的Set集合,得到每一个键。
- 根据键,获取键所对应的值。方法提示: get(K key)
Entry键值对对象:
我们已经知道,Map 中存放的是两种对象, 一种称为key(键) , 一种称为value(值) ,它们在在Map中是一对应关系,这一对对象又称做Map中的一个Entry(项)。Entry 将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对 ( Entry )对象中获取对应的键与对应的值。
既然Entry表示了一对键和值,那么也同样提供了获取对应键和对应值得方法:
- public K getkey() :获取Entry对象中的键。
- public V getValue() :获取Entry对象中的值。
在Map集合中也提供了获取所有Entry对象的方法: - public Set<Map.Entry<K,V>> entryset() ;获取到Map集合中所有的键值对对象的集合(Set集合)。
Map集合遍历的第二种方式:使用Entry对象遍历
Map集合中的方法:
Set<Map. Entry<K,V>> entrySet() 返回此映射中包含的映射关系的Set视图。
实现步骤:
- 使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
- 遍历Set集合,获取每一个Entry对象
- 使用Entry对象中的方法getKey( )和getValue( )获取键与值
HashMap存储自定义类型键值:
Map集合保证key是唯一的:
作为key的元素,必须重写hoshCode方法和equals方法,以保证key唯一
-
key:String类型
String类重写hashCode方法和equals方法,可以保证key唯一
value:Person类型
value可以重复(同名同年龄的人视为同一个) -
key:Person类型
Person类就必须重写hashCode方法和equals方法,以保证key唯一
value:String类型
可以重复
Map集合常用子类—HashMap<K,V>
java. util .HashMap<k, v>集合implements Map<k, v>接口
- HashMap<K,V> :存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode(方法、equals()方法。
HashMap集合的特点:
- HoshMap集合底层是哈希表:查询的速度特别的快
JDK1. 8之前:数组+单向链表
JDK1. 8之后:数组+单向链表/红黑树(链表的长度超过8) :提高查询的速度 - hashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致
HashMap常用方法:
void clear() 从这个映射中移除所有的映射。
Object clone() 返回该 HashMap实例浅拷贝:键和值本身不是克隆。
boolean containsKey(Object key) 返回 true如果这Map包含一个指定的键映射。
boolean containsValue(Object value) 返回 true如果映射到指定的值的一个或多个键。
Set<Map.Entry<K,V>> entrySet() 返回一个 Set视图的映射包含在这个Map。
V get(Object key) 返回指定的键映射的值,或 null如果这个Map不包含的键映射。
boolean isEmpty() 返回 true如果这个Map不包含键值的映射。
Set<K> keySet() 返回一个 Set的关键视图包含在这个Map。
V put(K key, V value) 将指定的值与此映射中的指定键关联。
V remove(Object key) 如果存在的话,从这个映射中移除指定的键的映射。
boolean remove(Object key, Object value) 仅当它当前映射到指定的值时,为指定的键移除条目。
V replace(K key, V value) 仅当它当前映射到某一值时,替换指定的键的条目。
boolean replace(K key, V oldValue, V newValue) 仅当当前映射到指定的值时,替换指定的键的条目。
void replaceAll(BiFunction<? super K,? super V,? extends V> function) 将每个条目的值替换为在该项上调用给定函数的结果,直到所有的条目都被处理或函数抛出异常。
int size() 返回这个映射中的键值映射的数目。
Collection<V> values() 返回一个 Collection视图的值包含在这个Map。
HashMap常用方法以及四种遍历方式
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
//HashMap集合常用方法以及遍历方式
public class MapDemo {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(10,"hsz");
map.put(13,"han");
map.put(12,"hhh");
map.put(7,"hhh");
System.out.println(map.get(10));
System.out.println(map.remove(7));
System.out.println(map.containsKey(10));
System.out.println("===========================");
//方法一:代码简洁,效率高,推荐使用,常用
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
for (Map.Entry<Integer, String> entry : entrySet) {
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println(key+" "+value);
}
System.out.println("=========================");
//方法二:使用 for-each 循环遍历 key 或者 values,一般适用于只需要 Map 中的 key 或者 value 时使用。
//打印键集合
for (Integer key : map.keySet()) {
System.out.println(key);
}
//打印值集合
for (String value : map.values()) {
System.out.println(value);
}
System.out.println("============================");
//方法三:通过键找值遍历,这种方式的效率比较低,因为本身从键取值是耗时的操作。
for (Integer key : map.keySet()) {
String value = map.get(key);
System.out.println(key+":"+value);
}
System.out.println("============================");
//方法四:使用迭代器(Iterator)遍历:当遍历的时候,如果涉及到删除操作,建议使用Iterator的remove方法,因为如果使用foreach的话会报错。
Iterator<Map.Entry<Integer, String>> entries = map.entrySet().iterator();
while (entries.hasNext()){
Map.Entry<Integer, String> entry = entries.next();
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println(key+":"+value);
}
}
}
HashMap底层实现原理及面试问题
HashMap底层实现原理及面试问题
深入浅出学Java——HashMap
Map集合常用子类—LinkedHashMap<K,V>
java. util. LinkedHashMap<k,v>集合extends HashMap<k, v>集合
LinkedHashMap<K,V> : HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复 ,需要重写键的hashCode(方法、equals()方法。
LinkedHashMap的特点:
- LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
- LinkedHashMap集合是一个有序的集合 ,存储元素和职出元素的顺序是一致的
Hashtable集合
java. util . Hashtable<K, V>集合implements Map<K, V>接口
Hashtable:底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快
HashMap集合(之前学的所有的集合):可以存储null值, null键
Hashtable集合,不能存储null值, null键
Hashtable和Vector集合一样 ,在jdk1. 2版本之后被更先进的集合(HashMap, Arraylist)取代了
Hashtable的子类Properties依然活跃在历史舞台
Properties集合是一个唯一和I0流相结合的集合
Properties集合
概述
java.util.Properties 继承于Hashtable ,来表示一个持久的属性集。它使用键值结构存储数据,每个键及其对应值都是一个字符串。该类也被许多Java类使用,比如获取系统属性时,System.getProperties 方法就是返回一个Properties对象。
Properties类
构造方法
public Properties() :创建一个空的属性列表。
基本的存储方法
public Object setProperty(String key, String value) : 保存一对属性。
public String getProperty(String key) :使用此属性列表中指定的键搜索属性值。
public Set<String> stringPropertyNames() :所有键的名称的集合
public class ProDemo {
public static void main(String[] args) throws FileNotFoundException {
// 创建属性集对象
Properties properties = new Properties();
// 添加键值对元素
properties.setProperty("filename", "a.txt");
properties.setProperty("length", "209385038");
properties.setProperty("location", "D:\\a.txt");
// 打印属性集对象
System.out.println(properties);
// 通过键,获取属性值
System.out.println(properties.getProperty("filename"));
System.out.println(properties.getProperty("length"));
System.out.println(properties.getProperty("location"));
// 遍历属性集,获取所有键的集合
Set<String> strings = properties.stringPropertyNames();
// 打印键值对
for (String key : strings ) {
System.out.println(key+" -- "+properties.getProperty(key));
}
}
}
输出结果:
{filename=a.txt, length=209385038, location=D:\a.txt}
a.txt
209385038
D:\a.txt
filename -- a.txt
length -- 209385038
location -- D:\a.txt
与流相关的方法
public void load(InputStream inStream): 从字节输入流中读取键值对。
参数中使用了字节输入流,通过流对象,可以关联到某文件上,这样就能够加载文本中的数据了。文本数据格式:
filename=a.txt
length=209385038
location=D:\a.txt
加载代码演示:
public class ProDemo2 {
public static void main(String[] args) throws FileNotFoundException {
// 创建属性集对象
Properties pro = new Properties();
// 加载文本中信息到属性集
pro.load(new FileInputStream("read.txt"));
// 遍历集合并打印
Set<String> strings = pro.stringPropertyNames();
for (String key : strings ) {
System.out.println(key+" -- "+pro.getProperty(key));
}
}
}
输出结果:
filename -- a.txt
length -- 209385038
location -- D:\a.txt
小贴士:文本中的数据,必须是键值对形式,可以使用空格、等号、冒号等符号分隔。